昨天提到 TD learning 方法、介紹其思路,以及說明這個方法向之前介紹的兩個方法 (動態規劃、蒙地卡羅) 借鏡之處。今天我們將實作以 TD learning 方法估計狀態價值函數。
昨天提到與蒙地卡羅方法一樣,透過模擬並更新模擬中,所經狀態的狀態價值。以下是自訂的模擬函式:
def SimProc(init_state, init_action, state_value, steps, gamma, alpha, reward, trans_mat):
state = init_state
action = init_action
for step in range(steps):
# get next infromation
next_state = np.argmax(trans_mat[:, state, action])
next_action = np.random.randint(0,4)
record = [state, next_state, action, reward[next_state]]
# update state value
state_value[state] = GetValue(state_value, record, gamma, alpha)
# update infromation
state = next_state
action = next_action
if state == 0 or state == 15:
break
return state_value
這裡有幾個地方值得注意:
在計算價值的地方,TD learning 採用動態規劃方法的逼近方式,這邊使用昨天推論出的更新方法,更新狀態價值:
def GetValue(state_value, records, gamma, alpha):
state = records[0]
next_state = records[1]
action = records[2]
reward = records[3]
value = state_value[state] + alpha*(reward + gamma*state_value[next_state] - state_value[state])
return value
除了多了參數 需要設定,這邊並沒有特別需要注意的地方。
最後我們設定 GridWorld 環境與模擬相關的參數,這裡新增一個 參數,代表更新的比率,這邊我們設定 0.05。其餘的參數請見主函式:
def main(InitState, InitAction, Episodes):
# environment setting
StateValue = np.zeros([16])
Reward = np.full(16, -1)
Reward[0] = 0
Reward[-1] = 0
TransMat = np.load('./gridworld/T.npy')
# parameters
GAMMA = 0.99
ALPHA = 0.05
STEPS = 50
# execute
for episode in range(Episodes):
StateValue = SimProc(InitState, InitAction, StateValue, STEPS, GAMMA, ALPHA, Reward, TransMat)
PrintValue(StateValue, episode)
#time.sleep(1)
如果想要有慢慢更新的感覺,請將最後一行的 '#time.sleep(1)' 中,去掉 '#'。
完整程式請見 GitHub
這邊進行模擬的結果如下:
============================================================
[State-Value]
Episode: 1000
[[ 0. -8.91641221 -14.0491088 -15.2773621 ]
[ -9.67885868 -12.95041551 -14.37948861 -14.07001144]
[-14.60779153 -14.85819826 -13.01810753 -7.45157775]
[-16.86235211 -14.72329853 -9.31593479 0. ]]
============================================================
我們可以觀察到,「狀態價值」與「該位置和終點的距離」,符合我們的期待與過去方法的結果。那麼,有了狀態價值後,我們就得開始考慮怎麼控制了。