# CartPole Skating បញ្ហាដែលយើងបានដោះស្រាយនៅមេរៀនមុនអាចនិយាយថាជាបញ្ហា​គន្លងលេង មិនពិតជាអាចប្រើប្រាស់បានសម្រាប់សេណារីយ៉ូជីវិតពិតទេ។ វាមិនមែនបែបនោះទេ ព្រោះបញ្ហាជីវិតពិតជាច្រើនក៍មានស្ថានភាពដូចគ្នានេះ សូម្បីតែការលេង Chess ឬ Go។ ពួកវាស្រដៀងគ្នា ព្រោះយើងក៏មានក្តារដូកជាមួយនឹងច្បាប់ផ្តល់ជូនហើយមាន **ស្ថានភាពប្រភេទដាច់**។ ## [Pre-lecture quiz](https://ff-quizzes.netlify.app/en/ml/) ## មុខជំនួញ នៅមេរៀននេះ យើងនឹងអនុវត្តគោលការណ៍ Q-Learning ដូចគ្នាទៅលើបញ្ហាមួយ ដែលមាន **ស្ថានភាពតាប់បន្ត** មានន័យថា ស្ថានភាពត្រូវបានផ្តល់ដោយចំនួនពិតមួយឬច្រើនជាងមួយ។ យើងនឹងដោះស្រាយបញ្ហាតទៅនេះ៖ > **បញ្ហា**៖ ប្រសិនបើ Peter ចង់គេចចេញពីខ្លា គាត់ត្រូវតែអាចចល័តបានលឿនជាងមុន។ យើងនឹងមើលថា Peter អាចរៀនលេងស្គេតបានយ៉ាងដូចម្តេច ជាពិសេស ដើម្បីរក្សាសមតុល្យ ដោយប្រើ Q-Learning។ ![The great escape!](../../../../translated_images/km/escape.18862db9930337e3.webp) > Peter និងមិត្តភក្តិរបស់គាត់បានប្រើិតច្នៃប្រឌិតដើម្បីគេចខ្លាចខ្លា! រូបភាពដោយ [Jen Looper](https://twitter.com/jenlooper) យើងនឹងប្រើកំណែមួយសាមញ្ញនៃការរក្សាសមតុល្យដែលហៅថា **បញ្ហា CartPole**។ នៅក្នុងពិភព cartpole យើងមានស្លាយទ្រនិចមួយអាចផ្លាស់ទីទៅឆ្វេង ឬស្ដាំ ហើយគោលបំណងគឺរក្សាដើមដេកបញ្ឈរត្រង់លើស្លាយ។ a cartpole ## ការត្រៀមមុន នៅមេរៀននេះ យើងនឹងប្រើបណ្ណាល័យមួយហៅថា **OpenAI Gym** ដើម្បីសម្រួលបរិយាកាសផ្សេងៗគ្នា។ អ្នកអាចរត់កូដមេរៀននេះនៅលើគ្រឿងរបស់អ្នក (ឧ. ពី Visual Studio Code) ដែលក្នុងករណីនេះការសម្រួលនឹងបើកក្នុងបង្អួចថ្មី។ នៅពេលរត់កូដតាមអ៊ីនធឺណិត អ្នកប្រហែលជាត្រូវតែធ្វើការកែប្រែបន្តិចទៅកូដ ដូចបានពិពណ៌នានៅ [ទីនេះ](https://towardsdatascience.com/rendering-openai-gym-envs-on-binder-and-google-colab-536f99391cc7)។ ## OpenAI Gym នៅមេរៀនមុន ច្បាប់ល្បែង និងស្ថានភាពត្រូវបានផ្តល់ដោយថ្នាក់ `Board` ដែលយើងកំណត់ដោយខ្លួនឯង។ នៅទីនេះ យើងនឹងប្រើ **បរិយាកាសសម្រួលពិសេសមួយ** ដែលនឹងសម្រួលរូបវិទ្យាលើខ្សែដេកកំពង់ផ្លាស់ទី។ មួយក្នុងចំណោមបរិយាកាសសម្រួលពេញនិយមជាងគេសម្រាប់ហ្វឹកហាត់អាល់ហ្គរីធម Q-Learning គឺហៅថា [Gym](https://gym.openai.com/) ដែលត្រូវបានគ្រប់គ្រងដោយ [OpenAI](https://openai.com/។) ដោយប្រើ យើងអាចបង្កើតបរិយាកាសផ្សេងៗចាប់ពីការសម្រួល cartpole ដល់ហ្គេម Atari។ > **Note**: អ្នកអាចមើលបរិយាកាសផ្សេងទៀតដែលអាចប្រើបានពី OpenAI Gym នៅ [ទីនេះ](https://gym.openai.com/envs/#classic_control)។ ជាដំបូង មកដំឡើង gym ហើយនាំចូលបណ្ណាល័យដែលត្រូវការ (ប្លុកកូដ ១)៖ ```python import sys !{sys.executable} -m pip install gym import gym import matplotlib.pyplot as plt import numpy as np import random ``` ## វិចារណកម្ម - កំណត់បរិយាកាស cartpole ដើម្បីដំណើរការជាមួយបញ្ហារក្សាសមតុល្យ cartpole យើងត្រូវតែបង្កើតបរិយាកាសឆ្លើយតប។ បរិយាកាសមួយៗភ្ជាប់នឹងៈ - **ចន្លោះសំគាល់** សំគាល់រចនាសម្ព័ន្ធនៃព័ត៌មានដែលយើងទទួលពីបរិយាកាស។ សម្រាប់បញ្ហា cartpole យើងទទួលបានទីតាំងខ្សែដេក ល្បឿន និងតម្លៃផ្សេងៗ។ - **ចន្លោះសកម្មភាព** កំណត់សកម្មភាពដែលអាចធ្វើបាន។ នៅក្នុងករណីនេះ សកម្មភាពមានប្រភេទដាច់ ហើយមានពីរជម្រើស - **ឆ្វេង** និង **ស្ដាំ**។ (ប្លុកកូដ ២) ១. ដើម្បី initialize សូមវាយកូដដូចតទៅ៖ ```python env = gym.make("CartPole-v1") print(env.action_space) print(env.observation_space) print(env.action_space.sample()) ``` ដើម្បីមើលពីរបៀបដែលបរិយាកាសដំណើរការ អ្នកអាចរត់សម្រួលខ្លីមួយចំនួនសម្រាប់ជំហាន ១០០។ នៅជំហាននីមួយៗ យើងផ្តល់សកម្មភាពមួយសម្រាប់​យកអនុវត្ត - នៅក្នុងសម្រួលនេះយើងគ្រាន់តែជ្រើសសកម្មភាពដោយចៃដន្យពី `action_space`។ ១. រត់កូដខាងក្រោម ហើយមើលផលប៉ះពាល់។ ✅ ចងចាំថា ល្អជាងក្នុងការរត់កូដនេះនៅនៅលើ Python local ដើម្បីបានប្រសិទ្ធភាពល្អ! (ប្លុកកូដ ៣) ```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) ១. នៅពេលសម្រួល យើងត្រូវទទួលបានស្ថានភាពសម្រាប់ជ្រើសរើសសកម្មភាព។ តាមពិត មុខងារ 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() ``` អ្នកនឹងឃើញលទ្ធផលតែឯកទេសនៅក្នុង notebook ផ្ទៃនិចន៍៖ ```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 ``` ចំណុចដែលត្រឡប់មកវិញនៅរៀងរាល់ជំហានមានតម្លៃដូចខាងក្រោម៖ - ទីតាំងរបស់ cart - ល្បឿនរបស់ cart - មុំនៃខ្សែដេក - អត្រាបង្វិលនៃខ្សែដេក ១. រកតម្លៃអប្បបរមា និងអតិបរមានៃចំនួនទាំងនេះ៖ (ប្លុកកូដ ៥) ```python print(env.observation_space.low) print(env.observation_space.high) ``` អ្នកអាចចាប់អារម្មណ៍ថាតម្លៃទទួលរង្ស័យនៅរៀងរាល់ជំហានតែងតែ ១។ នេះគឺព្រោះគោលបំណងរបស់យើងគឺរស់រានមួយរយះពេលយូរ ប #ប្រែទៅមុខវីជ័យដទៃមួយដែលហៅថា CartPole ដែលគេពិចារណាថាសម្រេចបាន ប្រសិនបើយើងទទួលបានផលចង់បានមធ្យម ១៩៥ នៅលើ ១០០ ជំលោះជាប់គ្នា។ ## ស្ថានភាពប្រភេទដាច់ ក្នុង Q-Learning យើងត្រូវតែរៀបចំតារាង Q ដែលកំណត់តើត្រូវធ្វើអ្វីនៅក្នុងស្ថានភាពនីមួយៗ។ ដើម្បីអាចធ្វើបានអ្វីនេះ យើងត្រូវការឲ្យស្ថានភាពមានលក្ខណ: **ប្រភេទដាច់** បុណ្យទៅលម្អិតគឺ មានតម្លៃប្រភេទដាច់កំណត់ចំនួនកំណត់។ ដូច្នេះយើងត្រូវធ្វើអ្វីមួយដើម្បី **ធ្វើស្ថានភាពជាប្រភេទដាច់** ដោយផែនទីវាទៅក្បាលសំណុំស្ថានភាពកំណត់មួយ។ មានវិធីភាគច្រើនក្នុងការធ្វើនេះ៖ - **ចែកចេញទៅក្នុងកន្ត្រក**។ ប្រសិនបើយើងដឹងចន្លោះតម្លៃមួយ យើងអាចចែកចន្លោះនេះទៅជាចំនួនកន្ត្រក ហើយបន្ទាប់មកបម្លែងតម្លៃទៅជាលេខកន្ត្រកដែលវាចូលរួម។ វាអាចធ្វើបានដោយប្រើវិធី numpy [`digitize`](https://numpy.org/doc/stable/reference/generated/numpy.digitize.html)។ ក្នុងករណីនេះ យើងនឹងដឹងពីទំហំស្ថានភាពយ៉ាងច្បាស់ ពីព្រោះវាអាស្រ័យលើចំនួនកន្ត្រកដែលយើងជ្រើសរើសសម្រាប់ធ្វើ digitization។ ✅ យើងអាចប្រើការប្រព្រឹត្តតាមសនិទ្ទេសផ្សេងៗដើម្បីយកតម្លៃទៅចន្លោះកំណត់ (ឧ. ពី -20 ទៅ 20) ហើយបន្ទាប់មកបម្លែងតម្លៃហ្នឹងទៅជាចំនួនគត់ដោយបូកបន្ថយ។ វាបានផ្តល់ឧបត្ថម្ភល្អវាង និង មានកំណត់តិចលើទំហំស្ថានភាព ដោយពិសេសប្រសិនបើយើងមិនដឹងពីសមាមាត្រពិតនៃតម្លៃចូល។ ឧ. ក្នុងករណីរបស់យើង ២ តម្លៃក្នុងចំនួន ៤ មិនមានព្រំដែនលើឬក្រោម ភាគច្រើននាំឲ្យមានចំនួនស្ថានភាពអនੰਤ។ ក្នុងឧទាហរណ៍របស់យើង យើងនឹងប្រើវិធីទីពីរ។ ដូចដែលអ្នកអាចមើលឃើញក្រោយនេះ ទោះបីចន្លោះលើ/ក្រោមមិនបានកំណត់ តម្លៃទាំងនេះក៍ឃើញបន្ថយក្នុងចន្លោះកំណត់មួយ ដូច្នេះស្ថានភាពដែលមានតម្លៃខ្ពស់ទាំងនេះស្ថិតនៅក្នុងករណីកាច្រើនតិច។ ១. នេះជាផ្នែកមុខងារណាមួយ ដែលទទួលការសម្គាល់ពីម៉ូដែលរបស់យើង ហើយបង្កើតជាស៊ុមក្រុម ៤ ពីតម្លៃعددគត់៖ (ប្លុកកូដ ៦) ```python def discretize(x): return tuple((x/np.array([0.25, 0.25, 0.01, 0.1])).astype(np.int)) ``` ១. យើងមកសាកល្បងវិធីផ្សេងមួយផ្សេងទៀតសម្រាប់ការបម្លែងប្រភេទដោយប្រើ bin៖ (ប្លុកកូដ ៧) ```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)] # ប្រើរយៈពេលនៃតម្លៃសម្រាប់ប៉ារ៉ាម៉ែត្រនីមួយៗ nbins = [20,20,10,10] # ចំនួនប្រអប់សម្រាប់ប៉ារ៉ាម៉ែត្រនីមួយៗ 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)) ``` ១. យើងចាប់ផ្តើមរត់សម្រួលខ្លី ហើយមើលតម្លៃបរិយាកាសប្រភេទដាច់ទាំងនេះ។ អ្នកអាចសាកល្បងទាំង `discretize` និង `discretize_bins` ដើម្បីមើលថាតើមានភាពខុសគ្នាឬអត់។ ✅ discretize_bins បង្ហាញលេខ bin ដែលគិតចាប់ពី 0 ។ ដូច្នេះចំពោះតម្លៃនៅចន្លោះនៅជុំវិញ 0 វាក៏បញ្ចេញលេខពីចន្លោះកណ្តាលនៃចន្លោះ (10)។ នៅក្នុង discretize យើងមិនគិតពីជួរតម្លៃនៃលទ្ធផល ដែលអនុញ្ញាតឲ្យវា អាចមានតម្លៃអវិជ្ជមាន ហ្នឹងស្ថានភាពមិនត្រូវបានផ្លាស់ទី ហើយ 0 ត្រូវនឹង 0។ (ប្លុកកូដ ៨) ```python env.reset() done = False while not done: #env.render() obs, rew, done, info = env.step(env.action_space.sample()) #បោះពុម្ភ discretize_bins(obs) print(discretize(obs)) env.close() ``` ✅ អាចដកចេញបន្ទាត់ដែលចាប់ផ្តើមជាមួយ env.render បើអ្នកចង់មើលពីរបៀបដែលបរិយាកាសដំណើរការ។ បើមិនដូច្នេះ អ្នកអាចរត់វាក្រោមផ្ទាំងក្រោយបន្ទប់ ដែលរហ័សជាង។ យើងនឹងប្រើការជាអាថ៍កំបាំងនេះក្នុងដំណាក់កាល Q-Learning របស់យើង។ ## រចនាសម្ព័ន្ធ Q-Table នៅមេរៀនមុន ស្ថានភាពគឺជាគូលេខសាមញ្ញ 0 ដល់ 8 ដូច្នោះវាស្រួលក្នុងការបង្ហាញ Q-Table ជារូបភាព numpy tensor ទំហំ 8x8x2។ ប្រសិនបើយើងប្រើ bin discretization ទំហំវ៉ិចទ័រស្ថានភាពក៏ត្រូវបានកំណត់ហើយ ដូច្នេះយើងអាចប្រើវិធីដូចគ្នា ទំនាក់ទំនងស្ថានភាពជាអារេ 20x20x10x10x2 (2 គឺជាមាត្រដ្ឋានសកម្មភាព ហើយទំហំដំបូងបង្ហាញពីចំនួន bin ដែលយើងបានជ្រើស សម្រាប់ប៉ារ៉ា៉ម៉ែត្រនៅចន្លោះសំគាល់)។ ប៉ុន្ដែពេលខ្លះ បរិមាណត្រឹមត្រូវរបស់ចន្លោះសម្រួលមិនត្រូវបានស្គាល់។ ក្នុងករណីមុខងារ `discretize` យើងមិនអាចប្រាកដថាស្ថានភាពនៅក្នុងដែនកំណត់មួយ ព្រោះតម្លៃដើមខ្លះមិនមានព្រំដែន។ ដូច្នេះ យើងនឹងប្រើវិធីខុសបន្តិច ដោយបង្ហាញ Q-Table ជាថតកំនត់ឈ្មោះ (dictionary)។ ១. ប្រើគូ *(state,action)* ជារឹងគន្លង key តាម(dictionary) ហើយតម្លៃនឹងត្រូវបង្ហាញ Q-Table នៅចំណុចនោះ (ប្លុកកូដ ៩) ```python Q = {} actions = (0,1) def qvalues(state): return [Q.get((state,a),0) for a in actions] ``` នៅទីនេះ យើងកំណត់មុខងារ `qvalues()`, ដែលត្រឡប់បញ្ជីតម្លៃតារាង Q សម្រាប់ស្ថានភាពមួយសម្រាប់ឥរិយាបថដែលអាចកើតមាន។ បើមិនមាន ចំណុចនៅក្នុង Q-Table គឺត្រឡប់ទៅ 0 ជាមានប្រយោជន៍។ ## ចាប់ផ្តើម Q-Learning ឥឡូវនេះ យើងត្រៀមខ្លួនសម្រាប់បង្រៀន Peter រក្សាសមតុល្យ! ១. ជាមុន សូមកំណត់​ភាពផ្តោតចិត្តខ្លះៗ៖ (ប្លុកកូដ ១០) ```python # ប៉ារ៉ាម៉ែត្រខ្ពស់ alpha = 0.3 gamma = 0.9 epsilon = 0.90 ``` នៅទីនេះ `alpha` គឺជា **អត្រានៃការរៀន** ដែលកំណត់ថាយើងត្រូវកែប្រែតម្លៃ Q-Table បច្ចុប្បន្នប៉ុន្មាន នៅរៀងរាល់ជំហាន។ នៅមេរៀនមុនយើងចាប់ផ្តើមពី 1 បន្ទាប់មកកាត់បន្ថយ `alpha` ទៅតម្លៃតិចៗក្នុងដំណាក់កាលហ្វឹកហាត់។ នៅឧទាហរណ៍នេះ យើងនឹងរក្សាវាជាពិសេស សម្រាប់ភាពសាមញ្ញ ហើយអ្នកអាចសាកល្បងកំណត់តម្លៃ alpha ពីក្រោយបាន។ `gamma` គឺជា **តែវាដែលបញ្ចុះតម្លៃ** បង្ហាញពីការបញ្ញើសំរាប់កម្រិតការប្រមូលរង្ស័យក្នុងអនាគត ក្រែងលើរង្ស័យបច្ចុប្បន្ន។ `epsilon` គឺជា **មូលហេតុសម្រាប់ការទេសត/ប្រើប្រាស់** ដែលកំណត់ថាតើយើងធ្វើការស្វែងរក (exploration) ឬប្រើប្រាស់តម្លៃដែលយើងបានរៀនមកហើយ (exploitation)។ ក្នុងអាល់ហ្គរីធមីរបស់យើង នៅ `epsilon` ភាគរយនៃករណី យើងជ្រើសសកម្មភាពតាមតារាង Q និងនៅករណីសល់ យើងជ្រើសសកម្មភាពដោយចៃដន្យ។ វានឹងអនុញ្ញាតឲ្យយើងស្វែងរកតំបន់នៅលើលំហរកំណត់ដែលមិនដែលបានឃើញពីមុន។ ✅ សម្រាប់ការរក្សាសមតុល្យ - ជ្រើសសកម្មភាពចៃដន្យ (exploration) គឺអាចដូចជាការវាយចៃដន្យទៅខ្យល់ខុស គ្នា ហើយខ្សែគួរតែរៀនវិធីកំណត់សមតុល្យពីកង្វះខាតទាំងនេះ។ ### ពង្រឹងអាល់ហ្គរីធមី យើងក៏អាចធ្វើការកែលម្អពីរយ៉ាងចំរូងមកលើអាល់ហ្គរីធមីពីមេរៀនមុន៖ - **គណនាភាពមធ្យមរង្ស័យចងក្រង** អំពីរ៉ាចំនួនជាច្រើននៃការសម្រួល។ យើងនឹងបោះពុម្ពវាថា ទៅជារឿយៗរៀងរាល់ ៥០០០ ជំលោះ ហើយយើងនឹងទទួលបានរង្ស័យមធ្យមចងក្រងលើរយៈពេលនោះ។ មានន័យថាបើយើងទទួលបានជាង ១៩៥ ពិន្ទុ យើងអាចគិតថាបញ្ហាទទួលបានការដោះស្រាយ បទពិសោធអាចខ្ពស់ជាងគេដែលត្រូវបានដាក់ស្នើ។ - **គណនាពិន្ទុមធ្យមចងក្រងអតិបរមា** `Qmax`, ហើយយើងនឹងរក្សាទុក Q-Table ដែលទាក់ទងនឹងលទ្ធផលនោះ។ នៅពេលអ្នករត់ហ្វឹកហាត់ អ្នកនឹងកត់សម្គាល់ថា ពេលខ្លះលទ្ធផលមធ្យមចងក្រងចាប់ផ្តើមធ្លាក់ចុះ ហើយយើងចង់រក្សាតម្លៃ Q-Table ដែលពាក់ព័ន្ធនឹងម៉ូដែលល្អបំផុតដែលបានសង្កេតឃើញក្នុងដំណាក់កាលហ្វឹកហាត់។ ១. សូមប្រមូលរង្ស័យចងក្រងទាំងអស់នៅរៀងរាល់ជំហានសម្រួលទៅក្នុងវ៉ិចទ័រ `rewards` សម្រាប់ការគូរជាបន្ទាប់។ (ប្លុកកូដ ១១) ```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 # == ចាប់ផ្តើមសមួង == while not done: s = discretize(obs) if random.random() Qmax: Qmax = np.average(cum_rewards) Qbest = Q cum_rewards=[] ``` អ្វីដែលអ្នកអាចគិតស្រមៃពីលទ្ធផលទាំងនេះ៖ - **ជិតដល់គោលបំណង**។ យើងជិតដល់គោលបំណងក្នុងការទទួលបាន ១៩៥ រង្ស័យចងក្រងលើការប្រតិបត្តិ ១០០+ ផ្តាច់មុខឬយើងប្រហែលជាទទួលបានហើយ! ទោះបីជាលទ្ធផលតិចក៏ដោយ យើងមិនដឹងទេ ពីព្រោះយើងគណនាមធ្យមលើការរត់ ៥០០០ ហើយត្រូវការប្រតិបត្តិ ១០០ ។ ។ - **រង្ស័យចាប់ផ្តើមចុះ**។ ពេលខ្លះ រង្ស័យចាប់ផ្តើមធ្លាក់ បង្ហាញថាយើងអាច "បំផ្លាញ" តម្លៃដែលបានរៀនហើយនៅក្នុង Q-Table ជាមួយតម្លៃដែលធ្វើឲ្យស្ថានភាពកាន់តែអាក្រក់។ ការសង្កេតនេះមានភាពច្បាស់ជាង នៅពេលយើងគូរអភិវឌ្ឍន៍នៃការហ្វឹកហាត់។ ## រូបភាពអភិវឌ្ឍន៍ការហ្វឹកហាត់ ខណៈពេលហ្វឹកហាត់ យើងបានយកតម្លៃរង្ស័យចងក្រងនៅរៀងរាល់ជំលោះទៅក្នុងវ៉ិចទ័រ `rewards`។ នេះជារូបភាពនៃវាដែលធ្វើជាក្រាបជាមួយលេខជំលោះ៖ ```python plt.plot(rewards) ``` ![raw progress](../../../../translated_images/km/train_progress_raw.2adfdf2daea09c59.webp) ពីក្រាបនេះ មិនអាចប្រាប់អ្វីបានទេ ព្រោះដោយសារតែធម្មជាតិនៃដំណើរការហ្វឹកហាត់ stochastic ប្រវែងរបស់វគ្គហ្វឹកហាត់ផ្សេងគ្នា។ ដើម្បី​ធ្វើឲ្យមាន​អារម្មណ៍ល្អជាងនេះ យើងអាចគណនាមធ្យមរត់ជាមួយនឹងករណីជាច្រើន ដូចជា១០០។ វាអាចធ្វើបានដោយងាយស្រួលជាមួយ `np.convolve`: (ប្លុកកូដ ១២) ```python def running_average(x,window): return np.convolve(x,np.ones(window)/window,mode='valid') plt.plot(running_average(rewards,100)) ``` ![training progress](../../../../translated_images/km/train_progress_runav.c71694a8fa9ab359.webp) ## ការផ្លាស់ប្តូរពណ៌អំបូង ដើម្បីធ្វើឲ្យការរៀនមានស្ថេរភាព ចំនុចមួយМаЕнហចាំត្រូវបានប្តូរបន្តិចក្នុងដំណាក់កាលហ្វឹកហាត់។ ជាពិសេសៈ - **សម្រាប់អត្រារៀន** `alpha` អាចចាប់ផ្តើមជាមួយតម្លៃជិត 1 ហើយបន្តការកាត់បន្ថយជាបន្តបន្ទាប់។ ជាមួយពេលវេលា យើងនឹងទទួលបានតម្លៃប្រតិបត្តិល្អក្នុង Q-Table ហើយគួរតែធ្វើការកែប្រែតិចតួច មិនមែនលុបទាំងស្រុងជាមួយតម្លៃថ្មីទេ។ - **បន្ថែម epsilon**។ យើងអាចចង់បន្ថែម `epsilon` យឺតៗ ដើម្បីស្វែងរកតិច និងប្រើប្រាស់ច្រើនជាងមុន។ វាហាក់ដូចជាងសមស្របចាប់ផ្តើមជាមួយតម្លៃតិចនៃ `epsilon` ហើយលេចមកដល់ប្រហែល 1។ > **Task 1**: លេងជាមួយតម្លៃ hyperparameter ហើយមើលថាតើអ្នកអាចទទួលបានរង្ស័យចងក្រងខ្ពស់ជាងមុន។ តើអ្នកទទួលបានលើស ១៩៥ ទេ? > **Task 2**: ដើម្បីដោះស្រាយបញ្ហាផ្លូវការយ៉ាងត្រឹមត្រូវ អ្នកត្រូវការទទួលបានរង្វាន់មធ្យម ១៩៥ ក្នុងចន្លោះ ១០០ ដងរត់ជាប់គ្នា។ វាស់វែងវាក្នុងអំឡុងពេលបណ្តុះបណ្តាល ហើយធ្វើអោយប្រាកដថាអ្នកបានដោះស្រាយបញ្ហាផ្លូវការយ៉ាងត្រឹមត្រូវ! ## មើលលទ្ឋផលក្នុងសកម្មភាព វានឹងគួរឲ្យចាប់អារម្មណ៍ក្នុងការមើលការប្រព្រឹត្តទៅរបស់គំរូដែលបានបណ្តុះបណ្តាល។ ចាប់ផ្តើមរត់សកម្មភាពពិត និងអនុវត្តយុទ្ធសាស្រ្តជ្រើសរើសសកម្មភាពដូចក្នុងអំឡុងបណ្តុះបណ្តាល ដោយសេងតាមចែកចាយប្រតិបត្តិការជាប្រាក់ប្រមាណនៅក្នុងតារាង Q: (khối mã 13) ```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() ``` អ្នកគួរតែឃើញអ្វីមួយដូចខាងក្រោមនេះ៖ ![a balancing cartpole](../../../../8-Reinforcement/2-Gym/images/cartpole-balance.gif) --- ## 🚀បញ្ហាប្រឈម > **Task 3**: នៅទីនេះ យើងកំពុងប្រើច្បាប់ចុងក្រោយនៃតារាង Q ដែលប្រហែលជាមិនមែនល្អបំផុតឡើយ។ ចាំថាយើងបានរក្សាទុកតារាង Q ដែលមានប្រសិទ្ធភាពល្អបំផុតនៅក្នុងអថេរ `Qbest`! សាកល្បងឧទាហរណ៍ដដែលនេះជាមួយតារាង Q ដែលមានប្រសិទ្ធភាពល្អបំផុតដោយចម្លង `Qbest` ទៅ `Q` ហើយមើលថាអ្នកតើយល់ឃើញខុសគ្នាឬទេ។ > **Task 4**: នៅទីនេះ យើងមិនបានជ្រើសរើសសកម្មភាពល្អបំផុតក្នុងជំហាននិមួយៗទេ ប៉ុន្តែបញ្ចូលការសេងតាមចែកចាយប្រតិបត្តិការដែលបានផ្គូរផ្គង។ តើវានឹងមានហេតុផលប្រសើរជាងមុនក្នុងការជ្រើសរើសសកម្មភាពល្អបំផុតជានិច្ច ដែលមានតម្លៃ Q-Table ខ្ពស់បំផុតមែនទេ? អាចធ្វើបានដោយប្រើមុខងារ `np.argmax` ដើម្បីរកលេខសកម្មភាពដែលសមស្របនឹងតម្លៃ Q-Table ខ្ពស់បំផុត។ អនុវត្តយុទ្ធសាស្រ្តនេះ និងមើលថាវាបង្កើនលទ្ធផលការរក្សាសមតុល្យរបស់យើងទេ។ ## [ប្រលងក្រោយមេរៀន](https://ff-quizzes.netlify.app/en/ml/) ## ការងារ [បណ្តុះបណ្តាលរថយន្តភ្នំ](assignment.md) ## សេចក្ដីសន្និដ្ឋាន ឥឡូវនេះយើងបានរៀនពីវិធីបណ្ដុះបណ្តាលភ្នាក់ងារដើម្បីទទួលបានលទ្ធផលល្អ ដោយផ្តល់មុខងាររង្វាន់ដែលកំណត់រដ្ឋភាពដែលចង់បាន សម្រាប់ហ្គេម និងផ្តល់ឱកាសឲ្យពួកគេចុះសូមតាមដានការស្រាវជ្រាវក្នុងលំហស្វែងរកយ៉ាងមានឆន្ទៈ។ យើងបានអនុវត្តអាល់ហ្គរីធម Q-Learning ដោយជោគជ័យក្នុងករណីបរិយាកាសជាបន្ត និងបញ្ឈរ ដែលមានសកម្មភាពបញ្ឈរប៉ុណ្ណោះ។ វាសំខាន់ផងដែរដើម្បីសិក្សា ស្ថានភាពដែលរដ្ឋភាពសកម្មភាពក៏ជាបន្ត និងពេលដែលលំហសំឡេងសង្កត់មានភាពស្មុគស្មាញជាងនេះ ដូចជារូបភាពពីអេក្រង់ហ្គេម Atari។ ក្នុងបញ្ហាទាំងនោះ យើងតែងតែត្រូវការប្រើបច្ចេកទេសខ្លាំងជាងក្នុងការសិក្សាគ្រឿងម៉ាស៊ីន ដូចជា បណ្តាញសារធាតុកោសិកា neural networks ដើម្បីទទួលបានលទ្ធផលល្អ។ បញ្ហាស្មុគស្មាញជាងនេះជាគោលបំណងនៃវគ្គសិក្សា AI លំដាប់ខ្ពស់ជាងមួយដែលយើងនឹងបើកសិក្សាផ្សេងទៀត។ --- **ការព្រមាន**: ឯកសារនេះត្រូវបានបកប្រែដោយប្រើសេវាបកប្រែ AI [Co-op Translator](https://github.com/Azure/co-op-translator)។ ទោះយើងខំប្រឹងប្រែងរកការត្រឹមត្រូវ ប៉ុន្តែសូមយល់ថាការបកប្រែដោយម៉ាស៊ីនអាចមានកំហុស ឬការខ្វះខាតខ្លះៗ។ ឯកសារដើមដែលមានភាសាតំណើរការដើមគួរត្រូវបានទទួលស្គាល់ជាផ្នែកដើមដែលមានសុពលភាព។ សម្រាប់ព័ត៌មានសំខាន់ៗ មេរៀនបកប្រែដោយអ្នកជំនាញផ្នែកមនុស្សគឺត្រូវបានណែនាំ។ យើងមិនទទួលខុសត្រូវចំពោះការយល់ច្រឡំ ឬការបកស្រាយខុសពីការប្រើប្រាស់បកប្រែនេះឡើយ។