TD3 — 给 DDPG 装两副刹车,连续控制终于稳了
待复核TD3(Twin Delayed Deep Deterministic policy gradient)是 2018 年 McGill 团队修好的 DDPG。日常类比:原来的 DDPG 像一个过度自信的实习生——他每次估自己能赚多少钱总往上吹,于是越学越偏。TD3 给他配了两个会计 + 强制让他先核账再行动 + 估算时加点保守误差,三招下去人就清醒了。
DDPG 在连续控制任务(机器人手臂、仿真四足)上有个老毛病:Q 值估得越来越高,actor(选动作的网络)跟着这个虚高的 Q 学,最后整个崩。TD3 不换框架,只在三个点上拧螺丝;论文图里 HalfCheetah 一类任务,回报量级大约从三千抬到九千上下。
不理解 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)。两个会计不会同时往高估方向偏,取较低分就压回来。 - Delayed Policy Update(延迟策略更新):critic 每步都更新,actor 每
d=2步才更新一次。让估分先稳,再让选动作的人跟着稳的分数优化。 - Target Policy Smoothing(目标策略平滑):算 target 时给 target actor 输出加一点截断高斯噪声。让 Q 对邻近动作平滑,避免 actor 钻虚假尖峰。
三招合起来:保守估值 + 慢更新 + 平滑正则。单招都能在前人里找到影子(Double Q、target network、SARSA 式随机化),但组合成套、调到能稳跑,才是 TD3 的贡献。少一件通常都会退化——这是工程论文最值得学的范式:把已知小药方配成新疗法。
案例 1:高估偏差到底有多严重
Section titled “案例 1:高估偏差到底有多严重”论文在 HalfCheetah(MuJoCo 里的仿真四足跑酷环境)上画了两条曲线,量级大致是:
真实回报(蒙特卡洛估) ≈ 3000critic 给出的 Q 值 ≈ 10000逐部分解释:
- 下面那条是环境真给的分数;上面那条是 critic 自己喊的分
- 差了约三倍 → critic 在吹牛,不是小误差
- actor 听信虚高 Q 猛冲,策略就掉进坑
- 换成 TD3 后两条曲线贴在一起,差距通常压到约 10% 内
案例 2:Clipped Double Q 怎么算 target
Section titled “案例 2:Clipped Double Q 怎么算 target”# DDPG:单 critic 的 targety = r + gamma * Q_target(s_next, actor_target(s_next))
# TD3:双 critic + min + 平滑噪声a_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))# Q1、Q2 都用同一个 y 训练;更新 actor 时只用 Q1 反传逐部分解释:
a_next先加截断噪声 → 目标策略平滑,避免尖峰min(Q1, Q2)故意略低估:低估只会学慢,高估会学歪- 两个 critic 共用
y,但 actor 只跟 Q1,避免双网络互相拖累策略梯度
案例 3:延迟更新 + 最低超参
Section titled “案例 3:延迟更新 + 最低超参”# 每步:更新两个 critic# 每 d=2 步:才更新 actor 与 target 网络hidden = [256, 256]; lr = 3e-4; batch_size = 256buffer_size = 1_000_000; tau = 0.005; gamma = 0.99policy_noise = 0.2; noise_clip = 0.5policy_delay = 2; explore_noise = 0.1逐部分解释:
- critic 像温度计每秒校准;actor 像厨师每两秒才改菜谱——温度计还在抖就改火,菜会忽咸忽淡
policy_delay=2是甜点:d=1退回 DDPG 频率,d=4/8又让 critic 跟不上- 上表是 Walker2d / Hopper / HalfCheetah 的常见起步;稀疏奖励或像素输入要重搜
实践上:先跑 SAC,跑不动再换 TD3,反过来也行。两个都收敛不了就先检查环境本身(奖励尺度、动作裁剪、是否真的连续动作)。
- 以为换大网络就能解决高估:critic 加宽加深反而更糟——逼近误差更花,max 更容易抓尖峰。
- target smoothing 噪声调太大:σ=0.2、clip=0.5 是原论文默认;σ=1.0 会把 Q 糊成一片,训练直接崩。
- 把 d 调成 1:丢掉延迟优势;
d=2才是工程甜点。 - 复现时忘了 target actor 加噪声:跑分能差约 30%,Q 会重新长尖峰。
- 以为 TD3 离散动作也能用:它假设动作连续可微;离散动作退回 Double DQN 系列。
适用 vs 不适用场景
Section titled “适用 vs 不适用场景”适用:
- 连续动作空间(机器人控制、自动驾驶仿真、MuJoCo / PyBullet)
- 标准 MuJoCo 任务大约 1e6 steps 量级就能看到论文级曲线;确定性策略适合部署期不要随机性
- 离线交互成本低、可跑 100 万 ~ 1000 万步;样本效率要求高于 PPO 时
不适用:
- 离散动作 → 用 DQN 系列 / Rainbow / IMPALA
- 高维像素输入但没视觉编码器 → 加 ResNet 或换 SAC + Dreamer
- 真机器人在线训练(仍需大量采样;off-policy 意思是可以用旧数据重放,但不等于少采)→ 加 demonstrations / model-based
- 多 agent 博弈环境 → MADDPG / QMIX 系列
历史小故事(可跳过)
Section titled “历史小故事(可跳过)”- 2010:Hasselt 提出 Double Q-learning,发现离散动作下 Q-learning 系统性高估
- 2015:Lillicrap 把 DQN 思路搬到连续动作,发表 DDPG,但很多人发现”跑得通但调不稳”
- 2016:Hasselt 把 Double Q 思想搬到神经网络,得到 Double DQN
- 2018 年初:Fujimoto 发现 DDPG 高估更严重,且单纯套 Double Q 不 work,设计了 clipped double + delayed + smoothing
- 2018 年中:Haarnoja 发表 SAC,从最大熵 RL 独立解决同类问题,TD3 / SAC 并列连续控制双雄
- 高估偏差是 Q-learning + 神经网络的结构性问题:max 操作叠噪声的必然产物,不是偶然 bug
- 保守估计胜过准确估计:min 两个 Q 数学上有偏,但稳定性远胜无偏的高方差估计
- 更新频率要分层:快变量(critic)追真值,慢变量(actor)跟稳定的快变量
- 正则不一定加在 loss 上:target smoothing 把正则加在 target 里,相当于要求邻近动作的分数别差太远(一种平滑约束)
- 先跑 SAC 或 TD3 都行:两个都收敛不了,优先检查环境奖励与动作尺度,而不是再堆网络宽度
- 论文 PDF:Fujimoto et al. 2018(10 页正文,附录消融更值得看)
- 作者参考实现:github.com/sfujim/TD3(约 300 行 PyTorch)
- 视频:Yannic Kilcher — TD3 Paper Explained
- Stable-Baselines3 文档里 TD3 / SAC 超参表(7 种 MuJoCo 任务)
- ddpg —— TD3 修的就是 DDPG,建议先看
- sac —— 同年同类问题的另一条路径
- dqn —— 离散动作版祖宗,Double Q 思想发源地