(2019年8月第1版第1次印刷)
Gym 0.25版本更新了API,GitHub代码已相应更新。代码以GitHub上为准。
本勘误文档中,行数计算“第
记为
记为
动作空间是Dicrete(3)
动作空间是Discrete(3)
作者注: “轨道”又称为“轨迹”。本书中这两个词混用。
作者注: 这种带折扣的回报定义既可以用于回合制任务,也可以用于连续性任务,是一种统一的表示。
为
为
有观点认为:用动作价值表示状态价值的表达式,或是用状态价值表示动作价值的表达式,不能称为Bellman方程;而用动作价值表示动作价值的表达式,或是用状态价值表示状态价值的表达式,才可以称为Bellman方程。
xxxxxxxxxximport sympyfrom sympy import symbolssympy.init_printing()v_hungry, v_full = symbols('v_hungry v_full')q_hungry_eat, q_hungry_none, q_full_eat, q_full_none = \symbols('q_hungry_eat q_hungry_none q_full_eat q_full_none')alpha, beta, x, y, gamma = symbols('alpha beta x y gamma')system = sympy.Matrix(((1, 0, x-1, -x, 0, 0, 0),(0, 1, 0, 0, -y, y-1, 0),(-gamma, 0, 1, 0, 0, 0, -2),((alpha-1)*gamma, -alpha*gamma, 0, 1, 0, 0, 4*alpha-3),(-beta*gamma, (beta-1)*gamma, 0, 0, 1, 0, -4*beta+2),(0, -gamma, 0, 0, 0, 1, 1) )) # 标准形式的系数矩阵sympy.solve_linear_system(system,v_hungry, v_full,q_hungry_none, q_hungry_eat, q_full_none, q_full_eat)
其中
如果对于任意
如果对于任意
(共2处)
所有的下标
xxxxxxxxxximport sympyfrom sympy import symbolssympy.init_printing()alpha, beta, gamma = symbols('alpha beta gamma')v_hungry, v_full = symbols('v_hungry v_full')q_hungry_eat, q_hungry_none, q_full_eat, q_full_none = \symbols('q_hungry_eat q_hungry_none q_full_eat q_full_none')xy_tuples = ((0, 0), (1, 0), (0, 1), (1, 1))for x, y in xy_tuples: # 分类讨论system = sympy.Matrix(((1, 0, x-1, -x, 0, 0, 0),(0, 1, 0, 0, -y, y-1, 0),(-gamma, 0, 1, 0, 0, 0, -2),((alpha-1)*gamma, -alpha*gamma, 0, 1, 0, 0, 4*alpha-3),(-beta*gamma, (beta-1)*gamma, 0, 0, 1, 0, -4*beta+2),(0, -gamma, 0, 0, 0, 1, 1) ))result = sympy.solve_linear_system(system,v_hungry, v_full,q_hungry_none, q_hungry_eat, q_full_none, q_full_eat, simplification=True)msgx = 'v(饿) = q(饿,{}吃)'.format('' if x else '不')msgy = 'v(饱) = q(饱,{}吃)'.format('不' if y else '')print('==== {}, {} ==== x = {}, y = {} ===='.format(msgx, msgy, x, y))display(result)
接下来进一步分析这个方程组。比较最优价值的方程组和一般策略的价值方程组可以发现,最优策略价值方程组的解正是在一般策略方程组的解中
进而比较大小可以只比较分子部分。
首先来比较
即
两边除以
注意到
接下来比较
即
两边除以
注意到
综合上述分析,有以下四种情况。
情况I:
情况II:
其中
情况III:
其中
情况IV:
其中
作者注:用线性规划求解最优状态价值的详细证明可见《Markov Decision Processes: Discrete Stochastic Dynamic Programming》(Martin Puterman)的第6.9节。证明大致如下:当
情况I:
即饿时不吃,饱时吃。
情况II:
即一直吃。
情况III:
即一直
情况IV:
即
对于一组特定的数值,求解则更加直接。例如,当
回合奖励为各步奖励之。
回合奖励为各步奖励之和。
xxxxxxxxxxdef play_once(env, policy):total_reward = 0state = env.reset()while True:loc = np.unravel_index(state, env.shape)print('状态 = {}, 位置 = {}'.format(state, loc), end=' ')action = np.random.choice(env.nA, p=policy[state])state, reward, done, _ = env.step(action)print('动作 = {}, 奖励 = {}'.format(action, reward))total_reward += rewardif done:breakreturn total_reward
Bellmn期望方程为
Bellman期望方程为
Bellan期望方程:
Bellman期望方程:
用Bellman方程求解状态价值和动作价值
xxxxxxxxxxdef evaluate_bellman(env, policy, gamma=1.):a, b = np.eye(env.nS), np.zeros((env.nS))for state in range(env.nS - 1):for action in range(env.nA):pi = policy[state][action]for p, next_state, reward, done in env.P[state][action]:a[state, next_state] -= (pi * gamma * p)b[state] += (pi * reward * p)v = np.linalg.solve(a, b)q = np.zeros((env.nS, env.nA))for state in range(env.nS - 1):for action in range(env.nA):for p, next_state, reward, done in env.P[state][action]:q[state][action] += ((reward + gamma * v[next_state]) * p)return v, q
计算这个动态规划问题
计算这个线性规划问题
可以应用下列线性规划求解最优动作价值
可以应用下列线性规划求解最优状态价值
这里的
用动作价值表示动作价值的形式
用状态价值表示状态价值的形式
考虑到
考虑到
进而易知
进而易知
如果
如果
(fix point)
(fixed point)
对于两个确定性的策略
对于策略
作者注:这里的修改使得策略改进定理不仅可以用于确定性策略的改进。这样修改后,相关的结论就可以用于后续章节中(如第60~61页的4.1.3节)。
不等式(3-1)等价于
其中的期望是针对用策略
考虑到
所以
进而有
作者注:Gym 0.19版本将FrozenLake-v0改为FrozenLake-v1。
作者注:Gym 0.22删除了DiscreteEnv类,所以env.unwrapped.nS和env.unwrapped.nA不再可用。建议用env.observation_space.n替换env.unwrapped.nA,用env.action_space.n替换env.unwrapped.nA。
这个函数使用theta作
这个函数使用tolerant作
xxxxxxxxxxpolicy_vi, v_vi = iterate_value(env)print('状态价值函数 =')print(v_vi.reshape(4, 4))print('最优策略 =')print(np.argmax(policy_vi, axis=1).reshape(4, 4))episode_rewards = [play_policy(env, policy_vi) for _ in range(100)]print("价值迭代 平均奖励:{}".format(np.mean(episode_rewards)))
同时满足
初始化动作价值估计
初始化状态价值估计
态
态
证明:对于某个
改进后的策略为
证明:考虑在
在3.2.2节策略改进定理的证明过程中,我们已经证明,只要
就有
回报是等概率出现的是。
回报是等概率出现的。
算法4-7给出了每次方法加权重要性采样
算法4-7给出了每次访问加权重要性采样
作者注:Gym 0.20版本将Blackjack-v0改为Blackjack-v1。
范围为3~21的int型数值
范围为4~21的int型数值
是有将1张A牌计算为11点。
是否将1张A牌计算为11点。
最优价值和最优价值函数
最优策略和最优价值函数
evaluate_action_monte_carlo_importance_resample
evaluate_monte_carlo_importance_sample
evaluate_monte_carlo_importance_resample
evaluate_monte_carlo_importance_sample
monte_carlo_importance_resample
改为
monte_carlo_importance_sample
2.1(初始化状态动作对)
2.1(初始化状态)
输出:动作价值估计
输出:状态价值估计
前一个步骤2.2的编号应为2.1。
输入:环境(无数学描述)、策略
输入:环境(无数学描述)、如果是策略评估还需要输入策略
若是最优策略控制则还是输出策略
若是最优策略控制则还要输出策略
根据
根据
初始化状态动作对
初始化状态
使得从
使得从
2.1(初始化状态动作对)
2.1(初始化状态)
时序差分目标
时序差分目标
对的单步自益结果
的单步自益结果
参数:资格迹参数
参数:资格迹参数
初始化资格迹
2.2.2 根据输入策略
2.2.3(更新资格迹)
2.2.4(计算回报的估计值)
2.2.5(更新价值)
初始化资格迹
2.1(初始化状态动作对)选择状态
2.1(初始化状态和资格迹)选择状态
2.2.5(更新价值)
Taxi-v2
Taxi-v3
(共3处。Gym 0.15.2版本Taxi-v2变更地图为Taxi-v3)
xxxxxxxxxx+---------+|R: | : :G|| : : : : || : : : : || | : | : ||Y| : |B: |+---------+
xxxxxxxxxx+---------+|R: | : :G|| : | : : || : : : : || | : | : ||Y| : |B: |+---------+
(Gym 0.15.2版本Taxi-v2变更地图为Taxi-v3)
xxxxxxxxxxv = (self.q[next_state].sum() * self.epsilon + \
xxxxxxxxxxv = (self.q[next_state].mean() * self.epsilon + \
DoubleQLearnignAgent类
DoubleQLearningAgent类
xclass SARSALambdaAgent(SARSAAgent):def __init__(self, env, lambd=0.5, beta=1.,gamma=0.9, learning_rate=0.1, epsilon=.01):super().__init__(env, gamma=gamma, learning_rate=learning_rate,epsilon=epsilon)self.lambd = lambdself.beta = betaself.e = np.zeros((env.observation_space.n, env.action_space.n))def learn(self, state, action, reward, next_state, done, next_action):# 更新资格迹self.e *= (self.lambd * self.gamma)self.e[state, action] = 1. + self.beta * self.e[state, action]# 更新价值u = reward + self.gamma * \self.q[next_state, next_action] * (1. - done)td_error = u - self.q[state, action]self.q += self.learning_rate * self.e * td_error# 为下一回合初始化资格迹if done:self.e *= 0.agent = SARSALambdaAgent(env)
形式为
形式为
回合的损失为
回合的损失为
2.1(初始化状态动作对)选择状态
2.1(初始化状态)选择状态
删去此步
如果是动作价值评估
如果是状态价值评估
(更新动作价值函数)
(更新价值函数)
算法6-5
算法6-3
删去该算法
初始化资格迹
2.1(初始化状态动作对)选择状态
2.1(初始化状态和资格迹)选择状态
决定确定性策略
决定策略
2.1(初始化状态动作对)
2.1(初始化状态)
其中
其中
本节将“duel network”译作“对偶网络”有误。可译为“决斗网络”。相应的“对偶Q网络”、“对偶深度Q网络”可改为“决斗Q网络”、“决斗深度Q网络”。
作者注:
砖瓦编码是一种历史悠久的特征构造方法,可用于回归、分类等问题。目前学术界倾向于用神经网络代替砖瓦编码来构造特征。由于砖瓦编码和强化学习没有直接关联,本书没有用过多的篇幅介绍砖瓦编码。
实际使用砖瓦编码时,不需要精确计算砖瓦的数量,常随意的大致估计砖瓦的数量作为特征数。如果设置的特征数大于真实的砖瓦数量,那么有些特征永远不会取到,有些浪费;如果设置的特征数小于真实的砖瓦数量,那么有多个砖瓦需要共享特征,具体逻辑可以见代码清单6-3中“冲突处理”部分。这些浪费和冲突往往不会造成明显的性能损失。
第118页砖瓦数计算:每个大网格的网格宽度刚好是整个取值范围的1/8。所以,第0层大网格每个维度有8个大网格;第1~7层由于有偏移,每个维度需要有9个大网格才能覆盖整个取值范围。第117页图6-3b的情况略有不同:这个图中每个维度的取值范围不是大网格的长度的整数倍。所以有些层偏移后,不需要更多的大网格也可以覆盖整个取值范围。
再配合其他一些容易活动的
再配合其他一些容易获得的
改为
增量
增量
输入:环境(无数学描述)、策略
输入:环境(无数学描述)。
2.(时序差分更新)
2.(回合更新)
随机变量
随机变量
值函数的估计是可以得到的。
值函数的估计。
更新
更新
不过,由于梯度
但是,在实际应用中,无法事先知道这个值,所以
2.3(初始化回报和权重)
2.3(初始化回报)
减了基线
减去基线
learn()函数y = np.eye(self.action_n)[df['action']] * \df['psi'].values[:, np.newaxis]self.policy_net.fit(x, y, verbose=0)
xxxxxxxxxxsample_weight = df['psi'].values[:, np.newaxis]y = np.eye(self.action_n)[df['action']]self.policy_net.fit(x, y, sample_weight=sample_weight, verbose=0)
加上基线
减去基线
2.2(决定初始动作)用
2.2(决定初始状态动作对)选择状态
得到采样
得到奖励
2.2(决定初始动作)用
2.3 如果回合未结束,执行以下操作:
2.3.1(采样)根据状态
2.3.2(执行)用
2.3.3(估计回报)
2.2(决定初始状态)选择状态
2.3 如果回合未结束,执行以下操作:
2.3.1(采样)用
2.3.2(执行)执行动作
2.3.3(估计回报)
作者注:这里的更新式子遵循了论文原文而没有考虑累积折扣。推导出现折扣是正确的;更新时考虑折扣也是正确和合理的。
改为
初始化资格迹
2.2(决定初始动作)用
2.2(决定初始状态)选择状态
更新
更新
最小化
最小化
minimize
maximize
如果它们满足
如果它们满足
2.1
2.1
minimize
maximize
2.2(决定初始动作)用
2.2(决定初始状态动作对)选择状态
得到动作
得到动作
将前式代入后式可得
为
将前式代入后式可得
为
将第3.3步重新编号为第3.2.4步。
和最优动作价值函数。
和最优状态价值函数。
其中目标
其中目标
对应的回报
对应的回报
作者注:“动作价值网络和策略网络往往采用矢量形式的输出”指的是动作空间是离散动作空间的情况。如果动作空间是连续动作空间,往往用Gaussian形式的策略,详见GitHub代码。包括SAC算法在内的使用策略梯度的算法采用Gaussian形式策略后,策略被限制为了单峰(unimodal)形式。如果需要策略具有多峰(multimodal)形式,可以使用混合Gaussian模型(Gaussian Mixture Model,GMM)。
作者注:这个案例的动作空间是离散的。同时,本章介绍的算法,包括但不限于PPO、SAC等算法,也可用于动作空间是连续空间的情况。
使得角速度有界
使得角速度有界
单5-7中的qlearning()函数
单5-3中的play_sarsa()函数
其中的learn()函数代码改为
xxxxxxxxxxdef learn(self, observation, action, reward, next_observation, done,next_action=None):# 训练执行者网络x = observation[np.newaxis]u = self.critic_net.predict(x)q = u[0, action]x_tensor = tf.convert_to_tensor(x, dtype=tf.float32)with tf.GradientTape() as tape:pi_tensor = self.actor_net(x_tensor)[0, action]logpi_tensor = tf.math.log(tf.clip_by_value(pi_tensor,1e-6, 1.))loss_tensor = -self.discount * q * logpi_tensorgrad_tensors = tape.gradient(loss_tensor, self.actor_net.variables)self.actor_net.optimizer.apply_gradients(zip(grad_tensors, self.actor_net.variables))# 训练评论者网络u[0, action] = rewardif not done:q = self.critic_net.predict(next_observation[np.newaxis])[0, next_action]u[0, action] += self.gamma * qself.critic_net.fit(x, u, verbose=0)if done:self.discount = 1.else:self.discount *= self.gamma
中的qlearning()函数
中的play_qlearning()函数
其中的learn()函数代码改为
xxxxxxxxxxdef learn(self, observation, action, reward, next_observation, done):x = observation[np.newaxis] # 特征u = reward + (1. - done) * self.gamma * self.critic_net.predict(next_observation[np.newaxis]) # 评论者目标td_error = u - self.critic_net.predict(x)# 训练执行者网络x_tensor = tf.convert_to_tensor(observation[np.newaxis],dtype=tf.float32)with tf.GradientTape() as tape:pi_tensor = self.actor_net(x_tensor)[0, action]logpi_tensor = tf.math.log(tf.clip_by_value(pi_tensor, 1e-6, 1.))loss_tensor = -self.discount * td_error * logpi_tensorgrad_tensors = tape.gradient(loss_tensor, self.actor_net.variables)self.actor_net.optimizer.apply_gradients(zip(grad_tensors, self.actor_net.variables)) # 更新执行者网络# 训练评论者网络self.critic_net.fit(x, u, verbose=0) # 更新评论者网络if done:self.discount = 1. # 为下一回合初始化累计折扣else:self.discount *= self.gamma # 进一步累计折扣
的qlearning()函数联合起来
的play_qlearning()函数联合起来
改为
作者注:从严格意义上说,有折扣的状态分布并不是概率分布,因为它的和不总是1。针对有折扣的状态分布的期望也只是采用了期望的形式。
其中
其中
2.2(决定初始动作)
2.2(初始化状态动作对)选择状态
方差为
方差为
对于连续的动作空间,我们希望能够找到一个确定性策略,使得每条轨迹的回报最大。同策确定性算法利用策略
异策确定性算法可能比同策确定性算法性能好的原因在于,行为策略可能会促进探索,用行为策略采样得到的轨迹能够更加全面的探索轨迹空间。这时候,最大化对轨迹分布的平均期望时能够同时考虑到更多不同的轨迹,使得在整个轨迹空间上的所有轨迹的回报会更大。
与非确定性策略梯度相比,非确定性异策算法的迭代式中含有重采样因子
2.2(初始化状态)选择状态
2.3(确定行为策略)确定行为策略
2.2.1(执行)用
2.4.1(执行)用
作者注:Gym 0.21版本将Pendulum-v0改为Pendulum-v1。

下一观测
下一观测
| 倒立摆(Pendulum-v0) |
|---|
| 倒立摆(Pendulum-v0) |
|---|
值
值
gym[atari]已官方支持Windows。Gym <=0.20:在Windows、macOS、Linux系统下均只需用下列命令就可以完成gym[atari]的安装:Gym 0.21又更改了安装方式,需要再下载ROM。
xxxxxxxxxxpip install --upgrade gym[atari]
NoFrameSkip
NoFrameskip
极大极小算法(monimax)
极大极小算法(minimax)
