## প্রয়োজনীয়তা এই পাঠে আমরা **OpenAI Gym** নামক একটি লাইব্রেরি ব্যবহার করব বিভিন্ন **পরিবেশ** সিমুলেট করার জন্য। আপনি যদি এই পাঠের কোড স্থানীয়ভাবে (যেমন Visual Studio Code থেকে) চালান, তাহলে সিমুলেশনটি একটি নতুন উইন্ডোতে খুলবে। অনলাইনে কোড চালানোর সময়, আপনাকে কোডে কিছু পরিবর্তন করতে হতে পারে, যেমনটি [এখানে](https://towardsdatascience.com/rendering-openai-gym-envs-on-binder-and-google-colab-536f99391cc7) বর্ণনা করা হয়েছে। ## OpenAI Gym পূর্ববর্তী পাঠে, খেলার নিয়ম এবং অবস্থান আমরা নিজেরাই সংজ্ঞায়িত `Board` ক্লাসের মাধ্যমে দিয়েছিলাম। এখানে আমরা একটি বিশেষ **সিমুলেশন পরিবেশ** ব্যবহার করব, যা ভারসাম্য রক্ষার জন্য পোলের পিছনের পদার্থবিদ্যা সিমুলেট করবে। রিইনফোর্সমেন্ট লার্নিং অ্যালগরিদম প্রশিক্ষণের জন্য সবচেয়ে জনপ্রিয় সিমুলেশন পরিবেশগুলির মধ্যে একটি হল [Gym](https://gym.openai.com/), যা [OpenAI](https://openai.com/) দ্বারা রক্ষণাবেক্ষণ করা হয়। এই Gym ব্যবহার করে আমরা বিভিন্ন **পরিবেশ** তৈরি করতে পারি, যেমন CartPole সিমুলেশন থেকে Atari গেমস। > **Note**: OpenAI Gym থেকে অন্যান্য উপলব্ধ পরিবেশগুলি আপনি [এখানে](https://gym.openai.com/envs/#classic_control) দেখতে পারেন। প্রথমে Gym ইনস্টল করুন এবং প্রয়োজনীয় লাইব্রেরিগুলি ইমপোর্ট করুন (কোড ব্লক 1): ```python import sys !{sys.executable} -m pip install gym import gym import matplotlib.pyplot as plt import numpy as np import random ``` ## অনুশীলন - একটি CartPole পরিবেশ ইনিশিয়ালাইজ করুন CartPole ভারসাম্য সমস্যার সাথে কাজ করতে, আমাদের সংশ্লিষ্ট পরিবেশ ইনিশিয়ালাইজ করতে হবে। প্রতিটি পরিবেশের সাথে যুক্ত থাকে: - **Observation space**, যা পরিবেশ থেকে প্রাপ্ত তথ্যের গঠন সংজ্ঞায়িত করে। CartPole সমস্যার ক্ষেত্রে, আমরা পোলের অবস্থান, গতি এবং অন্যান্য কিছু মান পাই। - **Action space**, যা সম্ভাব্য ক্রিয়াগুলি সংজ্ঞায়িত করে। আমাদের ক্ষেত্রে Action space ডিসক্রিট, এবং দুটি ক্রিয়া নিয়ে গঠিত - **বাম** এবং **ডান**। (কোড ব্লক 2) 1. ইনিশিয়ালাইজ করতে, নিম্নলিখিত কোড টাইপ করুন: ```python env = gym.make("CartPole-v1") print(env.action_space) print(env.observation_space) print(env.action_space.sample()) ``` পরিবেশটি কীভাবে কাজ করে তা দেখতে, 100 ধাপের জন্য একটি ছোট সিমুলেশন চালান। প্রতিটি ধাপে, আমরা একটি ক্রিয়া প্রদান করি যা নেওয়া হবে - এই সিমুলেশনে আমরা `action_space` থেকে এলোমেলোভাবে একটি ক্রিয়া নির্বাচন করি। 1. নিচের কোডটি চালান এবং এটি কী ফলাফল দেয় তা দেখুন। ✅ মনে রাখবেন যে এই কোডটি স্থানীয় Python ইনস্টলেশনে চালানো পছন্দনীয়! (কোড ব্লক 3) ```python env.reset() for i in range(100): env.render() env.step(env.action_space.sample()) env.close() ``` আপনি এরকম একটি চিত্র দেখতে পাবেন: ![non-balancing cartpole](../../../../8-Reinforcement/2-Gym/images/cartpole-nobalance.gif) 1. সিমুলেশনের সময়, আমাদের সিদ্ধান্ত নিতে পর্যবেক্ষণগুলি পেতে হবে। প্রকৃতপক্ষে, `step` ফাংশন বর্তমান পর্যবেক্ষণ, একটি রিওয়ার্ড ফাংশন এবং `done` ফ্ল্যাগ প্রদান করে যা নির্দেশ করে যে সিমুলেশন চালিয়ে যাওয়া যুক্তিযুক্ত কিনা: (কোড ব্লক 4) ```python env.reset() done = False while not done: env.render() obs, rew, done, info = env.step(env.action_space.sample()) print(f"{obs} -> {rew}") env.close() ``` আপনি নোটবুক আউটপুটে এরকম কিছু দেখতে পাবেন: ```text [ 0.03403272 -0.24301182 0.02669811 0.2895829 ] -> 1.0 [ 0.02917248 -0.04828055 0.03248977 0.00543839] -> 1.0 [ 0.02820687 0.14636075 0.03259854 -0.27681916] -> 1.0 [ 0.03113408 0.34100283 0.02706215 -0.55904489] -> 1.0 [ 0.03795414 0.53573468 0.01588125 -0.84308041] -> 1.0 ... [ 0.17299878 0.15868546 -0.20754175 -0.55975453] -> 1.0 [ 0.17617249 0.35602306 -0.21873684 -0.90998894] -> 1.0 ``` সিমুলেশনের প্রতিটি ধাপে ফেরত দেওয়া পর্যবেক্ষণ ভেক্টরটি নিম্নলিখিত মানগুলি ধারণ করে: - কার্টের অবস্থান - কার্টের গতি - পোলের কোণ - পোলের ঘূর্ণন হার 1. এই সংখ্যাগুলির সর্বনিম্ন এবং সর্বাধিক মান পান: (কোড ব্লক 5) ```python print(env.observation_space.low) print(env.observation_space.high) ``` আপনি লক্ষ্য করতে পারেন যে প্রতিটি সিমুলেশন ধাপে রিওয়ার্ড মান সর্বদা 1। এর কারণ আমাদের লক্ষ্য যতটা সম্ভব দীর্ঘ সময় ধরে টিকে থাকা, অর্থাৎ পোলটিকে একটি যুক্তিসঙ্গতভাবে উল্লম্ব অবস্থানে দীর্ঘ সময় ধরে রাখা। ✅ প্রকৃতপক্ষে, CartPole সিমুলেশন সমাধান করা হয়েছে বলে বিবেচিত হয় যদি আমরা 100 ধারাবাহিক ট্রায়ালের উপর গড় রিওয়ার্ড 195 অর্জন করতে পারি। ## অবস্থার ডিসক্রিটাইজেশন Q-Learning-এ, আমাদের একটি Q-Table তৈরি করতে হবে যা প্রতিটি অবস্থায় কী করতে হবে তা সংজ্ঞায়িত করে। এটি করতে, আমাদের অবস্থান **ডিসক্রিট** হতে হবে, আরও স্পষ্টভাবে, এটি একটি সীমিত সংখ্যক ডিসক্রিট মান ধারণ করতে হবে। তাই, আমাদের পর্যবেক্ষণগুলিকে **ডিসক্রিটাইজ** করতে হবে, তাদের একটি সীমিত সেটের সাথে মানচিত্র করতে হবে। এটি করার কয়েকটি উপায় রয়েছে: - **বিনে ভাগ করুন**। যদি আমরা একটি নির্দিষ্ট মানের পরিসর জানি, আমরা এই পরিসরটিকে একটি নির্দিষ্ট সংখ্যক **বিনে** ভাগ করতে পারি এবং তারপর মানটিকে সেই বিন নম্বর দ্বারা প্রতিস্থাপন করতে পারি যেখানে এটি অন্তর্ভুক্ত। এটি numpy [`digitize`](https://numpy.org/doc/stable/reference/generated/numpy.digitize.html) পদ্ধতি ব্যবহার করে করা যেতে পারে। এই ক্ষেত্রে, আমরা সঠিকভাবে অবস্থার আকার জানব, কারণ এটি ডিজিটালাইজেশনের জন্য নির্বাচিত বিনের সংখ্যার উপর নির্ভর করবে। ✅ আমরা লিনিয়ার ইন্টারপোলেশন ব্যবহার করে মানগুলিকে একটি সীমিত পরিসরে (যেমন, -20 থেকে 20) আনতে পারি এবং তারপর সংখ্যাগুলিকে রাউন্ডিং করে পূর্ণসংখ্যায় রূপান্তর করতে পারি। এটি আমাদের অবস্থার আকারের উপর কিছুটা কম নিয়ন্ত্রণ দেয়, বিশেষত যদি আমরা ইনপুট মানগুলির সঠিক পরিসর না জানি। উদাহরণস্বরূপ, আমাদের ক্ষেত্রে 4টির মধ্যে 2টি মানের উপরের/নিচের সীমা নেই, যা সীমাহীন সংখ্যক অবস্থার ফলস্বরূপ হতে পারে। আমাদের উদাহরণে, আমরা দ্বিতীয় পদ্ধতির সাথে যাব। আপনি পরে লক্ষ্য করতে পারেন, অজানা উপরের/নিচের সীমা থাকা সত্ত্বেও, এই মানগুলি খুব কমই নির্দিষ্ট সীমিত পরিসরের বাইরে মান নেয়, তাই চরম মান সহ অবস্থাগুলি খুব বিরল হবে। 1. এখানে একটি ফাংশন রয়েছে যা আমাদের মডেল থেকে পর্যবেক্ষণ গ্রহণ করবে এবং 4টি পূর্ণসংখ্যার মানের একটি টুপল তৈরি করবে: (কোড ব্লক 6) ```python def discretize(x): return tuple((x/np.array([0.25, 0.25, 0.01, 0.1])).astype(np.int)) ``` 1. বিন ব্যবহার করে আরেকটি ডিসক্রিটাইজেশন পদ্ধতি অন্বেষণ করুন: (কোড ব্লক 7) ```python def create_bins(i,num): return np.arange(num+1)*(i[1]-i[0])/num+i[0] print("Sample bins for interval (-5,5) with 10 bins\n",create_bins((-5,5),10)) ints = [(-5,5),(-2,2),(-0.5,0.5),(-2,2)] # intervals of values for each parameter nbins = [20,20,10,10] # number of bins for each parameter bins = [create_bins(ints[i],nbins[i]) for i in range(4)] def discretize_bins(x): return tuple(np.digitize(x[i],bins[i]) for i in range(4)) ``` 1. এখন একটি ছোট সিমুলেশন চালান এবং সেই ডিসক্রিট পরিবেশের মানগুলি পর্যবেক্ষণ করুন। `discretize` এবং `discretize_bins` উভয়ই চেষ্টা করুন এবং পার্থক্য আছে কিনা তা দেখুন। ✅ `discretize_bins` বিন নম্বর ফেরত দেয়, যা 0-ভিত্তিক। তাই ইনপুট ভেরিয়েবলের মান 0-এর কাছাকাছি থাকলে এটি পরিসরের মাঝখান থেকে একটি সংখ্যা (10) ফেরত দেয়। `discretize`-এ, আমরা আউটপুট মানগুলির পরিসরের বিষয়ে চিন্তা করিনি, তাদের নেতিবাচক হতে দিয়েছি, তাই অবস্থার মানগুলি স্থানান্তরিত হয়নি এবং 0 মানে 0। (কোড ব্লক 8) ```python env.reset() done = False while not done: #env.render() obs, rew, done, info = env.step(env.action_space.sample()) #print(discretize_bins(obs)) print(discretize(obs)) env.close() ``` ✅ পরিবেশটি কীভাবে কার্যকর হয় তা দেখতে `env.render` দিয়ে শুরু হওয়া লাইনটি আনকমেন্ট করুন। অন্যথায় আপনি এটি ব্যাকগ্রাউন্ডে কার্যকর করতে পারেন, যা দ্রুত। আমরা আমাদের Q-Learning প্রক্রিয়ার সময় এই "অদৃশ্য" কার্যকরকরণ ব্যবহার করব। ## Q-Table এর গঠন পূর্ববর্তী পাঠে, অবস্থাটি 0 থেকে 8 পর্যন্ত সংখ্যার একটি সাধারণ জোড়া ছিল, এবং তাই এটি একটি numpy টেনসর দ্বারা Q-Table উপস্থাপন করা সুবিধাজনক ছিল যার আকৃতি ছিল 8x8x2। যদি আমরা বিন ডিসক্রিটাইজেশন ব্যবহার করি, আমাদের অবস্থান ভেক্টরের আকারও জানা যায়, তাই আমরা একই পদ্ধতি ব্যবহার করতে পারি এবং অবস্থানটিকে একটি অ্যারের আকার 20x20x10x10x2 দ্বারা উপস্থাপন করতে পারি (এখানে 2 হল Action space-এর মাত্রা, এবং প্রথম মাত্রাগুলি পর্যবেক্ষণ স্পেসে প্রতিটি প্যারামিটারের জন্য ব্যবহৃত বিনের সংখ্যার সাথে সম্পর্কিত)। তবে, কখনও কখনও পর্যবেক্ষণ স্পেসের সঠিক মাত্রা জানা যায় না। `discretize` ফাংশনের ক্ষেত্রে, আমরা কখনই নিশ্চিত হতে পারি না যে আমাদের অবস্থান নির্দিষ্ট সীমার মধ্যে থাকে, কারণ কিছু মূল মান সীমাবদ্ধ নয়। তাই, আমরা একটি সামান্য ভিন্ন পদ্ধতি ব্যবহার করব এবং Q-Table একটি ডিকশনারি দ্বারা উপস্থাপন করব। 1. *(state,action)* জোড়াকে ডিকশনারি কী হিসাবে ব্যবহার করুন, এবং মানটি Q-Table এন্ট্রি মানের সাথে সম্পর্কিত হবে। (কোড ব্লক 9) ```python Q = {} actions = (0,1) def qvalues(state): return [Q.get((state,a),0) for a in actions] ``` এখানে আমরা একটি ফাংশন `qvalues()` সংজ্ঞায়িত করি, যা একটি প্রদত্ত অবস্থার জন্য Q-Table মানগুলির একটি তালিকা ফেরত দেয় যা সমস্ত সম্ভাব্য ক্রিয়াগুলির সাথে সম্পর্কিত। যদি এন্ট্রি Q-Table-এ উপস্থিত না থাকে, আমরা ডিফল্ট হিসাবে 0 ফেরত দেব। ## আসুন Q-Learning শুরু করি এখন আমরা পিটারকে ভারসাম্য রক্ষা করতে শেখানোর জন্য প্রস্তুত! 1. প্রথমে কিছু হাইপারপ্যারামিটার সেট করুন: (কোড ব্লক 10) ```python # hyperparameters alpha = 0.3 gamma = 0.9 epsilon = 0.90 ``` এখানে, `alpha` হল **learning rate**, যা সংজ্ঞায়িত করে যে প্রতিটি ধাপে Q-Table এর বর্তমান মানগুলি আমরা কতটা সমন্বয় করব। পূর্ববর্তী পাঠে আমরা 1 দিয়ে শুরু করেছি এবং প্রশিক্ষণের সময় `alpha`-কে কম মানগুলিতে কমিয়েছি। এই উদাহরণে আমরা এটি স্থির রাখব শুধুমাত্র সরলতার জন্য, এবং আপনি পরে `alpha` মানগুলি সামঞ্জস্য করার সাথে পরীক্ষা করতে পারেন। `gamma` হল **discount factor**, যা দেখায় যে আমরা বর্তমান রিওয়ার্ডের তুলনায় ভবিষ্যতের রিওয়ার্ডকে কতটা অগ্রাধিকার দেব। `epsilon` হল **exploration/exploitation factor**, যা নির্ধারণ করে যে আমরা অনুসন্ধানকে শোষণের তুলনায় বেশি পছন্দ করব কিনা বা এর বিপরীত। আমাদের অ্যালগরিদমে, আমরা `epsilon` শতাংশ ক্ষেত্রে Q-Table মান অনুযায়ী পরবর্তী ক্রিয়া নির্বাচন করব, এবং বাকি সংখ্যক ক্ষেত্রে আমরা একটি এলোমেলো ক্রিয়া কার্যকর করব। এটি আমাদের অনুসন্ধান স্পেসের এমন এলাকাগুলি অন্বেষণ করতে দেবে যা আমরা আগে কখনও দেখিনি। ✅ ভারসাম্যের ক্ষেত্রে - এলোমেলো ক্রিয়া (অনুসন্ধান) নির্বাচন করা ভুল দিকে একটি এলোমেলো ধাক্কার মতো কাজ করবে, এবং পোলটি এই "ভুলগুলি" থেকে ভারসাম্য পুনরুদ্ধার করতে শিখতে হবে। ### অ্যালগরিদম উন্নত করুন আমরা পূর্ববর্তী পাঠ থেকে আমাদের অ্যালগরিদমে দুটি উন্নতি করতে পারি: - **গড় সামগ্রিক রিওয়ার্ড গণনা করুন**, একটি নির্দিষ্ট সংখ্যক সিমুলেশনের উপর। আমরা প্রতি 5000 পুনরাবৃত্তিতে আমাদের অগ্রগতি প্রিন্ট করব এবং আমরা সেই সময়ের মধ্যে আমাদের সামগ্রিক রিওয়ার্ড গড় করব। এর মানে হল যে যদি আমরা 195 পয়েন্টের বেশি পাই - আমরা সমস্যাটি সমাধান হয়েছে বলে বিবেচনা করতে পারি, এমনকি প্রয়োজনীয় মানের চেয়েও বেশি মানের সাথে। - **সর্বাধিক গড় সামগ্রিক ফলাফল গণনা করুন**, `Qmax`, এবং আমরা সেই ফলাফলের সাথে সম্পর্কিত Q-Table সংরক্ষণ করব। যখন আপনি প্রশিক্ষণ চালান তখন আপনি লক্ষ্য করবেন যে কখনও কখনও গড় সামগ্রিক ফলাফল কমতে শুরু করে, এবং আমরা Q-Table এর মানগুলি রাখতে চাই যা প্রশিক্ষণের সময় পর্যবেক্ষণ করা সেরা মডেলের সাথে সম্পর্কিত। 1. প্রতিটি সিমুলেশনে সমস্ত সামগ্রিক রিওয়ার্ড `rewards` ভেক্টরে সংগ্রহ করুন ভবিষ্যতে প্লট করার জন্য। (কোড ব্লক 11) ```python def probs(v,eps=1e-4): v = v-v.min()+eps v = v/v.sum() return v Qmax = 0 cum_rewards = [] rewards = [] for epoch in range(100000): obs = env.reset() done = False cum_reward=0 # == do the simulation == while not done: s = discretize(obs) if random.random() Qmax: Qmax = np.average(cum_rewards) Qbest = Q cum_rewards=[] ``` এই ফলাফলগুলি থেকে আপনি যা লক্ষ্য করতে পারেন: - **আমাদের লক্ষ্য কাছাকাছি**। আমরা 100+ ধারাবাহিক সিমুলেশনের উপর 195 সামগ্রিক রিওয়ার্ড অর্জনের লক্ষ্য অর্জনের খুব কাছাকাছি, বা আমরা প্রকৃতপক্ষে এটি অর্জন করেছি! এমনকি যদি আমরা ছোট সংখ্যা পাই, আমরা এখনও জানি না, কারণ আমরা 5000 রান গড় করি, এবং আনুষ্ঠানিক মানদণ্ডে শুধুমাত্র 100 রান প্রয়োজন। - **রিওয়ার্ড কমতে শুরু করে**। কখনও কখনও রিওয়ার্ড কমতে শুরু করে, যার অর্থ আমরা Q-Table-এ ইতিমধ্যে শেখা মানগুলি "ধ্বংস" করতে পারি এমন মানগুলির সাথে যা পরিস্থিতিকে আরও খারাপ করে তোলে। এই পর্যবেক্ষণটি আরও স্পষ্টভাবে দৃশ্যমান হয় যদি আমরা প্রশিক্ষণের অগ্রগতি প্লট করি। ## প্রশিক্ষণের অগ্রগতি প্লট করা প্রশিক্ষণের সময়, আমরা প্রতিটি পুনরাবৃত্তিতে সামগ্রিক রিওয়ার্ড মান `rewards` ভেক্টরে সংগ্রহ করেছি। এটি পুনরাবৃত্তি সংখ্যার বিপরীতে প্লট করলে এটি দেখতে কেমন: ```python plt.plot(rewards) ``` ![raw progress](../../../../8-Reinforcement/2-Gym/images/train_progress_raw.png) এই গ্রাফ থেকে কিছু বলা সম্ভব নয়, কারণ স্টোকাস্টিক প্রশিক্ষণ প্রক্রিয়ার প্রকৃতির কারণে প্রশিক্ষণ সেশনের দৈর্ঘ্য ব্যাপকভাবে পরিবর্তিত হয়। এই গ্রাফটি আরও অর্থবহ করতে, আমরা 100টি পরীক্ষার উপর **running average** গণনা করতে পারি। এটি সুবিধামত `np.convolve` ব্যবহার করে করা যেতে পারে: (কোড ব্লক 12) ```python def running_average(x,window): return np.convolve(x,np.ones(window)/window,mode='valid') plt.plot(running_average(rewards,100)) ``` ![training progress](../../../../8-Reinforcement/2-Gym/images/train_progress_runav.png) ## হাইপারপ্যারামিটার পরিবর্তন করা শিক্ষণ আরও স্থিতিশীল করতে, প্রশিক্ষণের সময় আমাদের কিছু হাইপারপ্যারামিটার সামঞ্জস্য করা বুদ্ধিমানের কাজ। বিশেষত: - **শিক্ষণ হার**, `alpha`, আমরা 1-এর কাছাকাছি মান দিয়ে শুরু করতে পারি এবং তারপর প্যারামিটারটি কমিয়ে রাখতে পারি। সময়ের সাথে সাথে, আমরা Q-Table-এ ভাল সম্ভাব্য মান পাব, এবং তাই আমাদের তাদের সামান্য সামঞ্জস্য করা উচিত এবং নতুন মানগুলির সাথে সম্পূর্ণভাবে ওভাররাইট করা উচিত নয়। - **epsilon বৃদ্ধি করুন**। আমরা `epsilon` ধীরে ধীরে বৃদ্ধি করতে চাই, যাতে কম অনুসন্ধান এবং বেশি শোষণ করা যায়। সম্ভবত এটি কম `epsilon` মান দিয়ে শুরু করা এবং প্রায় 1 পর্যন্ত নিয়ে যাওয়া বুদ্ধিমানের কাজ। > **টাস্ক ১**: হাইপারপ্যারামিটার মানগুলোর সাথে পরীক্ষা করুন এবং দেখুন আপনি কি উচ্চতর সামগ্রিক পুরস্কার অর্জন করতে পারেন। আপনি কি ১৯৫ এর উপরে পাচ্ছেন? > **টাস্ক ২**: সমস্যাটি আনুষ্ঠানিকভাবে সমাধান করতে, আপনাকে ১০০ ধারাবাহিক রান জুড়ে ১৯৫ গড় পুরস্কার অর্জন করতে হবে। প্রশিক্ষণের সময় এটি পরিমাপ করুন এবং নিশ্চিত করুন যে আপনি সমস্যাটি আনুষ্ঠানিকভাবে সমাধান করেছেন! ## ফলাফল কার্যকরভাবে দেখা প্রশিক্ষিত মডেলটি কীভাবে আচরণ করে তা দেখা বেশ আকর্ষণীয় হবে। চলুন সিমুলেশন চালাই এবং প্রশিক্ষণের সময় ব্যবহৃত একই অ্যাকশন নির্বাচন কৌশল অনুসরণ করি, Q-টেবিলের সম্ভাব্যতা বিতরণ অনুযায়ী নমুনা করি: (কোড ব্লক ১৩) ```python obs = env.reset() done = False while not done: s = discretize(obs) env.render() v = probs(np.array(qvalues(s))) a = random.choices(actions,weights=v)[0] obs,_,done,_ = env.step(a) env.close() ``` আপনার কিছুটা এরকম দেখতে পাওয়া উচিত: ![একটি ব্যালেন্সিং কার্টপোল](../../../../8-Reinforcement/2-Gym/images/cartpole-balance.gif) --- ## 🚀চ্যালেঞ্জ > **টাস্ক ৩**: এখানে আমরা Q-টেবিলের চূড়ান্ত কপি ব্যবহার করছিলাম, যা হয়তো সেরা নাও হতে পারে। মনে রাখবেন যে আমরা `Qbest` ভেরিয়েবলে সেরা পারফর্মিং Q-টেবিল সংরক্ষণ করেছি! `Qbest`-কে `Q`-তে কপি করে একই উদাহরণ চেষ্টা করুন এবং পার্থক্য লক্ষ্য করুন। > **টাস্ক ৪**: এখানে আমরা প্রতিটি ধাপে সেরা অ্যাকশন নির্বাচন করছিলাম না, বরং সংশ্লিষ্ট সম্ভাব্যতা বিতরণ দিয়ে নমুনা করছিলাম। সর্বোচ্চ Q-টেবিল মান সহ সর্বদা সেরা অ্যাকশন নির্বাচন করা কি আরও অর্থবহ হবে? এটি `np.argmax` ফাংশন ব্যবহার করে করা যেতে পারে, যা সর্বোচ্চ Q-টেবিল মানের সাথে সম্পর্কিত অ্যাকশন নম্বর খুঁজে বের করে। এই কৌশলটি বাস্তবায়ন করুন এবং দেখুন এটি ব্যালেন্সিং উন্নত করে কিনা। ## [পোস্ট-লেকচার কুইজ](https://ff-quizzes.netlify.app/en/ml/) ## অ্যাসাইনমেন্ট [একটি মাউন্টেন কার প্রশিক্ষণ দিন](assignment.md) ## উপসংহার আমরা এখন শিখেছি কীভাবে এজেন্টদের প্রশিক্ষণ দিয়ে ভালো ফলাফল অর্জন করা যায়, শুধুমাত্র একটি পুরস্কার ফাংশন প্রদান করে যা গেমের কাঙ্ক্ষিত অবস্থাকে সংজ্ঞায়িত করে এবং তাদের বুদ্ধিমত্তার সাথে অনুসন্ধান স্থানটি অন্বেষণ করার সুযোগ দিয়ে। আমরা সফলভাবে Q-লার্নিং অ্যালগরিদম প্রয়োগ করেছি ডিসক্রিট এবং কন্টিনিউয়াস পরিবেশের ক্ষেত্রে, তবে ডিসক্রিট অ্যাকশন সহ। এটি গুরুত্বপূর্ণ যে আমরা এমন পরিস্থিতি অধ্যয়ন করি যেখানে অ্যাকশন স্টেটও কন্টিনিউয়াস এবং পর্যবেক্ষণ স্থান অনেক বেশি জটিল, যেমন অ্যাটারি গেম স্ক্রিনের চিত্র। এই ধরনের সমস্যাগুলিতে ভালো ফলাফল অর্জনের জন্য প্রায়ই আরও শক্তিশালী মেশিন লার্নিং কৌশল, যেমন নিউরাল নেটওয়ার্ক, ব্যবহার করতে হয়। এই আরও উন্নত বিষয়গুলি আমাদের আসন্ন উন্নত AI কোর্সের বিষয়। --- **অস্বীকৃতি**: এই নথিটি AI অনুবাদ পরিষেবা [Co-op Translator](https://github.com/Azure/co-op-translator) ব্যবহার করে অনুবাদ করা হয়েছে। আমরা যথাসম্ভব সঠিক অনুবাদ প্রদানের চেষ্টা করি, তবে অনুগ্রহ করে মনে রাখবেন যে স্বয়ংক্রিয় অনুবাদে ত্রুটি বা অসঙ্গতি থাকতে পারে। মূল ভাষায় থাকা নথিটিকে প্রামাণিক উৎস হিসেবে বিবেচনা করা উচিত। গুরুত্বপূর্ণ তথ্যের জন্য, পেশাদার মানব অনুবাদ সুপারিশ করা হয়। এই অনুবাদ ব্যবহারের ফলে কোনো ভুল বোঝাবুঝি বা ভুল ব্যাখ্যা হলে আমরা তার জন্য দায়ী থাকব না।