简介:《强化学习的数学原理》(Mathematical Foundations of Reinforcement Learning)是西湖大学赵世钰教授撰写的英文专著,面向想真正理解强化学习底层逻辑的读者,尤其适合有一定数学基础的研究生、算法工程师和自学进阶者。全书从网格世界这一直观例子入手,系统讲解了状态值与贝尔曼方程、贝尔曼最优方程、值迭代与策略迭代、蒙特卡洛方法、随机近似、时序差分、值函数近似、策略梯度以及演员-评论家方法,并以矩阵-向量形式推导关键公式,帮助读者不只是调用接口,而是看懂算法为何有效、何时收敛。资源为单个PDF文件,压缩包约18.9MB,内容为全书完整章节,排版清晰,公式与推导过程完整,便于在电脑或平板上标记学习。已有839人学习下载,适合把它作为一本“数学视角的强化学习教材”放在手边,既能配合课程反复精读,也能按目录按需查阅相关主题。
1. 这本书把强化学习的“黑匣子”拆开给你看:数学原理才是调参的底气
做强化学习的人大概都经历过这种时刻:Q 值震荡不收敛,改个学习率就好;策略梯度跑着跑着奖励突然崩掉,换个网络初始化就稳了;同一个算法在 A 环境效果拔群,搬到 B 环境直接翻车。这些现象的根源,其实都在数学里。市面上的强化学习书很多,但大部分要么偏应用、把公式一笔带过,要么偏理论、动辄几十个定义符号让人劝退。某高校的这位老师的《强化学习的数学原理》恰好卡在中间:它不教你调参,但看完之后你会知道每个参数为什么存在、每个公式在表达什么,回头看那些“玄学调参”其实全是数学推导的结果。这本书适合两类人:一类是已经把 DQN、PPO 跑起来、但对收敛性心里没底的工程师,另一类是准备投入强化学习方向、想先建一座确定性地基的研究生。这本书的定位不是代码手册,而是推导手册,它要解决的核心问题是:当你的算法不收敛时,你能从数学上定位是哪一环出了问题,而不是靠抽卡式的调参撞运气。
2. 从 MDP 到贝尔曼方程:这本书的数学地基是怎么一步步垒起来的
2.1 为什么所有强化学习问题都必须先写成 MDP
这本书开头几章用了很大篇幅把马尔可夫决策过程拆开讲,很多人觉得这是入门内容直接跳过,实际上这里才是全书最容易出事的地方。强化学习的核心难点在于,智能体的每一个决策都会影响后续所有决策,这不是普通的监督学习,而是一个序列决策问题。MDP 的五元组——状态集合、动作集合、状态转移概率、奖励函数、折扣因子——把这个问题数学化成一个可解的形式。
书中反复强调一个关键点:马尔可夫性质才是把问题简化的核心。它假设下一时刻的状态只取决于当前状态和当前动作,与更早的历史无关。这个假设在真实环境里几乎从来不成立,但它是整个理论体系的基石。我见过不少人在实际项目中忽略这一点,把一个部分可观测的问题硬写成 MDP,结果算法怎么调都不收敛。这本书的写法是很聪明的,它会先告诉你这个假设的数学含义,然后再说“如果现实不满足这个假设,你要么换 POMDP 框架,要么想办法把历史信息压缩进状态表示里”。
另一个容易被忽略的点是折扣因子 γ 的作用。很多教材只是说“γ 越小越短视、越大越远视”,但书里详细推导了 γ 对值函数上界的影响。值函数 V(s) 的上界是 R_max/(1-γ),这个公式看起来简单,实际上决定了回报归一化、学习率选择、奖励值尺度设计等一连串工程决策。我在做一个长周期决策项目时,环境里单步奖励范围在 ±1 之间,γ 取 0.99,那么理论上 Q 值上界接近 100。但实际上 DQN 跑出来的 Q 值经常超过这个上界,这时候就该回去查是不是转移概率出了问题。
2.2 贝尔曼方程的三个变体:从期望到最优,再到贝尔曼算子
贝尔曼方程是全书第一个真正的门槛。书里从状态值函数出发,先写出贝尔曼期望方程,再写出贝尔曼最优方程,最后引入贝尔曼算子这个数学工具。这三步看似只是形式变换,实际上每一步都有不同的物理含义。
贝尔曼期望方程描述的是:在某个固定策略 π 下,状态 s 的值等于即时奖励加上折扣后的下一状态期望值。用数学表达就是 V^π(s) = E[r + γV^π(s')|s, π]。这个方程的用途是做策略评估——给定一个策略,算出它的值函数。书中给出了非常具体的解方程思路:因为这是一个线性方程组,所以可以直接求逆解出精确值,也可以用迭代法逼近,这就引出了后续的值迭代、策略迭代。
贝尔曼最优方程则换了个问题:找一个策略 π*,使得每个状态的值函数都最大化。表达式变成 V*(s) = max_a E[r + γV*(s')|s,a]。这里最关键的一个认知是,最大值算子在方程里是非线性的,因此贝尔曼最优方程不再是线性方程组,不能靠矩阵求逆解决,只能靠迭代。书中为此引入了贝尔曼算子 T,证明它是一个 γ-压缩映射,然后用巴拿赫不动点定理说明迭代为什么一定能收敛。这个证明过程是全书最早让读者感到“数学有用”的地方,收敛速度也被确定性地控制住了。
书里还有一个非常实用的推导:从最优值函数反解最优策略时,只需要贪心地在每个状态下选使 Q 值最大的动作即可。注意,这里用的是 Q 值函数而不是 V 值函数,因为 V 值函数不包含动作维度的信息。很多初学者分不清什么时候用 Q、什么时候用 V,书中通过最优策略的唯一性定理把这个关系讲透彻了,这部分值得反复读三遍。
2.3 策略迭代和值迭代的异同:收敛速度与计算代价的权衡
掌握了贝尔曼方程之后,书里紧接着讲了两种最基础的求解方案:策略迭代和值迭代。这两者的差异不仅仅是循环结构上的,更深层的是它们在不同维度上做优化。
策略迭代的运行逻辑是“评估—改进”交替进行。先固定当前策略,用策略评估算值函数,然后基于算出来的值函数做贪心改进,再回到评估。理论上的收敛性在最坏情况下需要有限次迭代,因为策略空间是有限的,每次改进都保证值函数单调不减。代价是每一步的策略评估本身可能就需要多次扫描整个状态空间,遇到大规模状态空间时计算量巨大。
值迭代则相当于把策略评估和策略改进揉成了一个步骤,每次更新都直接用 max 算子做改进,跳过了逐步评估的过程。它收敛的迭代次数比策略迭代更多,但单次迭代的计算量更小,不需要内层循环。书中有一个非常朴素的结论:实际工程里,值迭代是更常见的基线选择,因为它的实现简单、每次迭代的代价可控。策略迭代更适合状态空间小、但要求极精确最优策略的场景。
我在实际项目里有个习惯:先用值迭代快速探索环境特性,在确定收敛性没问题后再切换到策略迭代或函数逼近方法。因为值迭代的前几次迭代就能暴露转移概率估计是否离谱,这个诊断价值比收敛精度更宝贵。书里提到的“一次扫描”更新方式——在每轮迭代中对所有状态做一次更新的同步更新——是最标准也最好调试的实现方式,建议照着写一遍。
3. 蒙特卡洛、时序差分与策略梯度:三类方法的数学动机各是什么
3.1 蒙特卡洛方法:用完整轨迹估计回报,代价是方差巨大
从这章开始,书从“已知环境”走向“未知环境”,也就是环境的转移概率和奖励函数不再直接给出。蒙特卡洛方法的思想非常朴素:既然不知道概率分布,那就采样。跑完整的轨迹,把累积折扣回报当作值函数的无偏估计。
书中推导了 MC 估计的收敛性:因为回报的期望恰好就是值函数,所以这本质上是一个随机近似问题。但有一个关键细节是,MC 方法必须等整个轨迹结束才能更新,这在任务很长、终止条件很稀疏的环境里会导致训练速度极慢。更严重的问题是方差:一条轨迹的随机性可能极大,如果只看单次轨迹的回报来更新,值函数的估计会来回剧烈震荡。
书里给出了两个变体:first-visit MC 和 every-visit MC。前者只记录每个状态在整条轨迹中第一次出现的位置,后者则把每次出现都算一份样本。理论上的差别在于偏差,first-visit 是无偏的,every-visit 在某些情况下会和策略的真实值函数有偏差。实际工程中用 first-visit 更安全,这是我在处理稀疏奖励任务时验证过的。
3.2 时序差分方法:一步更新就能学习,偏差换方差
TD 方法解决的是 MC 的“等整条轨迹结束”的问题,它只等一步就走。TD 更新的核心公式是 V(s) ← V(s) + α[r + γV(s') - V(s)],其中 r + γV(s') 叫做 TD 目标,V(s) - (r + γV(s')) 的相反数就是 TD 误差 δ。
书里有一张非常重要的对比图:MC 用真实回报做目标,方差大、无偏;TD 用自举的估计值做目标,有偏但方差小。这里的“偏”来源于初始化的值函数本身就不准,V(s') 的估计误差会传导到当前更新上。但 TD 的好处是只要 α 满足邱尔-罗宾斯条件——步长序列满足 ∑α_t = ∞ 且 ∑α_t² < ∞——就能收敛。书中详细证明了 TD(0) 在表格型设置下的收敛性,给读者一个确定的数学承诺。
更重要的一个概念是 TD(λ),也就是资格迹。α_λ 这个参数在 TD(λ) 里控制的是多步之间的折中。λ=0 退化为 TD(0),λ=1 退化为 MC。书里对资格迹的定义做了非常仔细的数学展开,本质上是一个衰减系数不是加在回报上,而是加在“状态被访问的时刻”上。这个设计让算法既能利用远期的回报信息,又不至于完全放弃自举的低方差优势。我个人的经验是,λ 在 0.5~0.8 之间通常表现最好,但具体值强烈依赖环境的时间尺度,必须做网格搜索。
3.3 策略梯度定理:绕开值函数的另一种路线
表格型方法在状态空间巨大或连续状态下会直接失效,这是因为表格的存储和更新代价随状态数指数增长。策略梯度方法换了一条路:不再学习值函数表,而是用一个参数化的策略 π_θ(a|s) 直接输出动作概率分布,再对期望回报做梯度上升。
策略梯度定理是这一章的核心:∇J(θ) = E[∇log π_θ(a|s) Q^π(s,a)]。书中给出了一个特别清晰的证明思路:奖励函数对参数的梯度可以拆成两部分——当前这步动作的即时奖励变化,以及状态分布作为参数函数的变化。后者的梯度难算,但策略梯度定理利用对数似然技巧漂亮地把状态分布变化的那项消去了,只剩下可以在轨迹上直接采样的形式。
这里有个重要的工程结论:策略梯度是无偏但高方差的,一般会配合基线函数 b(s) 来降方差。只要基线不依赖动作,添加它不会改变策略梯度的期望值。书中推荐的经典基线是状态值函数 V^π(s),这就是 A2C/A3C 里 advantage 函数 A(s,a) = Q(s,a) - V(s) 的来源。我遇到过不少人在实现中直接把 Q 值当梯度权重,结果训练曲线剧烈抖动。书里这段推导就是诊断这类问题最好的参考。
4. 避坑课:照着这本书推导时最常翻车的 5 个地方
4.1 符号体系混乱:π 既是策略又表示概率分布,搞混就全盘出错
现象:读到策略梯度章节时,发现 ∇log π_θ(a|s) 里的 π 和 π(a|s) 里的 π 好像不是一个东西,推导的时候把两个 π 混用了,最后梯度表达式怎么验算都对不上。
原因:这本书的符号体系在不同章节之间有一定的延续性,但 π 在多数场合下也承担概率分布的代理身份。国内外的教材在符号使用上向来不统一,这本书不是符号最严格的,但在上下文中是可识别的。混用的原因通常是自己跳着章节读,没跟上前文默认的记号约定。
解决:读这本书时拿一张纸专门记录核心记号的约定。A 同学的做法是读完每一章就自己复写一遍该章出现的全部符号定义,尤其是“带下标/上标的 π”和“属于动作集合的 a”之间不要跳行。另外,在推导策略梯度定理时,把 ∇log π_θ(a|s) 中的 π 理解为策略网络输出层前的对数概率,而不是某个具体策略实例,这样整条链路的物理意义就清楚了。
4.2 迭代公式下标偏移:状态 s 和 s′ 的位置错一位
现象:按书上的值迭代公式写代码,训练出来的策略始终不是最优的,有些状态明明应该朝右走,结果策略朝左走。debug 很久发现,更新时用的是 V(s) ← R(s) + γ max V(s),但书里的公式是 V(s) ← R(s) + γ max V(s′),把下一步的状态当成了当前状态来用。
原因:值迭代里 s′ 的取法取决于转移函数 P(s′|s,a),如果环境实现时一步转移的索引写错,整个值函数学习就建立在错误的结构上。这不是书的问题,是自己没有按照书中的数学下标逐行对代码。
解决:实现值迭代时先写一个单步转移函数,单独测试它的输入输出是否和环境的物理意义一致——比如在一个网格世界里,从 (i,j) 坐标向右移动必须返回 (i,j+1)。确认无误之后再写迭代主循环。另外,书中给出的同步更新是“用上一轮的旧值表算更新量,再统一写回新表”,很多人图省事写成原地更新,这会导致一个周期内的更新顺序间相互污染,收敛行为完全变化。记住:同步更新是值迭代收敛性证明的前提。
4.3 训练曲线震荡触发“调参玄学”模式,却忘了先验证奖励尺度
现象:DQN 在某个环境上奖励曲线先冲到 500 再跌回 50,反复几次,于是去搜“learning rate 重调”“target network 更新频率”等常见答案,调了一周没改善。
原因:这本书在某章推导了值函数的上界 R_max/(1-γ),同时指出了实际回报尺度对优化地形的影响。奖励值过大或过小会让网络输出的 Q 值范围偏离初始化分布,导致梯度爆炸或梯度消失,这不是学习率的锅。
解决:任何新环境上线前,先手算或者采样估算 R_max 和 R_min,算出理论 Q 值上界,然后把奖励归一化到 [-1, 1] 或 [0, 1] 区间比较好。书里推导的值函数上界应该作为一条显式约束参与这个设计,而不是看一眼就过。我现在的常用做法是环境包装器里直接加一个 RewardClipper,并在训练日志里加一排“理论 Q 上界 vs 实测 Q 最大值”的对比指标,出现超界立刻停。
4.4 折扣因子和环境终止状态之间的关系被忽视
现象:在某个回合制游戏里,γ 从 0.99 改成 0.9 后训练速度明显加快,但最终策略质量下降。进一步观察发现,即使游戏已经分出胜负,环境也没有返回终态标记,导致后来不再更新这一步的状态值,策略学偏了。
原因:终态的处理在书里是隐式假设了的,即终态的值函数固定为 0。如果环境实现里终态输入给网络的观测保持一个非零向量,那么值函数永远不会学到“这个状态值应为 0”这个事实。γ 降低只是起到衰减错误信号的作用,没有根治问题。
解决:自查两个位置。第一,环境返回 done=True 时是否真的表示问题结束,而不是只表示该回合超时;第二,当 done=True 时,目标值应该直接用 r 而不是 r + γV(s′),因为 V(s′) 不存在。代码里要写成 target = r if done else r + γ·V(s′)。这个问题在书的后半部分有提到,但它写在一个不起眼的注脚里,很多人会漏掉。
4.5 策略梯度的 log 概率漏了忘加负号,或者把 log 写成了 ln 却混用
现象:实现 REINFORCE 算法时,损失函数用的是 -(R·log prob),结果每个 batch 的 loss 一路飙升,策略跑成了确定性停在原地的动作。另一个常见情况是把交叉熵损失直接套在动作概率上,等价于在最小化 log prob,梯度方向恰好相反。
原因:在数值实现中,PyTorch 的 nn.CrossEntropyLoss 内部已经把 log_softmax 和 NLLLoss 揉在一起了,也就是说当你传入原始 logits 时,它已经替你做了 softmax 和 log。如果策略网络输出层用的是 logits,这个写法是对的;如果把 softmax 输出再喂给它,就变成了二次 softmax,概率分布扭曲,梯度方向损坏。
解决:统一约定策略网络输出层直接返回 logits,在代码里显式计算 log_prob = F.log_softmax(logits, dim=-1),然后取对应动作的 log_prob,和 reward-to-go 相乘构建 loss。书里推的是数学形式 ∇log π_θ(a|s),落到实现时,这个 log_prob 指的是“最终动作概率的对数”,直接把 softmax 输出喂进去一定会出错。写代码时把这两层分干净,不要偷懒把 log_softmax 和 CrossEntropy 揉一起,这样出了错也好定位。
5. 把数学原理落到代码里:用配书推导复现一个最小 TD 学习器
5.1 第一步:写一个干净的表格型 Q 学习,验证贝尔曼方程
光看书不写代码,等于没看。这个章节我给一个最小可复现的表格型 Q 学习实现,配合书里的贝尔曼最优方程做验证。环境用最经典的网格世界——4×4 格子,左上角起点,右下角终点,每步奖励 -1。如果这个都能跑偏,那说明数学没理解。
import numpy as np class GridWorld: def __init__(self, size=4): self.size = size self.start = (0, 0) self.goal = (size-1, size-1) self.actions = [(0,1), (1,0), (0,-1), (-1,0)] # 右、下、左、上 def reset(self): return self.start def step(self, state, action): r, c = state dr, dc = self.actions[action] nr, nc = r + dr, c + dc # 出界则停留在原位置,奖励同样是 -1 if nr < 0 or nr >= self.size or nc < 0 or nc >= self.size: return state, -1, False if (nr, nc) == self.goal: return (nr, nc), 0, True return (nr, nc), -1, False逻辑说明:GridWorld 的 step 实现了状态转移、奖励、终止判断三件事。出界时状态不变、奖励 -1,到达终态奖励 0 且结束。这正好对应书里 MDP 五元组中的转移概率和奖励函数,只是这里的转移是确定性的。参数 size 控制网格边长,想验证不同状态空间规模下值迭代的收敛速度可以改这个值。
class TabularQLearning: def __init__(self, env, gamma=0.9, alpha=0.1): self.env = env self.gamma = gamma self.alpha = alpha # Q 表大小:状态数 × 动作数 self.q_table = np.zeros((env.size * env.size, len(env.actions))) def train(self, episodes=500): for _ in range(episodes): state = self.env.reset() done = False while not done: s_idx = state[0] * self.env.size + state[1] # 简单 epsilon-greedy 策略 if np.random.rand() < 0.1: action = np.random.randint(len(self.env.actions)) else: action = np.argmax(self.q_table[s_idx]) next_state, reward, done = self.env.step(state, action) ns_idx = next_state[0] * self.env.size + next_state[1] # Q 学习更新:目标 = r + γ * max_a Q(s', a) td_target = reward + self.gamma * np.max(self.q_table[ns_idx]) td_error = td_target - self.q_table[s_idx, action] self.q_table[s_idx, action] += self.alpha * td_error state = next_state return self.q_table逻辑说明:这段把书里的 Q 学习更新式一步到位实现了。关键行是 td_target = reward + γ·max_a Q(s′,a),注意 done=True 时 td_target 只等于 reward——因为终态后面没有状态了。如果你把终态也塞进 max 运算,Q 值会永远差一个 γ 的衰减项,最终收敛的 Q 值会系统性地偏小。参数 gamma 对应书里的折扣因子,alpha 是步长,0.1 在这个环境里是比较稳的选择,网格更大时可以适当调大到 0.2。
5.2 利用贝尔曼最优方程验证 Q 表结果:做完再对照
训练完的 Q 表怎么验证对不对?最直接的方法是用一个独立的程序解贝尔曼最优方程,得到精确的 Q* 值,然后对比两者差距。这时候贝尔曼方程就不再是课本符号,而是可以执行的计算过程。
def exact_bellman_q(env, gamma=0.9, theta=1e-6): n = env.size * env.size q = np.zeros((n, len(env.actions))) while True: delta = 0 new_q = q.copy() for r in range(env.size): for c in range(env.size): s_idx = r * env.size + c for a, (dr, dc) in enumerate(env.actions): nr, nc = r + dr, c + dc if nr < 0 or nr >= env.size or nc < 0 or nc >= env.size: reward = -1 ns_idx = s_idx elif (nr, nc) == env.goal: reward = 0 ns_idx = nr * env.size + nc else: reward = -1 ns_idx = nr * env.size + nc new_q[s_idx, a] = reward + gamma * np.max(q[ns_idx]) delta = np.max(np.abs(new_q - q)) q = new_q if delta < theta: break return q逻辑说明:这个函数的本质是书里的值迭代,只不过作用在 Q 函数上。每次迭代对每个 (状态, 动作) 对重新计算目标值 r + γ·max Q(s′,·) 作为新估计值,反复迭代直到所有条目变化量小于 theta。theta 是收敛阈值,1e-6 已经足够精确到 6 位小数,想更严可以再降一档。对比训练结果时,可以直接算平均绝对误差:
trained_q = TabularQLearning(GridWorld()).train() exact_q = exact_bellman_q(GridWorld()) print(np.mean(np.abs(trained_q - exact_q)))逻辑说明:这行代码把训练 500 回合的 Q 表和精确解做对比。如果平均绝对误差在 0.1 以下,说明训练过程基本贴合贝尔曼方程;如果误差超过 0.3,优先检查是否忘了对终态单独处理。这个方法最大的价值是,它把数学结论变成了可执行的验证工具,可以随时确认自己的实现不是在“看着像学但其实在乱学”。
5.3 收敛曲线可视化:把理论收敛保证翻译成可观测指标
最后一步是画收敛曲线,这里要画两条线:每回合累积奖励和 Q 表与精确解的误差。前者告诉你是否学到了好策略,后者告诉你是否真的在朝贝尔曼最优方程的解逼近。两条线缺一不可——只画奖励曲线,很多错误策略也能跑出高奖励,比如碰巧走了一条次优路径,但 Q 值本身是错的。
import matplotlib.pyplot as plt def train_with_tracking(env, episodes=500): agent = TabularQLearning(env) exact_q = exact_bellman_q(env) reward_history = [] error_history = [] for ep in range(episodes): state = env.reset() done = False total_reward = 0 while not done: s_idx = state[0] * env.size + state[1] action = np.argmax(agent.q_table[s_idx]) next_state, reward, done = env.step(state, action) ns_idx = next_state[0] * env.size + next_state[1] td_target = reward + agent.gamma * np.max(agent.q_table[ns_idx]) agent.q_table[s_idx, action] += agent.alpha * (td_target - agent.q_table[s_idx, action]) state = next_state total_reward += reward reward_history.append(total_reward) error_history.append(np.mean(np.abs(agent.q_table - exact_q))) return reward_history, error_history逻辑说明:这段代码把训练过程拆成可观测的指标。eval 阶段用纯贪心策略跑回合,记录累积奖励;误差指标用当前 Q 表和精确解做逐元素平均绝对差。注意 eval 阶段不更新 Q 表、不做探索,这正是为了衡量当前策略的真实水平,避免 epsilon 探索干扰评估。这套验证框架可以用在任何表格型方法的代码里,只要把更新式换成对应算法的即可(比如从 Q 学习换成 SARSA 只需要把 max 算子换成实际动作的值)。
画图时建议用左右双轴图:左轴画误差(对数刻度),右轴画累积奖励。如果误差线出现平台期,说明 alpha 太大在最优解附近震荡;如果奖励线已经稳定但误差还在下降,说明策略已经最优但 Q 值还有系统偏差,这种差距在表格型方法里问题不大,但在函数逼近时可能会引起不稳定的次优收敛。
rewards, errors = train_with_tracking(GridWorld()) fig, ax1 = plt.subplots() ax1.set_xlabel("episode") ax1.set_ylabel("mean abs Q error", color="tab:red") ax1.plot(errors, color="tab:red") ax2 = ax1.twinx() ax2.set_ylabel("total reward", color="tab:blue") ax2.plot(rewards, color="tab:blue") plt.show()6. 进阶用法:把这本书的标准推导扩展成你自家环境的诊断工具
读书读完,最终的检验是把书里的数学工具变成自己的调试手段。我常用的一个进阶技巧是把贝尔曼误差当一个实时指标来监控训练健康度。所谓贝尔曼误差就是式子 r + γ·max_a Q(s′,a) - Q(s,a) 的套用,在训练中每采样一条数据就算一次,然后按 batch 聚合。这个指标的意义是:如果值函数真的在逼近最优解,这个误差应当趋近于零。很多项目里我根本不看总奖励曲线,只盯着贝尔曼误差看,它是比奖励更早期的异常信号——策略还没坏透,值函数就已经在数学上先失真了。
具体做法是训练脚本里每隔若干步采样一个小 batch,计算平均贝尔曼误差和误差的 90 分位数。平均误差低、90 分位高,说明大部分状态已经学好了,但存在少数“失控状态”,多半是探索覆盖不足;平均误差和 90 分位都高,大概率是奖励尺度没归一化或者 γ 不合理,回到前面第 4 章的坑位排查;如果误差在训练中期突然跳高,那通常是 target network 更新频率过高导致目标经常移动,训练追赶不上。
这本书还有一个平时容易被忽略的点是策略梯度定理的条件和边界。书中证明依赖“轨迹从初始状态分布出发”这个前提,如果你的环境里初始状态分布和策略实际遇到的分布差别巨大,REINFORCE 的梯度估计会严重失真。我现在做起始状态固定、终止状态稀疏的任务时,会在日志里单独记录初始状态的贝尔曼误差,而不是只看全局平均,这样能快速区分“环境本身难”和“算法实现有毛病”。
最后说一个我做强化学习以来的习惯:任何新项目的第一周不写网络结构、不调优化器,只做两件事——把环境写成 MDP 并跑通值迭代或 Q 学习的表格版本,然后把真实环境里的奖励分布、状态转移结构、终止条件记录成一份文档。表格版本给出的最优策略即使不是最终方案,它也算出了一个上界参考,后续任何函数逼近算法的结果都应该向这个上界靠拢。如果没有表格参考,就不知道自己被函数逼近的误差拖了多少后腿。这本书最大的价值就在这里——它让你在动手写第一行神经网络之前,就拿一个确定性的数学结论锚住了项目预期。希望这本书的推导对你的项目也能发挥同样的作用,希望帮到你。
本文还有配套的精品资源,点击获取