基於Q_learning的寶藏獵人
技術標籤:強化學習
文章目錄
前言
本博文將簡單用Q-learning實現一個例子,在世界的右邊有寶藏, 探索者只要得到寶藏嚐到了甜頭, 然後以後就記住了得到寶藏的方法, 這就是他用強化學習所學習到的行為。
-o—T
T 就是寶藏的位置, o 是探索者的位置
Q-learning 是一種記錄行為值 (Q value) 的方法, 每種在一定狀態的行為都會有一個值 Q(s, a), 就是說 行為 a 在 s 狀態的值是 Q(s, a). s 在上面的探索者遊戲中, 就是 o 所在的地點了. 而每一個地點探索者都能做出兩個行為 left/right
如果在某個地點 s1, 探索者計算了他能有的兩個行為, a1/a2=left/right, 計算結果是 Q(s1, a1) > Q(s1, a2), 那麼探索者就會選擇 left 這個行為. 這就是 Q learning 的行為選擇簡單規則.
預設值
這一次需要的模組和引數設定:
import numpy as np
import pandas as pd
import time
N_STATES = 6 # 1維世界的寬度
ACTIONS = ['left', 'right'] # 探索者的可用動作
EPSILON = 0.9 # 貪婪度 greedy
ALPHA = 0.1 # 學習率
GAMMA = 0.9 # 獎勵遞減值
MAX_EPISODES = 13 # 最大回合數
FRESH_TIME = 0.3 # 移動間隔時間
Q 表
對於 tabular Q learning, 我們必須將所有的 Q values (行為值) 放在 q_table 中, 更新 q_table 也是在更新他的行為準則. q_table 的 index 是所有對應的 state (探索者位置), columns 是對應的 action (探索者行為)。
def build_q_table(n_states, actions):
table = pd.DataFrame(
np.zeros((n_states, len(actions))), # q_table 全 0 初始
columns=actions, # columns 對應的是行為名稱
)
return table
# q_table:
"""
left right
0 0.0 0.0
1 0.0 0.0
2 0.0 0.0
3 0.0 0.0
4 0.0 0.0
5 0.0 0.0
"""
定義動作
接著定義探索者是如何挑選行為的. 這是我們引入 epsilon greedy 的概念. 因為在初始階段, 隨機的探索環境, 往往比固定的行為模式要好, 所以這也是累積經驗的階段, 我們希望探索者不會那麼貪婪(greedy). 所以 EPSILON 就是用來控制貪婪程度的值. EPSILON 可以隨著探索時間不斷提升(越來越貪婪), 不過在這個例子中, 我們就固定成 EPSILON = 0.9, 90% 的時間是選擇最優策略, 10% 的時間來探索.
# 在某個 state 地點, 選擇行為
def choose_action(state, q_table):
state_actions = q_table.iloc[state, :] # 選出這個 state 的所有 action 值
if (np.random.uniform() > EPSILON) or (state_actions.all() == 0): # 非貪婪 or 或者這個 state 還沒有探索過
action_name = np.random.choice(ACTIONS)
else:
action_name = state_actions.argmax() # 貪婪模式
return action_name
環境反饋 S_, R
做出行為後, 環境也要給我們的行為一個反饋, 反饋出下個 state (S_) 和 在上個 state (S) 做出 action (A) 所得到的 reward ®. 這裡定義的規則就是, 只有當 o 移動到了 T, 探索者才會得到唯一的一個獎勵, 獎勵值 R=1, 其他情況都沒有獎勵.
def get_env_feedback(S, A):
# This is how agent will interact with the environment
if A == 'right': # move right
if S == N_STATES - 2: # terminate
S_ = 'terminal'
R = 1
else:
S_ = S + 1
R = 0
else: # move left
R = 0
if S == 0:
S_ = S # reach the wall
else:
S_ = S - 1
return S_, R
環境更新
接下來就是環境的更新了, 不用細看.
def update_env(S, episode, step_counter):
# This is how environment be updated
env_list = ['-']*(N_STATES-1) + ['T'] # '---------T' our environment
if S == 'terminal':
interaction = 'Episode %s: total_steps = %s' % (episode+1, step_counter)
print('\r{}'.format(interaction), end='')
time.sleep(2)
print('\r ', end='')
else:
env_list[S] = 'o'
interaction = ''.join(env_list)
print('\r{}'.format(interaction), end='')
time.sleep(FRESH_TIME)
強化學習主迴圈
最重要的地方就在這裡. 你定義的 RL 方法都在這裡體現. 在之後的教程中, 我們會更加詳細得講解 RL 中的各種方法, 下面的內容, 大家大概看看就行, 這節內容不用仔細研究.
def rl():
q_table = build_q_table(N_STATES, ACTIONS) # 初始 q table
for episode in range(MAX_EPISODES): # 回合
step_counter = 0
S = 0 # 回合初始位置
is_terminated = False # 是否回合結束
update_env(S, episode, step_counter) # 環境更新
while not is_terminated:
A = choose_action(S, q_table) # 選行為
S_, R = get_env_feedback(S, A) # 實施行為並得到環境的反饋
q_predict = q_table.loc[S, A] # 估算的(狀態-行為)值
if S_ != 'terminal':
q_target = R + GAMMA * q_table.iloc[S_, :].max() # 實際的(狀態-行為)值 (回合沒結束)
else:
q_target = R # 實際的(狀態-行為)值 (回合結束)
is_terminated = True # terminate this episode
q_table.loc[S, A] += ALPHA * (q_target - q_predict) # q_table 更新
S = S_ # 探索者移動到下一個 state
update_env(S, episode, step_counter+1) # 環境更新
step_counter += 1
return q_table
寫好所有的評估和更新準則後, 我們就能開始訓練了, 把探索者丟到環境中, 讓它自己去玩吧.
if __name__ == "__main__":
q_table = rl()
print('\r\nQ-table:\n')
print(q_table)
參考
https://mofanpy.com/tutorials/machine-learning/reinforcement-learning/general-rl/