2019.12.09
一、動態規劃 之 策略迭代
看懂值迭代的代碼之後,策略迭代變得簡單了許多,策略迭代主要包括:策略評估和策略改進。
策略迭代的步驟如下:
1.初始化隨機策略。
2.求得隨機策略下的值函數,並判斷其是否爲當下策略的最優,直到得到當下策略的最優值函數。
3.根據得到的當下策略的最優值函數,得到新的策略。
4.判斷新的策略是否爲最優(即判斷新舊策略是否相同)。(2.3.4步爲策略評估)
5.如果不是最優,不斷進行迭代。(策略改進)
6.重複2~5步,直到找到最優策略。
詳細代碼及細節如下:
import numpy as np
import gym
env = gym.make('FrozenLake-v0')
env.render()
# 根據給定的策略Π計算值函數V(s)
def compute_value_function(policy, gamma = 1.0):
# initialize value table with zeros
value_table = np.zeros(env.nS)
# 設置學習速率
threshold = 1e-10
while True:
# copy the value table to the updated_value_table
updated_value_table = np.copy(value_table)
# 對每一個狀態s,根據給定的策略計算值函數
for state in range(env.nS):
action = policy[state]
# 計算某個確定狀態s下,策略所選定的確定的動作a的值
value_table[state] = sum([trans_prob * (reward_prob + gamma * updated_value_table[next_state])
for trans_prob, next_state, reward_prob, _ in env.P[state][action]])
if (np.sum(np.fabs(updated_value_table - value_table)) <= threshold):
break
return value_table
# 根據給定的值函數V(s)計算策略Π
# 根據值函數V(s),計算出每個狀態s下的每個行爲a∈A的Q value,並選擇具有最大Q value的行爲作爲s的策略。
def extract_policy(value_table, gamma = 1.0):
# initialize the policy with zeros
policy = np.zeros(env.observation_space.n)
# 計算每個狀態s∈S
for state in range(env.observation_space.n):
# initialize the Q table for a state
Q_table = np.zeros(env.action_space.n)
# 計算具體某個狀態s的每個a∈A
for action in range(env.action_space.n):
# 計算具體某個a的每個s'∈S
for next_sr in env.P[state][action]:
# 獲取具體(s, a)的,各個s'∈S的概率、獎勵以及下個狀態s'是什麼
trans_prob, next_state, reward_prob, _ = next_sr
Q_table[action] += (trans_prob * (reward_prob + gamma * value_table[next_state]))
# 把Q value的最大值的索引(即代表某個動作或策略)賦給policy
policy[state] = np.argmax(Q_table)
return policy
# 執行整體策略迭代
# 判斷是否達到最佳策略
def policy_iteration(env, gamma = 1.0):
#initial policy with zeros
old_policy = np.zeros(env.observation_space.n)
no_of_iterations = 200000
for i in range(no_of_iterations):
# 計算新的值函數
new_value_function = compute_value_function(old_policy, gamma)
# 根據新的值函數得到新的策略
new_policy = extract_policy(new_value_function, gamma)
# 判斷是否達到最佳策略
if (np.all(old_policy == new_policy)):
print('到第 %d 步達到最優' %(i+1))
break
old_policy = new_policy
return new_policy
print(policy_iteration(env))
針對以上代碼,有如下筆記:
1.python中sum()的用法
2.經實測,一下兩段代碼效果相同:
# 對每一個狀態s,根據給定的策略計算值函數
for state in range(env.nS):
action = policy[state]
#計算某個確定狀態s下,策略所選定的確定的動作a的值
value_table[state] = sum([trans_prob * (reward_prob + gamma * updated_value_table[next_state])
for trans_prob, next_state, reward_prob, _ in env.P[state][action]])
# 對每一個狀態s,根據給定的策略計算值函數
for state in range(env.nS):
action = policy[state]
next_states_rewards = []
# 對具體某次循環的某個具體的(s, a),對每個s'∈S進行循環。
for next_sr in env.P[state][action]:
# 獲取具體(s, a)的,各個s'∈S的概率、獎勵以及下個狀態s'是什麼
trans_prob, next_state, reward_prob, _ = next_sr
next_states_rewards.append((trans_prob * (reward_prob + gamma * updated_value_table[next_state])))
value_table[state] = np.sum([next_states_rewards])
對值DP算法的值迭代和策略迭代,有以下說明:
以上兩段算法的代碼是以冰凍湖爲例,是在狀態轉移概率p和獎勵r已知的前提下編寫的。這也是動態規劃算法的缺點之一,必須要事先知道轉移概率和獎勵。
二、MDP建模示例
將冰凍湖問題建模爲MDP:(可參考《python強化學習實戰》)
1.定義狀態、行爲、轉移概率、獎勵、策略函數、值函數和Q函數。
2.利用Bellman最優方程,表示值函數和Q函數,求解該方程即可得到最優策略。
3.採用動態規劃的方法來求解Bellman最優方程。