You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
ML-For-Beginners/translations/th/8-Reinforcement/2-Gym/README.md

333 lines
33 KiB

<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "107d5bb29da8a562e7ae72262d251a75",
"translation_date": "2025-09-05T22:08:02+00:00",
"source_file": "8-Reinforcement/2-Gym/README.md",
"language_code": "th"
}
-->
## ข้อกำหนดเบื้องต้น
ในบทเรียนนี้ เราจะใช้ไลบรารีที่เรียกว่า **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
> **หมายเหตุ**: คุณสามารถดูสภาพแวดล้อมอื่นๆ ที่มีใน OpenAI Gym [ที่นี่](https://gym.openai.com/envs/#classic_control)
ก่อนอื่น มาติดตั้ง Gym และนำเข้าไลบรารีที่จำเป็น (code block 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 เป็นแบบไม่ต่อเนื่อง และประกอบด้วยสองการกระทำ - **ซ้าย** และ **ขวา** (code block 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 ที่ติดตั้งในเครื่องของคุณ! (code block 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 ที่ระบุว่าควรดำเนินการจำลองต่อไปหรือไม่: (code block 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. รับค่าต่ำสุดและค่าสูงสุดของตัวเลขเหล่านั้น: (code block 5)
```python
print(env.observation_space.low)
print(env.observation_space.high)
```
คุณอาจสังเกตเห็นว่าค่ารางวัลในแต่ละขั้นตอนของการจำลองมีค่าเท่ากับ 1 เสมอ นั่นเป็นเพราะเป้าหมายของเราคือการอยู่รอดให้นานที่สุดเท่าที่จะเป็นไปได้ กล่าวคือ รักษาเสาให้อยู่ในตำแหน่งแนวตั้งในระดับที่เหมาะสมให้นานที่สุด
✅ ในความเป็นจริง การจำลอง CartPole ถือว่าแก้ปัญหาได้หากเราสามารถรับรางวัลเฉลี่ย 195 ในการทดลองต่อเนื่อง 100 ครั้ง
## การทำสถานะให้เป็นแบบไม่ต่อเนื่อง
ใน Q-Learning เราจำเป็นต้องสร้าง Q-Table ที่กำหนดว่าจะทำอะไรในแต่ละสถานะ เพื่อที่จะทำสิ่งนี้ได้ เราจำเป็นต้องให้สถานะเป็นแบบ **ไม่ต่อเนื่อง** กล่าวคือ ควรมีจำนวนค่าที่ไม่ต่อเนื่องที่จำกัด ดังนั้นเราจำเป็นต้อง **ทำสถานะให้เป็นแบบไม่ต่อเนื่อง** โดยการแมปค่าการสังเกตไปยังชุดสถานะที่จำกัด
มีวิธีการบางอย่างที่เราสามารถทำได้:
- **แบ่งเป็นช่วง** หากเรารู้ช่วงของค่าบางค่า เราสามารถแบ่งช่วงนี้ออกเป็นจำนวน **ช่วง** และแทนค่าด้วยหมายเลขช่วงที่มันอยู่ วิธีนี้สามารถทำได้โดยใช้เมธอด [`digitize`](https://numpy.org/doc/stable/reference/generated/numpy.digitize.html) ของ numpy ในกรณีนี้ เราจะทราบขนาดของสถานะอย่างแม่นยำ เพราะมันจะขึ้นอยู่กับจำนวนช่วงที่เราเลือกสำหรับการทำให้เป็นแบบดิจิทัล
✅ เราสามารถใช้การแทรกเชิงเส้นเพื่อปรับค่ามาอยู่ในช่วงที่จำกัด (เช่น จาก -20 ถึง 20) และจากนั้นแปลงตัวเลขเป็นจำนวนเต็มโดยการปัดเศษ วิธีนี้จะให้การควบคุมขนาดของสถานะน้อยลง โดยเฉพาะอย่างยิ่งหากเราไม่ทราบช่วงที่แน่นอนของค่าขาเข้า ตัวอย่างเช่น ในกรณีของเรา 2 ใน 4 ค่าจะไม่มีขอบเขตบน/ล่าง ซึ่งอาจส่งผลให้มีจำนวนสถานะที่ไม่มีที่สิ้นสุด
ในตัวอย่างของเรา เราจะใช้วิธีที่สอง ตามที่คุณอาจสังเกตเห็นในภายหลัง แม้จะไม่มีขอบเขตบน/ล่าง ค่าดังกล่าวมักจะไม่ค่อยมีค่าที่อยู่นอกช่วงที่จำกัด ดังนั้นสถานะที่มีค่าที่สุดขั้วจะเกิดขึ้นได้ยาก
1. นี่คือฟังก์ชันที่จะรับค่าการสังเกตจากโมเดลของเราและสร้างทูเพิลของค่าจำนวนเต็ม 4 ค่า: (code block 6)
```python
def discretize(x):
return tuple((x/np.array([0.25, 0.25, 0.01, 0.1])).astype(np.int))
```
1. ลองสำรวจวิธีการทำให้เป็นแบบไม่ต่อเนื่องด้วยช่วงอีกวิธีหนึ่ง: (code block 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 (code block 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 และดังนั้นจึงสะดวกที่จะแสดง Q-Table ด้วยเทนเซอร์ numpy ที่มีรูปร่าง 8x8x2 หากเราใช้การทำให้เป็นแบบไม่ต่อเนื่องด้วยช่วง ขนาดของเวกเตอร์สถานะของเราก็จะทราบเช่นกัน ดังนั้นเราสามารถใช้วิธีเดียวกันและแสดงสถานะด้วยอาร์เรย์ที่มีรูปร่าง 20x20x10x10x2 (ที่นี่ 2 คือมิติของ Action space และมิติแรกสอดคล้องกับจำนวนช่วงที่เราเลือกใช้สำหรับแต่ละพารามิเตอร์ใน Observation space)
อย่างไรก็ตาม บางครั้งขนาดที่แน่นอนของ Observation space อาจไม่ทราบ ในกรณีของฟังก์ชัน `discretize` เราอาจไม่สามารถมั่นใจได้ว่าสถานะของเราจะอยู่ในขอบเขตที่แน่นอน เพราะค่าบางค่าของต้นฉบับไม่มีขอบเขต ดังนั้นเราจะใช้วิธีที่แตกต่างออกไปเล็กน้อยและแสดง Q-Table ด้วยดิกชันนารี
1. ใช้คู่ *(state,action)* เป็นคีย์ของดิกชันนารี และค่าจะสอดคล้องกับค่าของ Q-Table (code block 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 กันเถอะ
ตอนนี้เราพร้อมที่จะสอน Peter ให้ทรงตัวแล้ว!
1. ก่อนอื่น มาตั้งค่าพารามิเตอร์ไฮเปอร์บางตัว: (code block 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** ที่กำหนดว่าเราควรเลือกการสำรวจมากกว่าการใช้ประโยชน์หรือไม่ ในอัลกอริทึมของเรา เราจะเลือกการกระทำถัดไปตามค่าของ Q-Table ในเปอร์เซ็นต์ของกรณีที่กำหนดโดย `epsilon` และในจำนวนที่เหลือเราจะดำเนินการแบบสุ่ม สิ่งนี้จะช่วยให้เราสำรวจพื้นที่การค้นหาที่เราไม่เคยเห็นมาก่อน
✅ ในแง่ของการทรงตัว - การเลือกการกระทำแบบสุ่ม (การสำรวจ) จะทำหน้าที่เป็นการผลักแบบสุ่มในทิศทางที่ผิด และเสาจะต้องเรียนรู้วิธีการฟื้นฟูสมดุลจาก "ข้อผิดพลาด" เหล่านั้น
### ปรับปรุงอัลกอริทึม
เรายังสามารถปรับปรุงอัลกอริทึมของเราจากบทเรียนก่อน:
- **คำนวณรางวัลสะสมเฉลี่ย** ในการจำลองจำนวนหนึ่ง เราจะพิมพ์ความคืบหน้าทุกๆ 5000 รอบ และเราจะเฉลี่ยรางวัลสะสมในช่วงเวลานั้น หมายความว่าหากเราได้คะแนนมากกว่า 195 เราสามารถถือว่าปัญหาได้รับการแก้ไขแล้ว ด้วยคุณภาพที่สูงกว่าที่กำหนด
- **คำนวณผลลัพธ์สะสมเฉลี่ยสูงสุด** `Qmax` และเราจะเก็บ Q-Table ที่สอดคล้องกับผลลัพธ์นั้น เมื่อคุณรันการฝึก คุณจะสังเกตเห็นว่าบางครั้งผลลัพธ์สะสมเฉลี่ยเริ่มลดลง และเราต้องการเก็บค่าของ Q-Table ที่สอดคล้องกับโมเดลที่ดีที่สุดที่สังเกตได้ระหว่างการฝึก
1. เก็บรางวัลสะสมทั้งหมดในแต่ละการจำลองไว้ในเวกเตอร์ `rewards` เพื่อการพล็อตในภายหลัง (code block 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()<epsilon:
# exploitation - chose the action according to Q-Table probabilities
v = probs(np.array(qvalues(s)))
a = random.choices(actions,weights=v)[0]
else:
# exploration - randomly chose the action
a = np.random.randint(env.action_space.n)
obs, rew, done, info = env.step(a)
cum_reward+=rew
ns = discretize(obs)
Q[(s,a)] = (1 - alpha) * Q.get((s,a),0) + alpha * (rew + gamma * max(qvalues(ns)))
cum_rewards.append(cum_reward)
rewards.append(cum_reward)
# == Periodically print results and calculate average reward ==
if epoch%5000==0:
print(f"{epoch}: {np.average(cum_rewards)}, alpha={alpha}, epsilon={epsilon}")
if np.average(cum_rewards) > Qmax:
Qmax = np.average(cum_rewards)
Qbest = Q
cum_rewards=[]
```
สิ่งที่คุณอาจสังเกตเห็นจากผลลัพธ์เหล่านั้น:
- **ใกล้เป้าหมายของเรา** เราใกล้จะบรรลุเป้าหมายในการได้รับรางวัลสะสม 195 ในการรันการจำลองต่อเนื่อง 100+ ครั้ง หรือเราอาจบรรลุเป้าหมายแล้ว! แม้ว่าเราจะได้ตัวเลขที่น้อยกว่า เราก็ยังไม่ทราบ เพราะเราเฉลี่ยมากกว่า 5000 รอบ และมีเพียง 100 รอบที่จำเป็นในเกณฑ์อย่างเป็นทางการ
- **รางวัลเริ่มลดลง** บางครั้งรางวัลเริ่มลดลง ซึ่งหมายความว่าเราอาจ "ทำลาย" ค่าที่เรียนรู้แล้วใน Q-Table ด้วยค่าที่ทำให้สถานการณ์แย่ลง
การสังเกตนี้จะเห็นได้ชัดเจนขึ้นหากเราพล็อตความคืบหน้าการฝึก
## การพล็อตความคืบหน้าการฝึก
ระหว่างการฝึก เราได้เก็บค่ารางวัลสะสมในแต่ละรอบไว้ในเวกเตอร์ `rewards` นี่คือสิ่งที่มันดูเหมือนเมื่อเราพล็อตมันกับหมายเลขรอบ:
```python
plt.plot(rewards)
```
![raw progress](../../../../8-Reinforcement/2-Gym/images/train_progress_raw.png)
จากกราฟนี้ ไม่สามารถบอกอะไรได้ เพราะลักษณะของกระบวนการฝึกแบบสุ่มทำให้ความยาวของเซสชันการฝึกแตกต่างกันมาก เพื่อให้กราฟนี้มีความหมายมากขึ้น เราสามารถคำนวณ **ค่าเฉลี่ยเคลื่อนที่** ในการทดลองชุดหนึ่ง เช่น 100 สิ่งนี้สามารถทำได้อย่างสะดวกโดยใช้ `np.convolve`: (code block 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)
## การปรับพารามิเตอร์ไฮเปอร์
เพื่อให้การเรียนรู้มีเสถียรภาพมากขึ้น มีเหตุผลที่จะปรับพารามิเตอร์ไฮเปอร์บางตัวระหว่างการฝึก โดยเฉพาะ:
- **สำหรับ learning rate** `alpha` เราอาจเริ่มต้นด้วยค่าที่ใกล้เคียงกับ 1 และจากนั้นลดค่าพารามิเตอร์ลงเรื่อยๆ เมื่อเวลาผ่านไป เราจะได้รับค่าความน่าจะเป็นที่ดีใน Q-Table และดังนั้นเราควรปรับค่าพวกนั้นเล็กน้อย และไม่เขียนทับด้วยค่าที่ใหม่ทั้งหมด
- **เพิ่ม epsilon** เราอาจต้องการเพิ่ม `epsilon` อย่างช้าๆ เพื่อสำรวจน้อยลงและใช้ประโยชน์มากขึ้น อาจมีเหตุผลที่จะเริ่มต้นด้วยค่าที่ต่ำของ `epsilon` และเพิ่มขึ้นจนเกือบถึง 1
> **งานที่ 1**: ลองปรับค่าพารามิเตอร์ต่าง ๆ และดูว่าคุณสามารถทำให้ผลตอบแทนรวมสูงขึ้นได้หรือไม่ คุณได้คะแนนเกิน 195 หรือยัง?
> **งานที่ 2**: เพื่อแก้ปัญหาอย่างเป็นทางการ คุณจำเป็นต้องได้ค่าเฉลี่ยรางวัล 195 ในการทดลอง 100 ครั้งติดต่อกัน วัดผลระหว่างการฝึกและตรวจสอบให้แน่ใจว่าคุณได้แก้ปัญหาอย่างเป็นทางการแล้ว!
## ดูผลลัพธ์ในทางปฏิบัติ
มันน่าสนใจที่จะเห็นว่ารูปแบบที่ฝึกมาแล้วทำงานอย่างไร ลองรันการจำลองและใช้กลยุทธ์การเลือกการกระทำแบบเดียวกับที่ใช้ระหว่างการฝึก โดยสุ่มตามการแจกแจงความน่าจะเป็นใน Q-Table: (code block 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)
---
## 🚀ความท้าทาย
> **งานที่ 3**: ในที่นี้ เราใช้สำเนาสุดท้ายของ Q-Table ซึ่งอาจไม่ใช่ตัวที่ดีที่สุด อย่าลืมว่าเราได้บันทึก Q-Table ที่มีประสิทธิภาพดีที่สุดไว้ในตัวแปร `Qbest`! ลองใช้ตัวอย่างเดียวกันกับ Q-Table ที่มีประสิทธิภาพดีที่สุดโดยคัดลอก `Qbest` ไปยัง `Q` และดูว่าคุณสังเกตเห็นความแตกต่างหรือไม่
> **งานที่ 4**: ในที่นี้ เราไม่ได้เลือกการกระทำที่ดีที่สุดในแต่ละขั้นตอน แต่สุ่มตามการแจกแจงความน่าจะเป็นที่เกี่ยวข้อง จะสมเหตุสมผลกว่าหรือไม่ถ้าเลือกการกระทำที่ดีที่สุดเสมอ ซึ่งมีค่าที่สูงที่สุดใน Q-Table? สิ่งนี้สามารถทำได้โดยใช้ฟังก์ชัน `np.argmax` เพื่อค้นหาหมายเลขการกระทำที่สอดคล้องกับค่าที่สูงที่สุดใน Q-Table ลองใช้กลยุทธ์นี้และดูว่ามันช่วยปรับปรุงการทรงตัวหรือไม่
## [แบบทดสอบหลังการบรรยาย](https://ff-quizzes.netlify.app/en/ml/)
## งานที่ได้รับมอบหมาย
[ฝึก Mountain Car](assignment.md)
## สรุป
ตอนนี้เราได้เรียนรู้วิธีการฝึกตัวแทนเพื่อให้ได้ผลลัพธ์ที่ดีเพียงแค่ให้ฟังก์ชันรางวัลที่กำหนดสถานะที่ต้องการของเกม และให้โอกาสพวกเขาสำรวจพื้นที่ค้นหาอย่างชาญฉลาด เราได้ใช้ Q-Learning algorithm สำเร็จในกรณีของสภาพแวดล้อมแบบไม่ต่อเนื่องและต่อเนื่อง แต่มีการกระทำแบบไม่ต่อเนื่อง
สิ่งสำคัญคือต้องศึกษาสถานการณ์ที่สถานะการกระทำเป็นแบบต่อเนื่อง และเมื่อพื้นที่การสังเกตมีความซับซ้อนมากขึ้น เช่น ภาพจากหน้าจอเกม Atari ในปัญหาเหล่านี้เรามักต้องใช้เทคนิคการเรียนรู้ของเครื่องที่ทรงพลังมากขึ้น เช่น neural networks เพื่อให้ได้ผลลัพธ์ที่ดี หัวข้อที่ก้าวหน้ากว่านี้จะเป็นเนื้อหาในหลักสูตร AI ขั้นสูงของเราในอนาคต
---
**ข้อจำกัดความรับผิดชอบ**:
เอกสารนี้ได้รับการแปลโดยใช้บริการแปลภาษา AI [Co-op Translator](https://github.com/Azure/co-op-translator) แม้ว่าเราจะพยายามให้การแปลมีความถูกต้องมากที่สุด แต่โปรดทราบว่าการแปลอัตโนมัติอาจมีข้อผิดพลาดหรือความไม่ถูกต้อง เอกสารต้นฉบับในภาษาดั้งเดิมควรถือเป็นแหล่งข้อมูลที่เชื่อถือได้ สำหรับข้อมูลที่สำคัญ ขอแนะนำให้ใช้บริการแปลภาษามืออาชีพ เราไม่รับผิดชอบต่อความเข้าใจผิดหรือการตีความผิดที่เกิดจากการใช้การแปลนี้