การใช้ Reinforcement Q- learning ใน Python
Published: 2024-04-09 12:14:48

หากเราต้องการสอน AI ให้เรียนรู้ว่าสิ่งที่ทำนั้นเป็นสิ่งที่ถูกต้องหรือไม่เราจะสามารถใช้ Reinforcement Q-learning ซึ่งเป็นอัลกอริธึมการเรียนรู้ของ AI ประเภทหนึ่งที่ใช้ในเรียนรู้แบบ "Reinforcement" กล่าวง่าย ๆ ก็คือเป็นวิธีสำหรับการใช้ Agent ในการเรียนรู้การหาทางที่ดีที่สุดที่จะดำเนินการ(Action)ในสภาพแวดล้อม(environment )เฉพาะและให้รางวัล(Reward)แก่การดำเนินการที่ถูกต้องเพื่อให้เกิดประโยชน์สูงสุด

โดยบทความนี้เราจะใช้ Reinforcement Q- learning เพื่อสอนรถแท็กซี่ให้รับและส่งผู้โดยสารไปยังสถานที่ที่ถูกต้อง โดยทั้งหมด Code ทั้งหมดนี้จะรันผ่าน Google colab ทัั้งหมด

**ขั้นตอนการทำงาน**

**1.ทำการติดตั้งและ Import เกม taxi มาก่อน**
```
!pip install cmake 'gym[atari]' scipy
import gym

env = gym.make("Taxi-v3").env

env.reset() 
env.render()

print("Action Space {}".format(env.action_space))
print("State Space {}".format(env.observation_space))
```
ในตัวอย่างจะทำการสร้าง environment สำหรับเกมให้ด้วย
จะได้ผลลัพท์ดังนี้
```
Action Space Discrete(6)
State Space Discrete(500)
```
action space คือ การกระทำที่ทำได้ทั้งหมด
0 = south
1 = north
2 = east
3 = west
4 = pickup
5 = dropoff
ส่วน State Space นั้นคือรหัสตำแหน่งของรถแท็กซี่ ตำแหน่งของผู้โดยสาร และสถานที่ปลายทาง ทั้งหมด
โดย Q-Learning จะใช้ทั้งสองนี้ในการเรียนรู้

```
state = env.encode(3, 1, 2, 0) # (taxi row, taxi column, passenger index, destination index)
print("State:", state)

env.s = state
```
เราสามารถเช็คได้ด้วยว่าในตรงนั้นคือ state ใด
จะได้ออกมาเป็น
`State: 328`
และเรายังสามารถเช็ค reward จาก state นั้นได้อีกด้วย

```
env.P[328]
```
`{0: [(1.0, 428, -1, False)],
 1: [(1.0, 228, -1, False)],
 2: [(1.0, 348, -1, False)],
 3: [(1.0, 328, -1, False)],
 4: [(1.0, 328, -10, False)],
 5: [(1.0, 328, -10, False)]}`

0-5 นั้นคือ Action 
1.0 คือความน่าจำเป็น 
428 คือสถานะถัดไปหรือ state นั้นเอง 
-1 นั้นคือ reward จาก Action 
False สิ่งที่บอกว่าจากการเล่นว่า episode นี้เสร็จหรือยังโดยจะใช้ในระหว่างการเล่นหลาย ๆ ครั้ง


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6fb79eu3osza4pqjwj1c.png)

รูปตัวอย่างเกม

**2.ทำการ Import Q-Learing**

```
import numpy as np
q_table = np.zeros([env.observation_space.n, env.action_space.n])
```
หลังจาก import เสร็จแล้วก็ทำการสร้างตาราง Q-table เป็น 500 * 6 ตามเกม

**3.ทำการ train Agent**

เป็นการสอนให้ Agent นั้นได้เรียนรู้ว่าการทำ Action ไหนเป็นทางเลือกที่มอบ Reward มากที่สุด
```
%%time
"""Training the agent"""

import random
from IPython.display import clear_output

# Hyperparameters
alpha = 0.1
gamma = 0.6
epsilon = 0.1

# For plotting metrics
all_epochs = []
all_penalties = []

for i in range(1, 100001):
    state = env.reset()

    epochs, penalties, reward, = 0, 0, 0
    done = False
    
    while not done:
        if random.uniform(0, 1) < epsilon:
            action = env.action_space.sample() # Explore action space
        else:
            action = np.argmax(q_table[state]) # Exploit learned values

        next_state, reward, done, info = env.step(action) 
        
        old_value = q_table[state, action]
        next_max = np.max(q_table[next_state])
        
        new_value = (1 - alpha) * old_value + alpha * (reward + gamma * next_max)
        q_table[state, action] = new_value

        if reward == -10:
            penalties += 1

        state = next_state
        epochs += 1
        
    if i % 100 == 0:
        clear_output(wait=True)
        print(f"Episode: {i}")

print("Training finished.\n")
```
ตรงนี้เวลาในการ Train จะนานแค่ไหนนั้นขึ้นอยู่กับว่าเราตั้ง
for i in range(1, 100001)ไว้เยอะแค่ไหน

```
q_table[411]
```
หากเราเรียกดู Table ออกมาจะเห็นว่าซึ่งก็คือผล Reward จาก Table นั้น ๆ 
`array([ -2.27325183,  -2.3639511 ,  -2.27325183,  -2.27325184,
        -2.1220864 , -11.2732516 ])`
array ทั้งหมดนี้คือผล Rewardจาก Action ทั้งหมดที่เกิดขึ้นได้โดยจะเห็นได้ว่า 
Action ที่ 4 นั้นมีค่ามากที่สุดคือ -2.1220864 หมายความว่านี้คือทางเลือกที่ดีที่สุดนั่นเอง

**4.ทำการสรุปค่าและเปรียบเทียบความแตกต่าง**

```
total_epochs, total_penalties = 0, 0
episodes = 100

for _ in range(episodes):
    state = env.reset()
    epochs, penalties, reward = 0, 0, 0
    
    done = False
    
    while not done:
        action = np.argmax(q_table[state])
        state, reward, done, info = env.step(action)

        if reward == -10:
            penalties += 1

        epochs += 1

    total_penalties += penalties
    total_epochs += epochs
  

print(f"Results after {episodes} episodes:")
print(f"Average timesteps per episode: {total_epochs / episodes}")
print(f"Average penalties per episode: {total_penalties / episodes}")
```
ผลที่ออกมาคือ
`Results after 100 episodes:
Average timesteps per episode: 12.89
Average penalties per episode: 0.0`

เราเห็นได้ว่าประสิทธิภาพของตัว Agent ดีขึ้นอย่างมาก และไม่มีบทลงโทษ(penalties) ซึ่งหมายความว่า Action การรับส่งผู้โดยสาร 100 คนมีความถูกต้องทั้งหมด 

ทั้งนี้เรามาลองดูกับวิธีการที่ไม่ใช้ Q-learning กันบ้าง

```
env.s = 411  # set environment to illustration's state

epochs = 0
penalties, reward = 0, 0


done = False

while not done:
    action = env.action_space.sample()
    state, reward, done, info = env.step(action)

    if reward == -10:
        penalties += 1
    
    epochs += 1
    
  
print("Timesteps taken: {}".format(epochs))
print("Penalties incurred: {}".format(penalties))
```
ผลที่ได้คือ
`Timesteps taken: 1744
Penalties incurred: 581`
ซึ่งเห็นได้ว่ามี Penalties ที่สูงมาก ๆ ถึง 581 ต่างกับการใช้ Q-learning และนี้เป็นการทดลองแค่ 1 episodes เท่านั้น

**สรุปผล**
เราจะเห็นได้อย่างชัดเจนเลยว่า Q-learning Agent นั้นมีสามารถรับส่งผู้โดยสารได้อย่างแม่นยำและไม่มี penalties เลย ต่างกับวิธีที่ไม่ใช้ นั้นจะมี penalties ที่สูงและไม่แน่นอนเป็นอย่างมาก 
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rcvy3laj3wcoewmqsgav.png) 
หากเราทำการหาค่าเฉลี่ย 100 ครั้งจากการให้เล่นเกมจะพบว่า Q-Learing นั้นมีเฉลี่ยที่ดีกว่าเห็นได้ชัดทั้ง 3 ด้าน

เพราะฉะนั้นนี่เป็นหนึ่งในวิธีการ Train AI ที่ดีมากโดยการโยน AI เข้าไปใน environment ที่ต้องการและให้ AI เรียนรู้จากสิ่งเหล่านั้นแล้วเราส่งคำถามเข้าเพื่อเช็คสิ่งที่ AI นั้นเข้าใจและมอบ Reward จาก Action ที่ AI ทำว่าถูกต้องหรือไม่ 

ข้อมูลจาก
https://www.learndatasci.com/tutorials/reinforcement-q-learning-scratch-python-openai-gym/