Hello world với Reinforcement Learning

Xin chào các bạn. Tiếp nối series về Reinforcement Learning (RL), hôm nay mình xin giới thiệu một ví dụ đơn giản có thể coi như là “Hello world” của RL. 1. Giới thiệu Trong bài trước Đôi điều cơ bản về học tăng cường mình đã giới thiệu một số khái niệm của RL.

Xin chào các bạn. Tiếp nối series về Reinforcement Learning (RL), hôm nay mình xin giới thiệu một ví dụ đơn giản có thể coi như là “Hello world” của RL.

1. Giới thiệu

Trong bài trước Đôi điều cơ bản về học tăng cường mình đã giới thiệu một số khái niệm của RL. Trong đó môi trường và các trạng thái, phần thưởng là những yếu tố quan trọng. Để cho có thể học được những chiến lược tối ưu hoặc tìm được chuỗi hành động tối ưu, tác nhân phải thử nhiều lần và học từ các lần thử đó, và rất khó để cho tác nhân có thể học được trong thế giới thực. Do đó việc mô phỏng lại môi trường là rất quan trọng. Rất may OpenAI đã có một opensource mang tên Gym để mô phỏng lại một số môi trường đơn giản. Trong bài này mình sẽ sử dụng Q-Learning để giải quyết game mountain-car trong thư viện gym.

Với mountain-car, mục tiêu của chúng ta là điều khiển xe ô tô đến lá cờ:
image.png
Ta xét các thuộc tính của game này:

  1. Tập trạng thái S=R2S = R^{2} bao gồm vị trí của xe trên trục ngang và vận tốc của xe, chiều dương từ trái sang phải. Cụ thể hơn:

S={(x,v)∣x,v∈R;−1.2≤x≤0.6;−0.07≤v≤0.07}S = left { (x ,v ) | x,v in R; -1.2 leq x leq 0.6; -0.07 leq v leq 0.07 right }

  1. Tập hành động của xe:

A={0;1;2}mathcal{A} = left {0; 1; 2 right }

Với a∈Aa in mathcal{A}:

  • a = 0: tăng tốc sang trái
  • a = 1: Không tăng tốc
  • a = 2: Tăng tốc sang phải
  1. Phần thưởng: Với mỗi hành động, nếu chưa tới đích (x<0.5)(x < 0.5) nhận được phần thưởng -1, nếu không thì nhận được 0 và kết thúc game
  2. Trạng thái khởi tạo x0∈[−0.6,−0.4]x_0 in [-0.6, -0.4]v0=0v_0=0
  3. Trạng thái kết thúc: Đến được cờ tại x=0.5x=0.5 hoặc tổng phần thưởng đạt đến -200

Code import thư viện và khởi tạo môi trường:

# importimport gym
import time
import numpy as np
import IPython.display
from tqdm.notebook import tqdm

# create environment
env = gym.make('MountainCar-v0')

Hãy cùng chạy thử 1 ví dụ:

s = env.reset()# reset to starting State
action_list =list(range(env.action_space.n))whileTrue:
    a = np.random.choice(action_list)# random an action
    s, r, done, _ = env.step(a)# perform action, get state, reward, is terminatedif done:break
    env.render()
    time.sleep(0.05)

2. Code thôi

2.1 Xây dựng Q-function

Hãy cùng xét công thức cuối cùng của bài viết trước:

Q(s,a)=(1−α)Q(s,a)+αEs∼P(s′∣s,a)(R(s,a)+γmax⁡a∈AQ∗(s,a))Q(s,a) = (1-alpha) Q(s,a) + alpha E_{s sim P(s’ | s , a)} left (R(s, a) + gammamax _ {a in mathcal{A}}Q^*(s,a) right )

Trong trường hợp chúng ta đang xét, do thư viện gym mô phỏng lại hiện tượng vật lý từ thực tế nên tại mỗi trạng thái ss, ta thực hiện hành động aa sẽ đưa ta đến trạng thái s′s’ xác định. Do đó hàm QQ trong trường hợp này được viết lại:

Q(s,a)=(1−α)Q(s,a)+α(R(s,a)+γmax⁡a∈AQ∗(s,a))(1)tag{1}
Q(s,a) = (1-alpha) Q(s,a) + alpha left (R(s, a) + gammamax _ {a in mathcal{A}}Q^*(s,a) right )

Trong game này,không gian trạng thái có 2 chiều (xxvv), tập hành động chỉ có 3 hành động, do đó chúng ta có thể mô hình hàm QQ bằng một bảng Q−tableQ-table, với các cột tương ứng với các giá trị khác nhau của vận tốc vv, các cột tương ứng với các giá trị khác nhau của tọa độ xx. Tuy nhiên x,v∈Rx,v in R mà số cột và hàng phải hữu hạn nên ta cần lượng tử hóa trạng thái của xe thành NN trạng thái rời rạc khác nhau, nghĩa là chia chia các giá trị của tọa độ và vận tốc thành NN đoạn bằng nhau, trạng thái của xe sẽ là chỉ số của các đoạn tương ứng.

Code lượng tử hóa cho 1 chiều của trạng thái

classNBinDiscretizer:def__init__(self, min_val, max_val, nbins):
        self.min_val = min_val
        self.max_val = max_val
        self.step =(max_val - min_val)/ nbins
        self.nbins =int(nbins)def__call__(self, val):returnint(round((val - self.min_val)/ self.step))% self.nbins

Code lượng tử hóa cho không gian trạng thái:

classDicretezation:def__init__(self, discretezers):
        self.discretezers = discretezers
    def__getitem__(self, index):assertlen(index)==len(self.discretezers)returntuple([self.discretezers[i](index[i])for i inrange(len(index))])

Tạo các quantizer:

n_quantization =50
x_quantizer = NBinDiscretizer(env.observation_space.low[0], env.observation_space.high[0], n_quantization)
v_quantizer = NBinDiscretizer(env.observation_space.low[0], env.observation_space.high[0], n_quantization)
state_quantizer = Dicretezation([x_quantizer, v_quantizer])

2.2 Xây dựng quá trình học

Các bước của quá trình học như sau:

  • Khởi tạo một giá xác xuất ϵepsilon là xác suất thực hiện một bước đi ngẫu nhiên, còn lại 1−ϵ1 – epsilon là xác suất thực hiện theo chiến lược π∗=arg max⁡a∈AQ∗(s,a)pi ^ * = argmax _{a in mathcal{A}} Q^{*} (s,a). ϵepsilon sẽ giảm dần trong quá trình học bởi ban đầu khi mô hình chưa học được nhiều thì ta cần lấy các bước ngẫu nhiên để tạo thêm dữ liệu cho mô hình học, còn khi học được rồi thì sẽ học từ chính mô hình.
  • Tại mỗi epoch:
    1. Reset môi trường về trạng thái khởi tạo s=s0s=s_0
    2. Chọn một bước aa đi với xác suất ϵepsilon ngẫu nhiên, và 1-epsilion tuân theo chiến lược π∗pi^*.
    3. Thực hiện bước đi aa, nhận về trạng thái tiếp theo s′s’, lợi tức tức thời rr và trạng thái kết thúc.
    4. Cập nhật QQ theo (1)

Code:

# inititalize some variables
lr =0.1
gamma =0.9
epochs =10000
epsilon =0.9
epsilon_scale = epsilon /(epochs /4)# some metrics
max_reward =-1000
max_pos =-1000# logging# inititalize some variables
epochs =10000
epsilon =0.9
epsilon_scale = epsilon /(epochs /4)# some metrics
max_reward =-1000
max_pos =-1000# logging
log = display('', display_id=True)
reach_log = display('', display_id=True)for epoch in tqdm(range(epochs), desc="Epoch"):
    ep_max_pos =-1000
    ep_reward =0# reset environment
    obs = env.reset()
    done =Falsewhilenot done:# take an actionif np.random.random_sample()> epsilon:
            a = np.argmax(Q[state_quantizer[obs]])else:
            a = np.random.randint(0, env.action_space.n)# perform action
        new_obs, r, done, info = env.step(a)
        ep_reward += r
        
        if new_obs[0]>= env.goal_position:
            reach_log.update(f"Reach goal at epoch {epoch} with reward: {ep_reward}")# update Q
        cur_q_value = Q[state_quantizer[obs]][a]        
        new_q_value =(1-lr)* cur_q_value + lr *(r + gamma *max(Q[state_quantizer[new_obs]]))
        Q[state_quantizer[obs]][a]= new_q_value
        obs = new_obs
        ep_max_pos =max(obs[0], ep_max_pos)
        
    max_reward =max(ep_reward, max_reward)
    max_pos =max(ep_max_pos, max_pos)
    epsilon =max(0, epsilon - epsilon_scale)
    
    log.update("epoch {}: ep_reward: {:9.6f}, max_reward: {:9.6f}, ep_max_pos: {:.6f}, max_pos: {:.6f}, epsilon: {:.6f}".format(epoch, ep_reward, max_reward, ep_max_pos, max_pos, epsilon))

3. Tổng kết

Hy vọng với một ví dụ nhỏ trong bài viết này sẽ giúp các bạn hiểu hơn về Q-functionQ-learning. Code đầy đủ trong bài viết này mình sẽ để ở đây. Nếu có gì góp ý thì đừng ngần ngại cho mình biết để hoàn thiện hơn. Còn nếu thấy hay thì cho mình xin 1 upvote 😄.

Nguồn: viblo.asia

Bài viết liên quan

WebP là gì? Hướng dẫn cách để chuyển hình ảnh jpg, png qua webp

WebP là gì? WebP là một định dạng ảnh hiện đại, được phát triển bởi Google

Điểm khác biệt giữa IPv4 và IPv6 là gì?

IPv4 và IPv6 là hai phiên bản của hệ thống địa chỉ Giao thức Internet (IP). IP l

Check nameservers của tên miền xem website trỏ đúng chưa

Tìm hiểu cách check nameservers của tên miền để xác định tên miền đó đang dùn

Mình đang dùng Google Domains để check tên miền hàng ngày

Từ khi thông báo dịch vụ Google Domains bỏ mác Beta, mình mới để ý và bắt đầ