強化學習算法復現(四):n步自舉法的價值預測能力_隨機遊走問題

【馬爾可夫收益過程(Markov reward process , MRP)】是指不包含動作的馬爾可夫決策過程,在只關心預測問題時使用的模型。

問題描述:
以中心狀態C開始,在每個時刻以相同的概率向左或向右移動一個狀態,在兩端終止,episode終止於最右側時會有+1的收益,除此之外收益均爲0。
在這裏插入圖片描述
對於19個狀態的隨機遊走問題,其左端收益爲-1,右端收益爲+1,其真實的價值應爲[ 0. , -0.9, -0.8, -0.7, -0.6, -0.5, -0.4, -0.3, -0.2, -0.1, 0. , 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 0. ]


導入所需要的包:

import numpy as np
import matplotlib
import matplotlib.pyplot as plt
from tqdm import tqdm

plt.rcParams['font.sans-serif'] = ['SimHei']  # 正確顯示中文
plt.rcParams['axes.unicode_minus'] = False  # 正確顯示正負號

問題描述:

# 共有19個狀態
N_STATES = 19

# 折扣係數
GAMMA = 1

# 狀態合計【1,2,3,4,……,19】
STATES = np.arange(1, N_STATES + 1)

# 起始狀態_中間位置開始
START_STATE = (N_STATES+1)/2

# 兩個終止狀態
# S=0時,左邊終止 reward=-1    
# S=20時,右邊終止 reward=1
END_STATES = [0, N_STATES + 1]

# 隨機遊走問題中真實的價值函數,用來通過誤差評比各種算法的預測能力
TRUE_VALUE = np.arange(-20, 22, 2) / 20.0
TRUE_VALUE[0] = TRUE_VALUE[-1] = 0 #第一個和最後一個都是0

環境交互函數:(隨機action)

def env_step(state):
    
     # 隨機遊走,更新state
    if np.random.binomial(1, 0.5) == 1:
        next_state = state + 1
    else:
        next_state = state - 1

    # 根據state ,反饋回reward     
    if next_state == 0:
        reward = -1
    elif next_state == 20:
        reward = 1
    else:
        reward = 0
    
    done = False
    if next_state in END_STATES:
        done = True   # 到達終點
    
    info=' '
    return next_state,reward,done,info

一、n-steps TD method(n步自舉法)預測隨機遊走問題的狀態價值

def temporal_difference(value, n, alpha):
# @value: 更新對象——狀態價值評估結果
# @n: 每相隔幾步進行更新
# @alpha: 學習率
    state = START_STATE  # 初始化state,出發
    time = 0
    
    # 儲存一個episode中的state and reward
    states = [state]
    rewards = [0]

    T = float('inf')    # 幕序列時長到正無窮
    while True: # episode開始
        time += 1

        if time < T:
            next_state, reward, done, info = env_step(state)
            states.append(next_state)
            rewards.append(reward)

            if done:
                T = time   # 到達終點
                
        #更新第update_num個狀態        
        update_num = time - n 
        if update_num >= 0:
            returns = 0.0
            # 計算累計收益
            for t in range(update_num + 1, min(T, update_num + n) + 1):
                returns += pow(GAMMA, t - update_num - 1) * rewards[t]
            # 加入折後回報
            if time <= T:
                s=int(states[(update_num + n)])
                returns += pow(GAMMA, n) * value[s]
            
            state_to_update = int(states[update_num])
            if state_to_update not in END_STATES: #兩個終端狀態不進行估計
                value[state_to_update] += alpha * (returns - value[state_to_update])
                
                
        if done:
            break# episode結束
        state = next_state  # 更新state

選擇一組超參數,觀察算法收斂性

# 超參數選擇
n = 8  # 自舉數
alpha = 0.2 # 步長
episode_num = 100 #玩幾局遊戲

episodes = np.arange(1, episode_num+1)
value = np.zeros(N_STATES + 2) #初始化
errors = []
error = 0.0

for ep in range(0,episode_num):
    value = temporal_difference(value, n, alpha)  # 更新價值
    error += np.sqrt(np.sum(np.power(value - TRUE_VALUE, 2)) / N_STATES)
    error_a = error / (ep+1)
    errors.append(error_a)

plt.plot(episodes, errors)    
plt.xlabel('遊戲環節數')
plt.ylabel('與真實價值的誤差爲') 
plt.show()

在這裏插入圖片描述

對比不同步長與不同學習率對預測能力的影響

def figure7_2():
    # 步長分別爲:[  1,   2,   4,   8,  16,  32,  64, 128]
    steps = np.power(2, np.arange(0, 8))

    # 學習率分別爲:[0. , 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1. ]
    alphas = np.arange(0, 1.1, 0.1)

    # 進行20次遊戲
    episodes = 20

    # 進行10次獨立實驗測試
    runs = 10

    # errors數組存儲每個steps和每個alpha對應的error
    errors = np.zeros((len(steps), len(alphas)))
    
    for run in tqdm(range(0, runs)):#進度條
        for step_ind, step in enumerate(steps):
            for alpha_ind, alpha in enumerate(alphas):
                value = np.zeros(N_STATES + 2) #初始化21個value
                for ep in range(0, episodes):
                    temporal_difference(value, step, alpha)
                    errors[step_ind, alpha_ind] += np.sqrt(np.sum(np.power(value - TRUE_VALUE, 2)) / N_STATES)
    errors /= episodes * runs

    for i in range(0, len(steps)):
        plt.plot(alphas, errors[i, :], label='n = %d' % (steps[i]))
    plt.xlabel('不同學習率α')
    plt.ylabel('19個狀態前10幕經驗的均方誤差')
    plt.ylim([0.2, 0.6])# 縱軸座標範圍
    plt.legend()

    plt.savefig('figure_7_2.png')
    plt.show()

figure7_2()

在這裏插入圖片描述
n爲1時是單步TD、n爲正無窮時是MC預測。
由此可見,n去中間值時的預測效果更好,這也證明了將單步TD和MC方法推廣至N步自舉法能夠得到更好的結果。其中學習率的調節也應隨着n的調節變化。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章