资讯动态

时序差分(TD)深度解析:从TD(0)到GAE的强化学习核心

发布时间:2026/10/22 4:13:50 来源:尧图企业网站定制
强化学习这几年被炒得很热但真正落地做项目的时候我发现一个特别扎心的现象很多人能背出DQN的损失函数却说不清楚TD时序差分里面的那个“时序”到底指什么。模型训不出来第一反应是调网络结构第二反应是换奖励函数很少有人回头怀疑——是不是这个更新目标本身就有问题。这篇文章想聊透TD方法。我默认读的人已经写过几个简单智能体也听说过SARSA、Q-learning和DQN但可能一直没有把所有分支理成一张连贯的图。文章会覆盖TD的核心数学直觉、TD(0)和TD(λ)的差别、函数逼近时代TD的收敛性问题、实战中正在用的优化套路以及我实际调试时踩过的几个坑。目标很朴素下次你再看“目标网络”“经验回放”“GAE”这些词眼里不再是一个个孤立技巧而是一件事的不同侧面——怎么让TD目标更稳、更准。1. 先搞明白“时序差分”差分的是什么1.1 从一次真实的训练崩溃说起我以前做过一个模拟导航任务。环境很简单一个智能体从固定起点出发目标是到达终点动作只有上下左右奖励就两个每走一步罚一点到达终点给一个大的正向奖励。按照教科书写的代码用一个小型DQN就能跑通。但奇怪的是训练总是在几千步之后彻底崩溃Q值疯涨到离谱的程度智能体开始朝着墙壁猛撞。把Q值的曲线打印出来之后我发现问题出在一个非常基础的环节上我用了一个会不断随着训练变化的网络来生成下一个状态的估计值。这一步估计值本身就在波动而我们的目标又是拿它来校正当前状态的估计值——等于用一个动态的目标去追另一个动态的目标两边都在动自然永远追不上。这个现象让我第一次正视一个定义问题TD的核心不是“回传奖励”而是“计算奖励与当前价值估计之间的偏差”。1.2 差分公式里每一块在干什么TD方法的更新式是很多人闭眼都能写的[ V(S_t) \leftarrow V(S_t) \alpha \left[ R_{t1} \gamma V(S_{t1}) - V(S_t) \right] ]这个式子看着简单信息量其实很大。那个方括号中的整体就是我们说的“TD误差”通常记为 (\delta_t)。它可以拆成三层含义(R_{t1})环境给予的真实反馈来自实际采样的数据不是模型猜的(\gamma V(S_{t1}))对未来累积奖励的估计称为“引导”bootstrap因为我们是用当前已有的价值函数去猜还没发生的未来(-V(S_t))对当前状态的既有评价也就是我们要修正的对象。整个表达式就像一个闭环反馈我们拿“真实奖励 对未来的猜测”作为合成目标与当前评价做差再沿着这个差值的方向更新评价。值得强调的是(R_{t1} \gamma V(S_{t1})) 这个整体被称为“TD目标”TD target。之所以在训练中要强调把目标当作常数来对待是因为如果我们同时更新目标与当前值优化就变成了一个移动靶问题。这就是训练不稳定的一个剂量来源。很多人在代码里没有对目标做梯度截断或停止梯度犯的就是这个错误。1.3 TD和蒙特卡洛的本质差异理解了差分机制之后我们再来看TD和MC的区别。MC要跑完一整条episode才做一次更新用最终的真实回报 (G_t) 作为目标[ V(S_t) \leftarrow V(S_t) \alpha \left[ G_t - V(S_t) \right] ]MC没有bootstrap所以没有偏差无偏估计但因为一条轨迹里每一步都充满随机性它的方差非常大。这也导致MC的收敛速度往往很慢——你需要极多的完整轨迹才能把方差压下去。TD只走一步就更新用一步真实奖励加自己的猜测。因为有猜测参与所以目标是有偏的但正因为只涉及一步的随机性它的方差远小于MC能用更少的样本做更多更新。这个“偏差-方差权衡”bias-variance tradeoff是整个TD方法家族的主轴。你想让目标准低偏差就多用真实回报、少用猜测你想让训练稳低方差就多bootstrap、少等完整轨迹。没有绝对更好的方法只有更符合任务特点的方法。2. 三步走从TD(0)到SARSA、Q-learning再到TD(λ)2.1 TD(0)到底有多“零”TD(0)是TD家族最基础的一档。“0”的意思不是步数为零而是指只看一步之内的引导。在每一步结束后立刻用下一步的状态去更新当前步不做更远视野的推演。[ V(S_t) \leftarrow V(S_t) \alpha \left[ R_{t1} \gamma V(S_{t1}) - V(S_t) \right] ]它解决了MC的方差问题同时引入了偏差。在状态空间不大的表格型任务里TD(0)被证明在满足一定步长条件下可以收敛到真实价值函数。这也是所有后续变种的地基单步更新、引导估计。TD(0)在实践中的问题是它非常“近视”。每一步只看一个后继状态那么信息在状态之间传递时就只能一步一步渗透。如果一个稀疏奖励的关键信息藏在若干步之外TD(0)需要很多次迭代才能在状态间把信息传播开来。2.2 SARSA与Q-learning同是TD道不同TD的思想工具化了之后就衍生出两个经典的控制算法。SARSA是一个on-policy算法。它的更新式是[ Q(S_t, A_t) \leftarrow Q(S_t, A_t) \alpha \left[ R_{t1} \gamma Q(S_{t1}, A_{t1}) - Q(S_t, A_t) \right] ]注意(A_{t1}) 必须是智能体在状态 (S_{t1}) 下实际采取的动作这就让这个算法学到的Q值带有策略烙印——它评价的是“在当前策略下执行这个动作会得到什么”。Q-learning是off-policy算法。更新式是[ Q(S_t, A_t) \leftarrow Q(S_t, A_t) \alpha \left[ R_{t1} \gamma \max_a Q(S_{t1}, a) - Q(S_t, A_t) \right] ]这里拿的是对下一个状态能取到的最大Q值跟实际执行的动作无关。所以Q-learning学到的Q值收敛目标是“最优策略下的动作价值”与行为策略无关。两者在实践上的差异非常明显。Q-learning更激进——它总在看“如果接下来走最优路线会怎样”所以通常会学得更快但也会因为过度乐观而出现对偶偏差的问题。SARSA更保守——它评估的是现实里我们真正会执行的动作序列所以在线学习的稳定性和安全性往往更好。经典悬崖行走Cliff Walking实验里SARSA会贴着悬崖边走因为它的目标里包含“可能掉下去”的风险Q-learning就直接走悬崖边缘因为它假设后面一定走最优路径。我做项目时的习惯是如果你有一个可以反复模拟、追求极限性能的环境优先Q-learning如果你是实机训练或者行为策略本身还在剧烈变化SARSA的小心翼翼反而值得珍惜。2.3 TD(λ)用资格迹连接单步与多步TD(0)近视MC远视。有没有中间档有就是TD(λ)。它引入了一个衰减参数λ把“一步引导”和“完整回报”连成一个可以连续调节的光谱。核心公式是[ G_t^{\lambda} (1-\lambda) \sum_{n1}^{\infty} \lambda^{n-1} G_{t}^{(n)} ]这里 (G_{t}^{(n)}) 表示n步回报。整个式子的含义是把1步回报、2步回报、3步回报……全部加权平均越往后的回报权重指数级衰减。实现上有两种做法离线地重新计算n步回报或者用资格迹eligibility trace在线地追踪“最近访问过的状态”。资格迹的记忆向量会按 (\lambda \gamma) 的比例衰减每次访问状态就加1。这样更新时TD误差不仅能修正当前状态还能按资格迹等比例修正近期访问过的所有状态。在深度强化学习里原始的资格迹已经不太常用——因为每条状态会被神经网络参数共享迹向量在参数空间里的追踪代价高、收益不对称。但TD(λ)的思想本身没有死它的继承者是GAE广义优势估计我们后面会专门说。3. 深度时代TD的核心挑战那个“预测”自己会变的悖论3.1 为什么把TD套进神经网络就会不稳定表格型TD方法理论上说得很漂亮但一旦用深度网络近似价值函数问题就冒出来了。核心矛盾有以下几个第一样本相关性。当我们在同一段轨迹上连续采样时相邻样本高度相关。梯度下降的随机性假设被打破更新方向容易在某个局部不断放大震荡。这就是为什么“经验回放”不是选修课而是必修课——它把样本打散强制让训练数据满足独立同分布假设。第二目标非平稳。TD目标里的 (\gamma V(S_{t1})) 来自同一个正在被训练的网络。网络每次更新一丁点下一个状态的估计就会变化进而导致目标整体变化。等于用一个不断移动的靶子做监督信号这在监督学习里是不可想象的。目标网络target network的诞生就是为了把靶子暂时焊死每C步才更新一次让训练有短暂的时间窗可以相对稳定地追赶。第三过估计。Q-learning的max操作天然会高估价值——如果每个动作的估计值都有噪声取最大会把噪声推到极端。深度网络的大参数量让这种噪声更加显著。炒了很多年的Double DQN本质就是对TD目标修一个偏用当前Q选择动作用目标Q评估这个动作的价值。3.2 经验回放和目标网络是“标准套餐”而非“高级技巧”很多初学者把经验回放和目标网络当作“工程优化”但我想强调它们是让深度TD方法能work的基石不是锦上添花。经验回放至少有三个作用打破样本相关性满足随机梯度下降的前提提高样本利用率——五条轨迹可以被拆成一堆独立转移样本反复学习通过平均历史分布减少突然的分布偏移带来的训练波动。目标网络的作用要单独强调它对TD误差的方差有直接抑制作用。没有目标网络等价于“每更新一次所有目标都变一次”如果步长稍大就发散。我在调试中验证过的经验是目标网络更新周期 (C) 调太小会引入高频不稳定性调太大则价值网络“跟不上”环境变化模型变成钝刀。常见设置是每1000到5000步同步一次但如果环境奖励变化剧烈可以适当缩短同步间隔。以标准DQN为例一批数据里的单个TD误差是[ \delta r \gamma \max_{a} Q_{\theta^-}(s, a) - Q_{\theta}(s, a) ](\theta^-) 是目标网络参数(\theta) 是在线网络参数。注意在线网络只在左侧 (Q_{\theta}) 处产生梯度右侧的目标被固定的参数冻结了。这是代码层面的差异也是很多人容易忽略的细节之一。3.3 从Double DQN到Dueling DQN两步修正Double DQN其实只改了一个公式形状[ y r \gamma Q_{\theta^-}(s, \arg\max_{a} Q_{\theta}(s, a)) ]也就是说选动作用在线网络评价值用目标网络。这样的分离让max方向的噪声不再直接进入目标。原论文里说这招能把DQN在某些游戏上的分数显著抬升我在自己的环境里也观察到类似趋势尤其在奖励比较稠密的任务里Double DQN能让训练曲线更平滑。Dueling DQN则是改变网络结构把Q分解成状态价值V和优势值A[ Q(s,a) V(s) A(s,a) ]这个分解的动机很实用在很多状态下选择哪个动作其实不太影响结果比如在空旷走廊里左拐右拐都差不多此时只需要培养对状态的感知能力而不用为每个动作分别建模。实践中Dueling结构让Q值对状态变化更敏感样本效率通常有可见提升。它不是TD方法的对立面而是一个互补的改动。4. 实战场景一稀疏奖励任务中TD目标的重构4.1 稀疏奖励为什么会让TD失效我在做某个仓储机器人路径规划项目时面对的是一个典型的稀疏奖励环境智能体在网格货架之间移动只有成功把货物送到目标点才有一个大正奖励其他时候奖励恒为0。用标准DQN训练时Q值几乎不更新。问题在于TD误差需要“奖励信号”来驱动。当奖励恒为0TD误差就只有 (\gamma Q(s) - Q(s)) 这一项。初始化的Q要是恰好在0附近这个误差就几乎也是0信号传不回来智能体永远学不到有用的东西。这算是一个“死锁”状态。4.2 实操解法n步回报 子目标建议我当时用了两个改动来解开死锁。第一个改动是使用n步回报。把单步引导改成多步引导[ G_t^{(n)} R_{t1} \gamma R_{t2} \gamma^2 R_{t3} \cdots \gamma^{n-1} R_{tn} \gamma^n \max_a Q(s_{tn}, a) ]在稀疏奖励环境里n步回报的意义不是“算得更准”而是把稀疏的奖励信号传播到更早的状态。原本必须一步一步回传的信息现在n步之内就能从终点流到关键位置。我在项目里尝试了n3、n5、n10发现n5时效果最好——太长了方差变大太短了信息传播仍然慢。第二个改动是国家队做法手动设计稀疏奖励的保守替代。我当时加了一个阶段性子目标奖励进入目标所在的过道口给一个小的正奖励成功靠近目标再给一个中等的奖励最终送达给一个大奖励。这样TD误差在每个阶段都能被激发训练速度明显提升。这不是“作弊”——在奖励工程里稀疏奖励任务给中间状态加引导本质上是把长期信用分配变成短期信用分配降低TD方法的学习难度。很多纯学术派会批判这种做法“污染了最优策略”但在工程里更重要的是先让网络围绕错误方向有信号可学再逐步撤掉人工引导。4.3 一个小坑n步目标在经验回放里的bugn步回报配合经验回放时有一个极其隐蔽的bug当你从回放缓冲区取出一个经验这个经验里存的是 (s_t, a_t, r_t, s_{t1})如果要做n步回报就需要同时取出后续的 (r_{t1}, r_{t2}, ...)。很多人直接取“缓冲区的物理连续片段”这在按顺序填充的缓冲池里偶尔没问题但一旦缓冲区被新数据反复覆盖物理连续并不代表时间连续。正确的做法是在存入缓冲区时就为每条经验提前算好n步累计奖励或者使用一个独立的时间戳索引确保取出的是同一轨迹内的连续转移。当时调试时Q值忽高忽低查了一整天最后发现是这个索引错位问题教训很惨痛。5. 实战场景二连续控制中TD方法的“目标构造”与GAE5.1 从值函数到优势函数TD误差的新定位在离散动作领域我们拿TD误差直接培养Q值。但到了连续控制比如机器人关节控制、自动驾驶决策我们往往使用Actor-Critic架构Actor负责给动作Critic负责评价。这时TD方法的核心阵地从“Q值的迭代”转移到了“优势函数的估计”。优势函数 (A(s,a)) 的定义是“这个动作相对于平均水平到底好多少”[ A(s,a) Q(s,a) - V(s) ]一个直观好处是Critic不再需要精确预测每一个动作带来的绝对回报只要给出“这个动作比平均好”的相对信号。Actor的更新方向就变成了“往优势为正的方向推”。在Policy Gradient类方法里策略梯度的通用表达式可以写成[ \nabla_\theta J(\theta) \mathbb{E} \left[ \nabla_\theta \log \pi_\theta(a|s) \cdot A(s,a) \right] ]所以优势函数的估计质量直接决定策略梯度方不方向对。而这正是TD思想的主场。5.2 GAE把TD(λ)用现代方式重新发明GAEGeneralized Advantage Estimation本质上就是TD(λ)的连续控制变体。它的定义是[ A_t^{GAE} \sum_{l0}^{T-t-1} (\gamma \lambda)^l \delta_{tl} ]其中[ \delta_{tl} r_{tl} \gamma V(s_{tl1}) - V(s_{tl}) ]也就是说GAE把非常长视的TD误差序列按指数衰减加权。λ0的时候GAE退化为单步TD优势λ1的时候它趋近于蒙特卡洛优势。我实际用下来λ0.95配上γ0.99是很多基准任务都能稳定工作的默认组合。它的含义是“优势估计时向前看大约20步再往后权重就小到可以忽略不计。”这个组合之所以好用是在偏差与方差之间找到一个很好的平衡点。值得注意GAE里用到的TD误差是Critic算出来的所以Critic的价值函数准不准直接决定Actor接收到的建议质量。我在许多项目里都会先把Critic拿到一边单独观测它的预测误差如果TD误差长期偏大就先调整Critic模型容量或奖励尺度而不是急着调Actor的学习率。5.3 连续控制中的TD目标不匹配问题连续控制还有一个离散控制不会面临的细节动作空间是连续分布Critic训练数据里动作的覆盖范围有限。很多情况下Q函数的预测只在行为策略附近的区域比较可靠距离当前策略太远的动作Q值往往是外推出来的幻觉。这就导致一个诡异现象Critic的TD误差看起来不大但策略只要稍微往高估区域移动一步下一次的Q值就会更加离谱形成恶性循环。很多PPO项目跑到后半段策略崩溃根源不在PPO的clipping机制上而是Critic对远动作的估计崩了。我现在的处理思路是给Critic更新加一个简单的正则约束比如限制每次更新中 (\Delta Q) 的L2范数或者对离策略样本使用重要性采样修正权重。在不改变PPO主体结构的前提下这种“TD目标约束”能显著延长稳定期。6. 那些年我调试TD方法踩过的坑和最终生效的常见配置6.1 关于目标值的“常数化”强迫症你可能觉得代码里已经做了detach就完事了但我踩过的坑是有些框架的损失函数写法会自动把目标项也纳入梯度图。例如PyTorch风格q_next self.target_net(next_state).detach() target_q reward gamma * q_next.max(dim1, keepdimTrue)[0] loss F.mse_loss(self.q_net(state).gather(1, action), target_q)这里.detach()是必须的。如果忘了梯度就会同时穿过左右两边等于推一个同时往两边跑的物体训练基本必炸。调试时我建议在loss打印前手动检查target_q.requires_grad是否为False这个细节能排查掉一大批“离奇崩溃”。6.2 奖励尺度对TD误差的直接支配TD误差的量纲完全由奖励量纲决定。如果奖励给的量级是0.01TD误差天然就在0.01附近神经网络在这么小的梯度量级下几乎学不动。很多项目把奖励设计成一个绝对值很大的数结果TD误差很大梯度爆炸。我的经验是先把所有奖励除以一个全局常数让奖励的量级落在1附近。比如把“到达终点100”改成“1”把“每步罚0.1”改成“每步罚0.001”。量级统一之后配合一个合适的学习率比如Adam默认3e-4左右训练会顺畅很多。6.3 目标网络更新频率对训练稳定性的影响目标网络有一个很微妙的平衡。更新太勤比如每一步都同步等于没有目标网络更新太疏比如一万步才同步价值函数会脱节。我在环境奖励比较平稳的任务里习惯每2000步同步一次如果环境本身有动态变化比如对手在变强就缩到每500步一次。这里面没有“标准答案”但有一个通用排查方法把同步周期调大一倍如果训练曲线的波动幅度明显变小说明之前的振荡很可能来自目标网络太“跟手”。6.4 关于“那个更新公式里为什么要除以 (1-λ)”初学TD(λ)时总有人困惑GAE公式里乘了一个 ((\gamma\lambda)^l)为什么还要在外面除以 ((1-\lambda))其实这是为了归一化。想象你把 (l0) 到无穷的权重全部相加等比级数的和就是 (1/(1-\gamma\lambda))。如果不归一化所有状态的优势估计会被整体放大一个倍数这不会改变优势的相对排名但会改变策略梯度的大小。有些实现不除以直接用原始累加值也能训练但学习率对数的敏感度会因此变差。我在自己实现时习惯先归一化这样在换任务时学习率不用来回调。7. TD方法之外的一些边界思考把TD方法看成强化学习里的“局部估计器”你会发现它其实一再出现在各种高级算法里。MuZero里面有它——模型预测与真实奖励之间的修正SAC里面有它——软更新下的TD目标离线强化学习里面有它——保守Q学习里对高估区域的惩罚。我个人的体会是学会TD的最重要标志不是能推导公式而是在看到一个训练异常时第一反应是问“我的TD目标到底哪里不符合现实”。比如策略崩了检查行为策略和目标策略的差距off-policy偏差Q值爆了检查目标网络是否更新太频繁奖励迟迟不涨检查是否稀疏奖励下TD误差根本传不动连续控制里效果抖检查GAE的λ是否太大导致方差爆炸。强化学习项目多半不是被复杂算法难死的而是被简单环节里隐藏的假设背离拖死的。TD方法就是那个最简单的环节但它牵一发动全身。回想起我最开始说的那次Q值崩溃——最终定位到原因目标网络训练步骤写错了pytorch里detach位置放错。但这个过程让我彻底把TD链条中的每一环都亲手走了一遍。从此以后我再看到“Q值又爆了”这类问题脑子里会自然弹出一张排查表目标网络对不对、奖励量级合不合适、是不是在跟一个自己会变的目标较劲。如果你也在训练强化学习模型听我一句劝别急着换更花哨的算法先把TD目标这个最基础的环节查明白。这就像练武功马步站不稳招式再花也没用。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑