【馬爾可夫收益過程(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的調節變化。