TD3 — 给 DDPG 装两副刹车,连续控制终于稳了
是什么
TD3(Twin Delayed Deep Deterministic policy gradient)是 2018 年 McGill 团队修好的 DDPG。日常类比:原来的 DDPG 像一个过度自信的实习生——他每次估自己能赚多少钱总往上吹,于是越学越偏。TD3 给他配了两个会计 + 强制让他先核账再行动 + 估算时加点保守误差,三招下去人就清醒了。
DDPG 在连续控制任务(机器人手臂、仿真四足)上有个老毛病:Q 值估得越来越高,actor 跟着这个虚高的 Q 学,最后整个崩。TD3 不换框架,只在三个点上拧螺丝,HalfCheetah 跑分从 3000 飙到 9500。
为什么重要
不理解 TD3,下面这些事都解释不通:
- 为什么 Stable-Baselines3 / RLlib 把 TD3 默认列在 SAC 旁边当连续控制基线
- 为什么 2018 年之后做机器人 RL 的论文很少再用纯 DDPG
- 为什么 SAC 论文要把 TD3 作为最强对照——同一年两条独立路径都解决了 DDPG 的不稳定
- 为什么 Q-learning 系列只要用神经网络逼近,就一定要处理”高估偏差”
核心要点
DDPG 的病根:用 max(或贪婪 actor)选动作 + 神经网络有噪声 → Q 系统性偏高。这叫最大化偏差(maximization bias),Hasselt 2010 在离散动作上用 Double Q-learning 修过,但搬到连续动作不直接 work。TD3 的三板斧:
- Clipped Double Q(截断双 Q):训两个独立 critic Q1、Q2,算 target 时取
min(Q1, Q2)。两个网络不会同时往高估方向偏,min 一下就压回来。 - Delayed Policy Update(延迟策略更新):critic 每步都更新,actor 每
d=2步才更新一次。让 critic 先稳,再让 actor 跟着稳的 critic 优化。 - Target Policy Smoothing(目标策略平滑):算 target 时给 target actor 输出加一点截断高斯噪声。让 Q 函数对邻近动作平滑,避免 actor 钻 Q 函数的虚假尖峰。
三招合起来:保守估值 + 慢更新 + 平滑正则。代码改动不到 50 行,效果直接翻倍。
值得注意的是,三招里没有任何一招是 TD3 原创:clipped min 的思想来自 Hasselt 的 Double Q,delayed update 在 DQN 的 target network 里就有影子,target smoothing 的本质是 SARSA 风格的随机化。TD3 的贡献是发现这三件凑齐才稳,少一件都退化。这是工程论文最值得学的范式——把已知的小药方组合成新疗法。
实践案例
案例 1:高估偏差到底有多严重
DDPG 在 HalfCheetah 上跑 100 万步,作者画了一条曲线:
- 真实回报(蒙特卡洛估的):~3000
- critic 给出的 Q 值:~10000
差了三倍多。critic 自信地告诉 actor『这个动作能拿一万分』,actor 当然按这个方向猛冲,结果跌到坑里。换成 TD3,两条曲线贴在一起,差距控制在 10% 以内。
案例 2:Clipped Double Q 怎么算 target
伪代码(DDPG 原版 vs TD3):
# DDPG:用单 critic 的 target 网络y = r + gamma * Q_target(s_next, actor_target(s_next))
# TD3:双 critic + 取 mina_next = actor_target(s_next) + clip(noise, -c, c) # 平滑y = r + gamma * min(Q1_target(s_next, a_next), Q2_target(s_next, a_next))min 不是数学上”无偏”的,它是有意往低估方向偏一点——但低估比高估好得多,因为低估只会让学习慢,高估会让学习走错方向。
案例 3:延迟更新的直觉
把 critic 想成温度计、actor 想成要根据温度做菜的厨师。每秒都看温度计调火(每步更新 critic),但厨师每两秒才决定加不加料(actor 每 d=2 步更新)。如果厨师每秒都跟着温度计跳,温度计本身还在抖,菜就会忽咸忽淡。让温度计稳定一会儿再让厨师动手——这就是 delayed update。
案例 4:和 SAC 的分工
| 维度 | TD3 | SAC |
|---|---|---|
| 核心思路 | 修 DDPG 的高估 + 不稳定 | 重新设计 — 最大熵 RL |
| actor 输出 | 确定性动作 + 探索噪声 | 高斯分布(自带探索) |
| 超参数敏感度 | 中等 | 较低(自动调温 entropy) |
| 样本效率 | 高 | 略高 |
| 代码改动 | 比 DDPG 多 30 行 | 比 DDPG 多 100 行 |
实践上:先跑 SAC,跑不动再换 TD3,反过来也行。两个都收敛不了就检查环境本身。
案例 5:超参数清单(最低配置)
跑 MuJoCo 标准任务(Walker2d / Hopper / HalfCheetah)TD3 的推荐起步:
hidden = [256, 256] # actor / critic MLPlr = 3e-4 # 双网络共用batch_size = 256buffer_size = 1_000_000tau = 0.005 # target 软更新系数gamma = 0.99policy_noise = 0.2 # target smoothing 标准差noise_clip = 0.5 # smoothing 裁剪policy_delay = 2 # actor 延迟explore_noise = 0.1 # 收集数据时加的探索噪声这套参数在 7 个任务上都能跑出论文级数据。如果换到稀疏奖励或像素输入环境,需要重新搜。
踩过的坑
- 以为换大网络就能解决高估:作者实验过,把 DDPG 的 critic 加宽加深反而更糟——网络越大,逼近误差越花,max 越容易抓到尖峰。结构性偏差不能靠堆参数解决。
- target smoothing 噪声调太大:原论文 σ=0.2、clip=0.5。调成 σ=1.0 训练直接崩——平滑过度等于把 Q 函数糊成一片,actor 学不到方向。
- 把 d 调成 1:等价于退回 DDPG 的更新频率,丢掉延迟优势。但 d=4、d=8 也不会更好——critic 更新跟不上 actor 步伐。
d=2是工程甜点。 - 复现时忘了 target actor 加噪声:很多三方实现把 smoothing 漏了,跑分能差 30%。这一招看着小,去掉后 Q 函数会重新长尖峰。
- 以为 TD3 离散动作也能用:TD3 假设动作连续可微(通过 actor 直接给 a),离散动作要退回 Double DQN 系列。
适用 vs 不适用场景
适用:
- 连续动作空间(机器人控制、自动驾驶仿真、MuJoCo / PyBullet)
- 离线交互成本低、可以跑 100 万 ~ 1000 万步的环境
- 需要确定性策略(部署期不希望随机性)
- 对样本效率要求高于 PPO 的场景
不适用:
- 离散动作 → 用 DQN 系列 / Rainbow / IMPALA
- 高维像素输入但没视觉编码器 → 加 ResNet 或换 SAC + Dreamer
- 真机器人在线训练(off-policy 但仍需大量采样)→ 加 demonstrations / model-based 加速
- 多 agent 博弈环境 → MADDPG / QMIX 系列
历史小故事(可跳过)
- 2010:Hasselt 提出 Double Q-learning,发现 Q-learning 在离散动作下系统性高估,用两套独立 Q 估计修正
- 2015:Lillicrap 把 DQN 思路搬到连续动作,发表 DDPG,但很多人发现”跑得通但调不稳”
- 2016:Hasselt 把 Double Q 思想搬到神经网络,得到 Double DQN
- 2018 年初:Fujimoto 发现 DDPG 的高估比离散更严重,且单纯套 Double Q 不 work(连续动作 actor-critic 结构不一样),设计了 clipped double + delayed + smoothing 三件套
- 2018 年中:Haarnoja 发表 SAC,从最大熵 RL 的角度独立解决同一类问题,从此 TD3 / SAC 并列连续控制双雄
学到什么
- 高估偏差是 Q-learning + 神经网络的结构性问题:不是 bug 而是 max 操作 + 噪声叠加的必然产物
- 保守估计胜过准确估计:min 两个 Q 数学上有偏,但训练稳定性远胜无偏的高方差估计
- 更新频率要分层:快变量(critic)追真值,慢变量(actor)跟稳定的快变量。这是控制论老套路
- 正则不一定加在 loss 上:target smoothing 是把正则加在 target 计算里,等价于给 Q 函数加一个隐式的 Lipschitz 约束
- 三个独立小招组合能压倒一个大想法:TD3 没有任何理论突破,只是把已知技巧排列组合调对超参,效果碾压
延伸阅读
- 论文 PDF:Fujimoto et al. 2018(10 页正文,附录的消融实验比正文更值得看)
- 作者放出的参考实现:github.com/sfujim/TD3(300 行 PyTorch,最简洁的 baseline)
- 视频讲解:Yannic Kilcher — TD3 Paper Explained(30 分钟把三招讲透)
- 工程对比:Stable-Baselines3 文档里 TD3 / SAC 的超参表,列出了 7 种 MuJoCo 任务的推荐配置
- ddpg —— TD3 修的就是 DDPG,先看 DDPG
- sac —— 同年同类问题的另一条路径
- dqn —— 离散动作版的祖宗,Double Q 思想发源地