部分專有名詞在上一篇文章有介紹,本文不作過多贅述。
Q-Learning是強化學習演算法中value-based的演算法,Q即為Q(s,a),就是在某一個時刻的state狀態下,採取動作a能夠獲得收益的期望,環境會根據agent的動作反饋相應的reward獎賞,所以演算法的主要思想就是將state和action構建成一張Q_table表來存儲Q值,然後根據Q值來選取能夠獲得最大收益的動作。
Q-Learning
state
agent
reward
action
Q_table
Q-learning的主要優勢就是使用了時間差分法(融合了蒙特卡洛和動態規劃)能夠進行off-policy的學習,使用貝爾曼方程可以對馬爾科夫過程求解最優策略,本文對其中演算法不進行推導,會另外寫一篇推導的文章。
我們還是用一開始舉的做作業的例子來說明:
參數介紹
Epsilon greedy
alpha
gamma
背景
在一個一維時間,在世界的右邊有寶藏,探險者只要得到寶藏嘗到了甜頭,以後就會記住得到寶藏的方法,這就是他用強化學習所學習到的行為。
o
left/right
Q(s,a)
行為準則
預設參數
import numpy as np import pandas as pd import time
np.random.seed(2) # reproducible
N_STATES = 6 #一維世界的寬度 ACTIONS = [left,right] #探索者可用的動作 EPSILON = 0.9 #greedy貪婪度 ALPHA = 0.1 #學習率 GAMMA = 0.9 #獎勵遞減值 MAX_EPISODES = 13 #最大回合數 FRESH_TIME = 0.3 #每回合移動間隔時間
Q表
我們要將所有Q values放在q_table中,更新q_table也是在更新他的行為準則。q_table的index是所有對應的state(o所在的位置),columns是對應的action(探險者選擇left或者right)
Q values
q_table
index
state(o所在的位置)
columns
action(探險者選擇left或者right)
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 """
定義action
接著定義探險者是如何挑選行為的,這就是我們引入epsilon greedy的概念。因為在初始階段,隨機的探索環境,往往比固定的行為模式要好,所以這也是累積經驗的階段,我們希望探險者不那麼貪婪(greedy),所以EPSILON就是用來控制貪婪程度的值。EPSILON可以隨著探險時間不斷提升(越來越貪婪),不過在這個例子中,我們就固定EPSILON=0.9,90%的時間是選擇最優策略,10%的時間來探索。
epsilon greedy
(greedy)
EPSILON
def choose_action(state, q_table): state_actions = q_table.iloc[state, :] # 選出這個state的所有 action的value值 if (np.random.uniform() > EPSILON) or (state_actions.all() == 0): #非貪婪 or 或者這個 state 還沒有探索過 action_name = np.random.choice(ACTIONS) else: action_name = state_actions.idxmax() # 貪婪模式 return action_name
環境的反饋S_,R
做出行為後,環境也要給我們的行為一個反饋,反饋出下一個state(S_)和上一個state(S)做出action(A)所得到的reward(R)。這裡定義的規則是,只有當o移動到了T(探險者獲取了寶藏),探險者才會得到唯一的獎勵,獎勵值R=1,其他情況沒有獎勵。
state(S_)
state(S)
action(A)
reward(R)
T
def get_env_feedback(S,A): if A== right: #往右探險 if S == N_STATES - 2: #找到寶藏 S_ = terminal R = 1 else: S_ = S + 1 R = 0 else: #往左探險 R = 0 if S == 0: S_ = S #碰壁 else: S_ = S - 1 return S_,R
環境更新
接下來就是環境的更新了,這裡不多贅述。
def update_env(S, episode, step_counter): env_list = [-]*(N_STATES-1) + [T] # ---------T our environment if S == terminal: interaction = Episode %s: total_steps = %s % (episode+1, step_counter) print( {}.format(interaction), end=) time.sleep(2) print( , end=) else: env_list[S] = o interaction = .join(env_list) print( {}.format(interaction), end=) time.sleep(FRESH_TIME)
強化學習的主循環
最重要的地方就是這裡,將剛才理論部分我們講解到的演算法實現出來。
def rl(): q_table = bulid_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
q_table.loc[S,A] += ALPHA*(q_target - q_predict) #q_table更新 S = S_ #更新探索者位置
update_env(S,episode,step_counter+1)
step_counter += 1 return q_table
結果
我們可以看到,一開始沒有任何經驗的探險者需要非常多次的嘗試才能找到寶藏,而隨著探險次數的增多,最後就可以自己走到寶藏的地方了。
參考:
推薦閱讀: