1. 前言
上一篇博客我們介紹了價值迭代的原理。這一節我們實現強化學習里面的價值迭代的部分代碼(完整代碼GitHub)。
2. 價值迭代回顧
我們把注意點放在值函數上,等值函數收斂了,我們的策略也會收斂到最優值。
\[v^{T+1}(s) =max_{a} \sum_{s_{t+1}}p(s_{t+1}|s_t,a_t)[r_{a_t}^{s_{t+1}} + \gamma * v^T_{\pi}(s_{t+1})] \]
再對收斂值函數算狀態-行動值函數,通過狀態-行動值函數尋找最好的那個策略。這個步驟和策略迭代一樣,屬於策略提升,不同的是,價值迭代只要計算一次就能拿到最好的策略。
\[q^T_{\pi}(s_t,a_t)=\sum_{s_{t+1}}p(s_{t+1}|s_t,a_t)[r_{a_t}^{s_{t+1}} + \gamma * v^T_{\pi}(s_{t+1})]\;\;\;\;\;\;(2) \]
\[\pi^{T+1}(s) = argmax_aq^T_{\pi}(s,a)\;\;\;\;\;\;(3) \]
實現代碼:
class ValueIteration(object):
def value_iteration(self, agent, max_iter=-1):
"""
:param obj agent: 智能體
:param int max_iter: 最大迭代數
"""
iteration = 0
while True:
iteration += 1
# 保存算出的值函數
new_value_pi = np.zeros_like(agent.value_pi)
for i in range(1, agent.s_len):
value_sas = []
for j in range(0, agent.a_len):
# 對每一個狀態s和行動a,計算值函數
value_sa = np.dot(agent.p[j, i, :], agent.r + agent.gamma * agent.value_pi)
value_sas.append(value_sa)
# 從每個行動中,選出最好的值函數
new_value_pi[i] = max(value_sas)
# 前后2次值函數的變化小於一個閾值,結束
diff = np.sqrt(np.sum(np.power(agent.value_pi - new_value_pi, 2)))
if diff < 1e-6:
break
else:
agent.value_pi = new_value_pi
if iteration == max_iter:
break
print('Iter {} rounds converge'.format(iteration))
for i in range(1, agent.s_len):
for j in range(0, agent.a_len):
# 計算收斂后值函數的狀態-行動值函數
agent.value_q[i, j] = np.dot(agent.p[j, i, :], agent.r + agent.gamma * agent.value_pi)
# 取出最大的行動
max_act = np.argmax(agent.value_q[i, :])
agent.pi[i] = max_act
3. 總結
到現在為止,我們介紹完了強化學習中的兩個基本的最優策略算法。策略迭代和價值迭代。
但一個可悲的事實是,在很多實際問題中,我們無法得到游戲的全貌,也就是說,狀態轉移的信息\(P(s_{t+1}|s_t, a_t)\)無法獲得。
一般來說,我們知曉狀態轉移概率的問題稱為“基於模型”的問題(Model-based),將不知曉的稱為“無模型”問題(Model-free)。后面我們要繼續升級我們的問題,模擬一個真人去玩游戲,無法知道所有游戲的全貌。