任务描述
本关任务:编写一个能实现有模型价值迭代的小程序。
相关知识
为了完成本关任务,你需要掌握:1.有模型价值迭代,2.有模型价值迭代实现。
有模型价值迭代
价值迭代是一种利用迭代求解最优价值函数进而求解最优策略的方法。利用 Bellman
最优方程迭代求解最优策略的价值函数,并进而求得最优策略。
与策略评估的情形类似,价值迭代算法有参数来控制迭代的终止条件,可以是误差容忍度 ϑmax 或是最大迭代次数 kmax。
有模型价值迭代实现
一个价值迭代算法,这个价值迭代算法中先初始化状态价值函数,然后用 Bellman
最优方程来更新状态价值函数。只要迭代次数足够多,最终会收敛到最优价值函数。得到最优价值函数后,就能很轻易地给出确定性的最优策略。
有模型价值迭代算法
输入:动力系统p。 输出:最优策略估计π。 参数:策略评估需要的参数。
- (初始化)v0(s)←任意值,s∈S。如果有最终状态,v0(s终止)←0。
- (迭代)对于k←0,1,2,3,..., 执行以下步骤。
- 对于s∈S,逐一更新
vk+1(s)←amax{r(s,a)+γs′∑p(s′∣s,a)vk(s′)}
- 对于s∈S,逐一更新
动作价值函数 python 实现
def v2q(env, v, s=None, gamma=1.):
if s is not None:
q = np.zeros(env.unwrapped.nA)
for a in range(env.unwrapped.nA):
for prob, next_state,reward,done in env.unwrapped.P[s][a]:
q[a] += prob * (reward + gamma * v[next_state] * (1. - done))
else:
q = np.zeros((env.unwrapped.nS, env.unwrapped.nA))
for s in range((env.unwrapped.nS)):
q[s] = v2q(env, v, s, gamma)
return q
- 如果满足误差容忍度(即对于s∈S 均有 ∣vk+1(s)−vk(s)∣<ϑ)或达到最大迭代次数(即k=kmax ),则跳出循环。
上述原理的 python 实现
import numpy as np
import gym
env = gym.make('FrozenLake-v0')
env = env.unwrapped
gamma = 1
tolerant = 1e-6
v = np.zeros(env.unwrapped.nS)
while True:
delta = 0
for s in range(env.unwrapped.nS):
vmax = max(v2q(env, v, s, gamma))
delta = max(delta, abs(v[s]-vmax))
v[s] = vmax
if delta < tolerant:
break
- (策略)根据价值函数输出确定性策略 π,使得
π∗(s)←aargmax{r(s,a)+γs′∑p(s′∣s,a)vk+1(s′)},s∈S
上述公式 python 实现
import numpy as np
import gym
env = gym.make('FrozenLake-v0')
env = env.unwrapped
gamma = 1
policy = np.zeros((env.unwrapped.nS, env.unwrapped.nA))
for s in range(env.unwrapped.nS):
a = np.argmax(v2q(env, v, s, gamma))
policy[s][a] = 1.
print(policy, v)
参考资料:《强化学习:原理与Python实现》 肖智清 著
编程要求
根据提示,在右侧编辑器补充代码,实现案例:冰面滑行,冰面滑行问题(FrozenLake-v0)是扩展库 Gym 里内置的一个文本环境任务。该问题的背景是这样的:在一个大小为的湖面上,有些地方结冰了,有些地方没有结冰。这个环境的状态空间有 16 个不同的状态{s0,s1,s2,...,s15},表示当前处在哪一个位置;动作空间有 4 个不同的动作{a0,a1,a2,a3}。
import numpy as np
import gym
env = gym.make('FrozenLake-v0')
env = env.unwrapped
# 用策略执行一个回合
def play_policy(env, policy, render=False):
total_reward = 0.
observation = env.reset()
while True:
if render:
env.render()
action = np.random.choice(env.action_space.n, p=policy[observation])
observation, reward, done, _=env.step(action)
total_reward += reward
if done:
break
return total_reward
# 动作价值函数
def v2q(env, v, s=None, gamma=1.):
if s is not None:
q = np.zeros(env.unwrapped.nA)
for a in range(env.unwrapped.nA):
for prob, next_state,reward,done in env.unwrapped.P[s][a]:
q[a] += prob * (reward + gamma * v[next_state] * (1. - done))
else:
q = np.zeros((env.unwrapped.nS, env.unwrapped.nA))
for s in range((env.unwrapped.nS)):
q[s] = v2q(env, v, s, gamma)
return q
# 有模型价值迭代求解
# 价值迭代的实现
###### Begin ######
def iterate_value(env, gamma=1, tolerant=1e-6):
v = np.zeros(env.unwrapped.nS)
while True:
delta = 0
for s in range(env.unwrapped.nS):
q_values = v2q(env, v, s, gamma)
v_new = np.max(q_values)
delta = max(delta, np.abs(v_new - v[s]))
v[s] = v_new
if delta < tolerant:
break
policy_vi = np.zeros((env.unwrapped.nS, env.unwrapped.nA))
for s in range(env.unwrapped.nS):
q_values = v2q(env, v, s, gamma)
best_action = np.argmax(q_values)
policy_vi[s][best_action] = 1
return policy_vi, v
###### End ######
# 利用价值迭代算法求解最优策略
policy_vi, v_vi = iterate_value(env)
episode_rewards = [play_policy(env, policy_vi) for _ in range(100)]
# print('价值迭代 平均奖励: {}'.format(np.mean(episode_rewards)))
print('状态价值函数 =')
print(v_vi.reshape(4, 4))
print('最优策略 =')
print(np.argmax(policy_vi, axis=1).reshape(4, 4))