iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 6
1
AI & Data

從根本學習Reinforcement Learning系列 第 6

[Day06]蒙地卡羅方法

  • 分享至 

  • xImage
  •  

前言

我們不一定會知道環境的Dynamic,昨天的Taxi環境gym好心提供給我們,但如果像是更複雜的環境,比如自駕車、21點、圍棋等等。如果要將所有機率算出來,再算Value Function就有點困難。

蒙地卡羅方法(Monte Carlo Method)

這時候蒙利卡羅方法就有用了,還記得大數法則(Law of large numbers)嗎?只要抽樣的樣本數越多,就越能趨近期望值。

而我們說過強化學習中的Value Function,其實就是求全部Reward和的期望值:

https://ithelp.ithome.com.tw/upload/images/20200905/20129922KgxFfVDehJ.png

根據大數法則,我們可以知道當我們https://chart.googleapis.com/chart?cht=tx&chl=G_%7Bt%7D的樣本數越多,https://chart.googleapis.com/chart?cht=tx&chl=V_%7B%5Cpi%7D(s)就離真實值越近。這種用隨機採樣來估測問題的隨機性的方法,就稱為蒙地卡羅方法

所以我們只要跑足夠多的Epsiode,得到足夠多的https://chart.googleapis.com/chart?cht=tx&chl=G_%7Bt%7D,再將這些https://chart.googleapis.com/chart?cht=tx&chl=G_%7Bt%7D平均(取期望值),就是https://chart.googleapis.com/chart?cht=tx&chl=V(S_%7Bt%7D)的估計值。

https://chart.googleapis.com/chart?cht=tx&chl=V(S_%7Bt%7D)為在時間點https://chart.googleapis.com/chart?cht=tx&chl=t上的State的Value

演算法相當簡單,只要把所有Return平均當成期望值
https://ithelp.ithome.com.tw/upload/images/20200905/20129922cwQRDgz41f.png

  • Monte Carlo有first-visite與every-visite的版本,差別只在同個epsiode裡同個state要不要全部計算。
  • 圖片標題上的Prediction為Policy Evaluation的另一種稱呼

Exploration and Exploitation

Monte Carlo Method也遵循著GPI的流程

https://ithelp.ithome.com.tw/upload/images/20200905/201299225nwk4eklOU.png

如果我們的Policy更新一直都是以https://chart.googleapis.com/chart?cht=tx&chl=%5Cmathrm%7Bargmax%7D%5Climits_%7Ba%7D%5C%20%5C%20q(s%5C%20%2C%5C%20a)更新的話,會造成我們的Agent停止探索更多的行為。
從例子上來看
https://ithelp.ithome.com.tw/upload/images/20200905/20129922lkTTcqlkIE.png

我們把每個State的Value Function都初始化為0,Agent在一開始為隨機策略,並在第一個episode走了塗上紅色的路線,獲得Reward = 5,假如https://chart.googleapis.com/chart?cht=tx&chl=%5Cgamma為1,那根據上面的Monte Carlo Method,https://chart.googleapis.com/chart?cht=tx&chl=s1%2C%5C%20%20s4%2C%5C%20s7%2C%5C%20s8%5C%20%2Cs9的Value Function都會變為5。Policy Improvement後的https://chart.googleapis.com/chart?cht=tx&chl=%5Cpi因為是根據greedy action,它會認為紅色這條路徑的Value比其他高,所以是最好的走法,導致之後的每一個episode都走同樣紅色的路線。其實不經過炸彈的Value會更高,但永遠都不會知道。

這種情況發生在用取樣方法的強化學習算法上,稱為Exploration and Exploitation trade-off

  • Exploration是指我們需要足夠的時間去探索未知的行為
  • Exploitation是指我們利用已知的知識,來走最佳的行為

上面的情形是因為我們只花了一個episode去exploration,導致Agent的經驗不足,有很多方法可以在這兩種行為中平衡,這邊我們主要談論最簡單的https://chart.googleapis.com/chart?cht=tx&chl=%5Cepsilon-greedy。

https://chart.googleapis.com/chart?cht=tx&chl=%5Chuge%20%5Cepsilon-greedy

https://chart.googleapis.com/chart?cht=tx&chl=%5Cepsilon-greedy的概念非常簡單,我們的policy有https://chart.googleapis.com/chart?cht=tx&chl=%5Cepsilon的機率會做隨機行為,https://chart.googleapis.com/chart?cht=tx&chl=1%20-%20%5Cepsilon的機率做greedy action,這樣就能有https://chart.googleapis.com/chart?cht=tx&chl=%5Cepsilon的機率去做exploration來學習環境。
https://chart.googleapis.com/chart?cht=tx&chl=%5Cepsilon-greedy是一種https://chart.googleapis.com/chart?cht=tx&chl=%5Cepsilon-soft policy,https://chart.googleapis.com/chart?cht=tx&chl=%5Cepsilon-soft policy指的是對於所有State與Action,都滿足https://chart.googleapis.com/chart?cht=tx&chl=%5Cpi(a%5C%20%5Cmid%5C%20s)%20%5Cgeq%20%5Cfrac%7B%5Cepsilon%7D%7B%5Cleft%7CA(s)%5Cright%7C%7D
像是random policy也是一種https://chart.googleapis.com/chart?cht=tx&chl=%5Cepsilon-soft方法,普遍我們比較常用的還是https://chart.googleapis.com/chart?cht=tx&chl=%5Cepsilon-greedy。

Monte Carlo Control

上面提到Prediction指的就是Policy Evaluation的部分,用來估計目前https://chart.googleapis.com/chart?cht=tx&chl=V_%7B%5Cpi%7D(s)的值,
而Control就是指Policy Improvement的部分,用來更新policy。

直接看演算法
https://ithelp.ithome.com.tw/upload/images/20200905/20129922hAQmjBvpfZ.png

  1. 根據當前的https://chart.googleapis.com/chart?cht=tx&chl=%5Cpi跑完整個episode
  2. 算每個時間點的https://chart.googleapis.com/chart?cht=tx&chl=G_%7Bt%7D
  3. https://chart.googleapis.com/chart?cht=tx&chl=G_%7Bt%7D的值append到(s,a)的list中,方便計算平均
  4. https://chart.googleapis.com/chart?cht=tx&chl=q_%7B%5Cpi%7D(s%5C%20%2C%5C%20a)更新成https://chart.googleapis.com/chart?cht=tx&chl=G_%7Bt%7D的平均值
  5. 依據https://chart.googleapis.com/chart?cht=tx&chl=%5Cepsilon-greedy更新https://chart.googleapis.com/chart?cht=tx&chl=%5Cpi

需要注意的是:

  • 需要跑完整個episode才能得到https://chart.googleapis.com/chart?cht=tx&chl=G_%7Bt%7D
  • https://chart.googleapis.com/chart?cht=tx&chl=G_%7Bt%7Dhttps://chart.googleapis.com/chart?cht=tx&chl=t%20%3D%20T算到https://chart.googleapis.com/chart?cht=tx&chl=t%20%3D%200比較方便
  • 不用https://chart.googleapis.com/chart?cht=tx&chl=V(s)而用https://chart.googleapis.com/chart?cht=tx&chl=q(s%5C%20%2C%5C%20a)的原因是為了方便計算https://chart.googleapis.com/chart?cht=tx&chl=argmax,不用特別去看下個State的Value
  • 每次episode結束後更新一次policy,這邊policy看似很複雜的更新其實就是https://chart.googleapis.com/chart?cht=tx&chl=%5Cepsilon的機率為隨機,https://chart.googleapis.com/chart?cht=tx&chl=1%20-%20%5Cepsilon為greedy
  • 這邊一樣是用first visit的方式,與every visit的方式差別不大,只要episode夠多都能夠收斂

Blackjack

今天我們使用gym裡blackjack環境

  1. 不知道blackjack是甚麼的話可以看維基百科,簡單來講就是跟莊家比手牌中的大小,大的就獲勝,但手牌不能超過21點,而莊家在17點一下會持續抽牌
  2. gym環境中的blackjack不包含特殊規則,且假設抽牌後牌會放回牌堆中,所以同樣一張牌可能出現不只一次

在blackjack中,只有兩種action:繼續抽牌、停止;三種reward:贏為+1,輸為-1,平手為0。
我們用Monte Carlo Method來找找看最佳的Value Function與Policy

import gym
import numpy as np
import sys
from collections import defaultdict

env = gym.make('Blackjack-v0')

num_episodes = 500000
gamma = 1.0
epsilon = 0.2

returns_sum = defaultdict(float)
returns_count = defaultdict(float)
Q = defaultdict(lambda: np.zeros(env.action_space.n))
policy = defaultdict(lambda: np.ones(env.action_space.n) / env.action_space.n)

先初始化需要的變數,這裡將returns、Q與policy都設為defaultdict,可以讓我們不用一開始就初始化state大小的array,有時候我們並不知道state總共有多少,或是state太多避免浪費空間。

def first_visit_update(episode):
    G = 0
    used = set()
    for idx, (state, action, reward) in enumerate(episode[::-1]):
        G = gamma * G + reward
        if (state, action) in used:
            continue
        returns_sum[(state, action)] += G
        returns_count[(state, action)] += 1
        Q[state][action] = returns_sum[(state, action)] / returns_count[(state, action)]
        A_star = np.argmax(Q[state])
        policy[state] = np.ones(env.action_space.n) * epsilon / env.action_space.n
        policy[state][np.argmax(Q[state])] += 1 - epsilon
        used.add((state, action))

定義first visit的update function,used用來判斷(state, action) pair是否visit過

def every_visit_update(episode):
    G = 0
    for idx, (state, action, reward) in enumerate(episode[::-1]):
        G = gamma * G + reward
        returns_sum[(state, action)] += G
        returns_count[(state, action)] += 1
        Q[state][action] = returns_sum[(state, action)] / returns_count[(state, action)]
        A_star = np.argmax(Q[state])
        policy[state] = np.ones(env.action_space.n) * epsilon / env.action_space.n
        policy[state][np.argmax(Q[state])] += 1 - epsilon

也可以用every visit的方法來更新Value

for i in range(num_episodes):
    state = env.reset()
    episode = []
    while True:
        action = np.random.choice(np.arange(env.action_space.n), p = policy[state])
        next_state, reward, done, info = env.step(action)
        episode.append((state, action, reward))
        if done:
            break
        state = next_state
    first_visit_update(episode)
    #every_visit_update(episode)
    print(f'\repisode: {i + 1}/{num_episodes}', end = '')
    sys.stdout.flush()

總共跑num_episodes次迴圈,每次迴圈先跟環境互動,並用一個list存放環境回傳的資訊。再用剛剛寫的update 更新Value

# evaluation
win = 0
for i in range(num_episodes):
    state = env.reset()
    while True:
        action = np.argmax(policy[state])
        next_state, reward, done, info = env.step(action)
        if reward == 1:
            win += 1
        if done:
            break
        state = next_state
print(f'\nWin Rate: {win / num_episodes}')

最後可以用求出的policy來看看我們的Agent效果好不好,記得這裡使用的是greedy action,我們不希望評估效能的時候還要繼續exploration。

最後勝率大約在43%左右,而隨機策略的勝率約為37%~38%,提升了5~6%

可以參考udacity裡的plot function來看我們的policy與value

from plot_utils import *

plot_policy(dict((k, np.argmax(v)) for k, v in Q.items()))
plot_blackjack_values(dict((k, np.max(v)) for k, v in Q.items()))

https://ithelp.ithome.com.tw/upload/images/20200906/20129922vUFrWtqOMv.pnghttps://ithelp.ithome.com.tw/upload/images/20200906/20129922CAYRysdKu9.png

可以對照Sutton書中的optimal policy與對應的value:
https://ithelp.ithome.com.tw/upload/images/20200906/20129922WXKzJr37vv.png
跟我們訓練出來得值差不多。

總結

Monte Carlo Method還有很多地方可以優化,像是

  • 使用Epsilon Decay,https://chart.googleapis.com/chart?cht=tx&chl=%5Cepsilon會隨著時間越久,越來越少。可以在訓練後期越來越接近greedy policy。
  • 使用Incremental Implementation,平均的部分可以改寫成incremental的形式,原本 https://chart.googleapis.com/chart?cht=tx&chl=%5Cfrac%7B1%7D%7Bn%7D 的部分可以換成任意0~1的數,此數也被稱為Learning Rate

我們可不可以不要用https://chart.googleapis.com/chart?cht=tx&chl=%5Cepsilon-greedy來達到Exploration and Exploitation的平衡呢?只要行為的policy與目標的policy分開就行了,明天將會介紹這種方法。


上一篇
[Day05]Policy Iteration and Value Iteration
下一篇
[Day07]On-Policy and Off-Policy
系列文
從根本學習Reinforcement Learning12
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言