【強化學習】python 實現 saras 例一


本文作者: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)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM