📑 本页目录(点开跳转)
10 · Actor-Critic
⏱ 26 分钟 | ⭐ 把前两章的优点合起来
🎯 一句话
第 8 章学价值(方差小但学不了连续动作), 第 9 章学策略(通用但方差大)。 Actor-Critic 就是:让一个网络演(Actor),另一个网络打分(Critic)—— 用 Critic 的估计去替换策略梯度里那个高方差的回报。
🎭 一、两个角色
关键信息
- Actor(演员):策略网络 π(a|s; θ)
- 决定做什么动作
- Critic(评论家):价值网络 V(s; w) 或 Q(s,a; w)
- 评价这个状态/动作有多好
- ⭐ Actor 按 Critic 的评价来调整自己
- Critic 按实际的奖励来调整自己
📉 二、它到底改了什么
回顾策略梯度(第 9 章):
$$\nabla J(\theta) = \mathbb{E}\big[\nabla\log\pi(a|s;\theta)\cdot \underbrace{G_t}_{\text{整条轨迹的回报}}\big]$$
操作步骤
Actor-Critic 的替换:
$$\nabla J(\theta) = \mathbb{E}\big[\nabla\log\pi(a|s;\theta)\cdot \underbrace{A(s,a)}_{\text{优势函数}}\big]$$
其中最常用的估计是 TD 误差:
$$A(s,a) \approx \delta = r + \gamma V(s') - V(s)$$
💡 人话翻译:
δ = 「实际拿到的」减去「原本预期的」。 δ > 0 → 这个动作比预期好 → 提高它的概率 δ < 0 → 比预期差 → 降低它的概率
因果链
⭐ 三、优势函数与基线
为什么用"优势"而不是直接用 Q:
信息关系
📐 为什么减基线不改变梯度的期望(想看再点)
对任意只依赖状态的函数 $b(s)$:
$$\mathbb{E}_{a\sim\pi}\big[\nabla\log\pi(a|s)\cdot b(s)\big] = b(s)\sum_a \pi(a|s)\frac{\nabla\pi(a|s)}{\pi(a|s)} = b(s)\nabla\sum_a\pi(a|s) = b(s)\nabla 1 = 0$$
⭐ 所以减去任何基线都不引入偏差,却能降低方差。 最优基线接近 $V(s)$ —— 这就是用它的理由。
GAE:在偏差和方差之间调一个旋钮
$$A^{GAE(\lambda)}_t = \sum_{l=0}^{\infty}(\gamma\lambda)^l\delta_{t+l}$$
信息关系
🔨 四、最小实现
# 🧩 骨架,不是可运行脚本:critic / dist / state / reward 等来自你自己的训练循环
# 一步 Actor-Critic 的核心
import torch.nn.functional as F
value = critic(state)
next_value = critic(next_state).detach() # ⭐ 目标不回传
td_target = reward + gamma * (1 - done) * next_value
delta = (td_target - value).detach() # ⭐ 优势也要 detach
# Actor:朝"让好动作更可能"的方向走
logp = dist.log_prob(action)
actor_loss = -(logp * delta).mean() # ⭐ 负号:梯度上升
# Critic:把 V 拟合到 TD 目标
critic_loss = F.mse_loss(value, td_target)
loss = actor_loss + 0.5 * critic_loss - 0.01 * entropy # ⭐ 熵奖励鼓励探索
⚠️ 三个必踩的坑: ① 优势忘了
detach()→ 梯度会穿过 Critic 传回来,训练行为变得莫名其妙 ② 两个 loss 的量级差太多 → Critic 的 loss 通常大得多,要乘系数(常用 0.5) ③ 没有熵奖励 → 策略过早收敛到某个动作,探索直接死掉 ⭐
🧬 五、主要变体
| 算法 | 关键点 |
|---|---|
| A2C | 同步版本,多个环境并行采样 → 减小相关性 |
| A3C | 异步多线程(现在基本被 A2C 取代,因为同步版更简单也更稳) |
| PPO ⭐ | 加了"更新幅度限制",第 11 章的主角 |
| DDPG / TD3 | 确定性策略 + off-policy,用于连续控制 |
| SAC ⭐ | 最大熵 RL:目标里显式加入熵项,探索更好、超参更鲁棒 |
💡 SAC 值得记住:它把"熵奖励"从一个 trick 提升成了优化目标的一部分, 在连续控制任务上通常是最稳的选择。
🧭 六、三条路线的对比(这一章的总结)
| 价值方法(DQN) | 策略梯度(REINFORCE) | Actor-Critic | |
|---|---|---|---|
| 学什么 | Q 值 | 策略 | 两个都学 |
| 连续动作 | ❌ 难 | ✅ | ✅ |
| 方差 | 低 | 很高 | 中等 ⭐ |
| 偏差 | 有(自举) | 无 | 有 |
| 更新时机 | 每步 | 回合结束 | 每步 ⭐ |
| 样本效率 | 高(可回放) | 低(on-policy) | 中 |
🔑 一句话记住三者的关系: Actor-Critic 用"有偏但低方差"的 Critic 估计,换掉了策略梯度里"无偏但高方差"的回报。 这是一次典型的偏差-方差交易。
🔗 和站内其他章的关系
| 相关的地方 | 这里的位置 |
|---|---|
| 第 5 章 TD vs MC | 优势估计的 λ 就在调这个 ⭐ |
| 第 9 章 REINFORCE | Actor 部分 |
| 第 8 章 价值网络 | Critic 部分 |
| 第 7 章 探索 | 熵奖励是这里的探索手段 |
| ML 基础第 5 章 偏差方差 | 本章的核心权衡 |
✅ 检查点
- Actor 和 Critic 各负责什么?
- Actor-Critic 把策略梯度里的什么替换掉了?换成了什么?
- TD 误差 δ 的人话含义是什么?
- 这次替换带来三个好处和一个代价,分别是什么?
- 为什么用优势 A 而不是直接用 Q?
- 为什么减去基线不会引入偏差?
- GAE 的 λ 在调什么?常用取值?
- 实现的三个坑是什么?
- 用一句话概括三条路线的关系。
👀 答案
- Actor(策略网络)决定做什么动作;Critic(价值网络)评价状态/动作有多好。Actor 按 Critic 的评价调整,Critic 按实际奖励调整。
- 替换掉了整条轨迹的实际回报 G_t(高方差),换成优势函数 A(s,a),最常用的估计是 TD 误差 δ = r + γV(s') − V(s)。
- 实际拿到的减去原本预期的。δ>0 说明这个动作比预期好 → 提高其概率;δ<0 则降低。
- 好处:①每步就能更新不用等回合结束 ②方差大幅降低 ③保留策略梯度的通用性。代价:引入偏差(V 只是估计)——又是偏差-方差权衡。
- 因为 Q 的绝对大小没有意义,重要的是相对好坏。若所有动作 Q 都在 1000 左右,用 Q 当权重会把所有动作概率都推高、信号被淹没。A = Q − V 只保留"比平均好多少"。
- 因为对任意只依赖状态的 b(s),E[∇logπ·b(s)] = b(s)·∇(Σπ) = b(s)·∇1 = 0。所以减任何基线都不引入偏差,却能降方差。
- 调偏差和方差的折中:λ=0 是单步 TD(偏差大方差小),λ=1 是蒙特卡洛(无偏方差大)。常用 λ≈0.95。
- ①优势忘了 detach()(梯度穿过 Critic 传回)②两个 loss 量级差太多(Critic loss 要乘系数如 0.5)③没有熵奖励(策略过早收敛,探索死掉)。
- Actor-Critic 用"有偏但低方差"的 Critic 估计,换掉了策略梯度里"无偏但高方差"的回报——一次典型的偏差-方差交易。
🛑 可以停在这里
⚡ 走神救援
先记住这几件事
- Actor 选择动作,Critic 提供价值估计,二者承担不同工作。
- 优势衡量动作相对当前预期好多少,GAE 调节估计的偏差与方差。
- 分别检查策略损失、价值损失与梯度边界,避免让估计目标反向干扰更新。
下一节 👉 11-PPO.md ⭐