本文作者:hhh5460
本文地址:https://www.cnblogs.com/hhh5460/p/10146554.html
說明:將之前 q-learning 實現的例一,用 saras 重新寫了一遍。具體問題這里就不多說了。
0. q-learning 與 saras 偽代碼的對比
圖片來源:https://morvanzhou.github.io/tutorials/machine-learning/reinforcement-learning/3-1-A-sarsa/(莫凡)
1. q-learning 與 saras 真實代碼對比
a). q-learning 算法
# 探索學習13次 for i in range(13): # 0.從最左邊的位置開始(不是必要的) current_state = 0 # 1.進入循環,開始探索學習 while current_state != states[-1]: # 2.取當前狀態下的合法動作中,隨機(或貪婪)地選一個作為 當前動作 if random.uniform(0,1) > epsilon: # 探索 current_action = random.choice(get_valid_actions(current_state)) else: #current_action = q_table.ix[current_state].idxmax() # 這種寫法是有問題的!二維迷宮有機會陷入死鎖 s = q_table.ix[current_state].filter(items=get_valid_actions(current_state)) current_action = random.choice(s[s==s.max()].index) # 可能多個最大值,當然,一個更好 #3.執行當前動作,得到下一個狀態(位置) next_state = get_next_state(current_state, current_action) # 4.下個狀態的獎勵 next_state_reward = rewards[next_state] # 5.取下一個狀態所有的Q value,待取其最大值 next_state_q_values = q_table.ix[next_state, get_valid_actions(next_state)] # 6.根據貝爾曼方程,更新 Q table 中當前狀態-動作對應的 Q value,有max! q_table.ix[current_state, current_action] += alpha * (rewards[next_state] + gamma * next_state_q_values.max() - q_table.ix[current_state, current_action]) # 7.進入下一個狀態(位置) current_state = next_state
b). saras 算法
# 探索學習13次 for i in range(13): # 0.從最左邊的位置開始(不是必要的) current_state = 0 # 1.取當前狀態下的一個合法動作 if random.uniform(0,1) > epsilon: # 探索 current_action = random.choice(get_valid_actions(current_state)) else: # 利用(貪婪) s = q_table.ix[current_state].filter(items=get_valid_actions(current_state)) current_action = random.choice(s[s==s.max()].index) # 可能多個最大值,當然,一個更好 # 2.進入循環,開始探索學習 while current_state != states[-1]: # 3.執行當前動作,得到下一個狀態(位置) next_state = get_next_state(current_state, current_action) # 4.取下個狀態下的一個合法動作 if random.uniform(0,1) > epsilon: # 探索 next_action = random.choice(get_valid_actions(next_state)) else: # 利用(貪婪) s = q_table.ix[next_state].filter(items=get_valid_actions(next_state)) next_action = random.choice(s[s==s.max()].index) # 可能多個最大值,當然,一個更好 # 5.下個狀態的獎勵 next_state_reward = rewards[next_state] # 6.取下個狀態,下個動作對應的一個Q value next_q_value = q_table.ix[next_state, next_action] # 7.更新 Q table 中當前狀態-動作對應的 Q value,無max! q_table.ix[current_state, current_action] += alpha * (next_state_reward + gamma * next_q_value - q_table.ix[current_state, current_action]) # 8.進入下一狀態、下一動作 current_state, current_action = next_state, next_action
2. 完整代碼
''' -o---T # T 就是寶藏的位置, o 是探索者的位置 ''' # 作者: hhh5460 # 時間:20181219 import pandas as pd import random import time epsilon = 0.9 # 貪婪度 greedy alpha = 0.1 # 學習率 gamma = 0.8 # 獎勵遞減值 states = range(6) # 狀態集。從0到5 actions = ['left', 'right'] # 動作集。也可添加動作'none',表示停留 rewards = [0,0,0,0,0,1] # 獎勵集。只有最后的寶藏所在位置才有獎勵1,其他皆為0 q_table = pd.DataFrame(data=[[0 for _ in actions] for _ in states], index=states, columns=actions) def update_env(state): '''更新環境,並打印''' env = list('-----T') # 環境 env[state] = 'o' # 更新環境 print('\r{}'.format(''.join(env)), end='') time.sleep(0.1) def get_next_state(state, action): '''對狀態執行動作后,得到下一狀態''' global states # l,r,n = -1,+1,0 if action == 'right' and state != states[-1]: # 除末狀態(位置),向右+1 next_state = state + 1 elif action == 'left' and state != states[0]: # 除首狀態(位置),向左-1 next_state = state -1 else: next_state = state return next_state def get_valid_actions(state): '''取當前狀態下的合法動作集合,與reward無關!''' global actions # ['left', 'right'] valid_actions = set(actions) if state == states[0]: # 首狀態(位置),則 不能向左 valid_actions -= set(['left']) if state == states[-1]: # 末狀態(位置),則 不能向右 valid_actions -= set(['right']) return list(valid_actions) for i in range(13): #current_state = random.choice(states) current_state = 0 if random.uniform(0,1) > epsilon: # 探索 current_action = random.choice(get_valid_actions(current_state)) else: # 利用(貪婪) #current_action = q_table.ix[current_state].idxmax() # 這種寫法是有問題的! s = q_table.ix[current_state].filter(items=get_valid_actions(current_state)) current_action = random.choice(s[s==s.max()].index) # 可能多個最大值,當然,一個更好 update_env(current_state) # 環境相關 total_steps = 0 # 環境相關 while current_state != states[-1]: next_state = get_next_state(current_state, current_action) if random.uniform(0,1) > epsilon: # 探索 next_action = random.choice(get_valid_actions(next_state)) else: # 利用(貪婪) #next_action = q_table.ix[next_state].idxmax() # 這種寫法是有問題的!可能會陷入死鎖 s = q_table.ix[next_state].filter(items=get_valid_actions(next_state)) next_action = random.choice(s[s==s.max()].index) # 可能多個最大值,當然,一個更好 next_state_reward = rewards[next_state] next_q_value = q_table.ix[next_state, next_action] q_table.ix[current_state, current_action] += alpha * (next_state_reward + gamma * next_q_value - q_table.ix[current_state, current_action]) current_state, current_action = next_state, next_action update_env(current_state) # 環境相關 total_steps += 1 # 環境相關 print('\rEpisode {}: total_steps = {}'.format(i, total_steps), end='') # 環境相關 time.sleep(2) # 環境相關 print('\r ', end='') # 環境相關 print('\nq_table:') print(q_table)