SAC(Soft Actor-Critic)详解
目录
- SAC(Soft Actor-Critic)详解
- 0. 先建立直觉
- 1. SAC 里的符号都是什么?
- 2. SAC 的核心思想:最大熵强化学习
- 3. 什么是熵 Entropy?
- 4. Actor-Critic 结构
- 5. SAC 的 Actor
- 6. SAC 的 Critic
- 7. 为什么 SAC 有两个 Critic?Twin Q
- 8. SAC 的完整组件
- 9. On-policy 和 Off-policy
- 10. Replay Buffer
- 11. Target Network 是什么?
- 12. Reparameterization Trick 是什么?
- 13. SAC 的损失函数
- 14. SAC 训练流程
- 15. SAC 伪代码
- 16. SAC 的张量形状
- 17. SAC 和 PPO 的区别
- 18. SAC 和 DDPG / TD3 的关系
- 19. Residual SAC 怎么理解?
- 20. 为什么 SAC 适合机器人控制?
- 21. 常见超参数
- 22. 实现 SAC 时最容易错的地方
- 23. 三个关键机制的极简总结
- 24. 一张总览图
- 25. 记忆卡片
- 26. 建议后续学习路径
- 27. 本页反向链接建议
SAC(Soft Actor-Critic)详解
核心一句话
**SAC = Off-policy + Actor-Critic + Twin Q + Replay Buffer + Maximum Entropy。** 它是一种非常适合**连续动作控制**的强化学习算法,常用于机械臂、四足机器人、仿真控制、真实机器人策略学习等场景。0. 先建立直觉
SAC,全称 Soft Actor-Critic,中文常译为:
- 软演员-评论家算法
- 最大熵 Actor-Critic 算法
它想解决的问题是:
让智能体在追求高奖励的同时,不要过早变得死板,而是保留足够探索性。
普通 RL 常常只追求:
$$ \max_\pi \mathbb{E}\left[\sum_{t=0}^{\infty}\gamma^t r_t\right] $$
SAC 追求的是:
$$ \max_\pi \mathbb{E}\left[\sum_{t=0}^{\infty}\gamma^t\left(r_t + \alpha \mathcal{H}(\pi(\cdot|s_t))\right)\right] $$
也就是:
高 reward + 高 entropy
其中:
- reward:动作带来的任务收益;
- entropy:策略的随机性 / 探索性;
- $\alpha$:温度系数,用来控制“奖励”和“探索”的权衡。
1. SAC 里的符号都是什么?
| 符号 | 名称 | 它是什么 | 例子 |
|---|---|---|---|
| $s$ | state,状态 | 环境当前观测/状态向量 | 机器人关节角、速度、末端位置、目标位置 |
| $a$ | action,动作 | 智能体输出给环境的控制量 | 关节速度、电机力矩、夹爪开合 |
| $r$ | reward,奖励 | 环境给智能体的标量反馈 | 抓取成功 +1,距离变近 +0.1 |
| $s'$ / $s_{t+1}$ | next state,下一状态 | 执行动作后的新状态 | 下一帧机器人状态 |
| $d$ / done | 终止标记 | episode 是否结束 | 成功、失败、摔倒、超时 |
| $\pi$ | policy,策略 | 一个函数 / 神经网络 | 输入状态,输出动作分布 |
| $Q(s,a)$ | Q-value,状态-动作价值 | 一个数值 | 在状态 $s$ 做动作 $a$ 的长期回报估计 |
关键理解
$\pi$ 不是一个动作。 $\pi$ 是策略函数,输入状态后,给出动作分布。 动作 $a$ 才是真正送给环境执行的控制量。例如机械臂任务:
状态 s:
[关节1角度, 关节2角度, 末端x, 末端y, 目标x, 目标y]
动作 a:
[关节1速度, 关节2速度]
策略 π:
一个神经网络,输入状态 s,输出动作分布
2. SAC 的核心思想:最大熵强化学习
SAC 的 “Soft” 主要来自 entropy bonus。
普通强化学习希望:
选长期回报最高的动作
SAC 希望:
选长期回报高,同时策略保持一定随机性的动作
SAC 的 actor 优化目标常写成:
$$ \max_\pi \mathbb{E}_{a\sim\pi(\cdot|s)}\left[Q(s,a)-\alpha \log \pi(a|s)\right] $$
拆开看:
| 项 | 含义 |
|---|---|
| $Q(s,a)$ | 鼓励选择长期价值高的动作 |
| $-\alpha\log\pi(a | s)$ |
为什么要鼓励随机性?
如果策略太早变得确定,可能会陷入局部最优。 比如机械臂一开始学会一种“勉强可用”的抓取姿势后,如果不继续探索,就可能永远找不到更好的抓取方式。3. 什么是熵 Entropy?
熵衡量一个策略的“不确定性”。
假设某状态下有三个动作。
低熵策略:
动作1:0.98
动作2:0.01
动作3:0.01
这个策略几乎永远选动作 1,所以熵很低。
高熵策略:
动作1:0.34
动作2:0.33
动作3:0.33
这个策略更随机,探索性更强,所以熵更高。
连续动作中,SAC 的策略通常是高斯分布:
$$ a \sim \mathcal{N}(\mu_\theta(s),\sigma_\theta(s)) $$
策略熵和标准差 $\sigma$ 有关:
- $\sigma$ 大:动作更分散,探索更强;
- $\sigma$ 小:动作更集中,策略更确定。
4. Actor-Critic 结构
SAC 是一种 Actor-Critic 算法。
| 角色 | 中文 | 作用 | 网络形式 |
|---|---|---|---|
| Actor | 演员 | 负责选动作 | $\pi_\theta(a |
| Critic | 评论家 | 负责评价动作好坏 | $Q_\phi(s,a)$ |
可以类比成:
Actor:我觉得这个动作不错,我来执行。
Critic:我来评价你这个动作长期看值多少钱。
5. SAC 的 Actor
SAC 的 actor 是一个随机策略网络。
它输入状态 $s$,输出动作分布的参数:
$$ \mu_\theta(s),\quad \log\sigma_\theta(s) $$
也就是:
state
↓
Actor Network
↓
mean, log_std
↓
构造高斯分布
↓
采样动作
连续动作 SAC 常用 squashed Gaussian policy:
$$ u = \mu_\theta(s)+\sigma_\theta(s)\epsilon,\quad \epsilon\sim\mathcal{N}(0,I) $$
$$ a = \tanh(u) $$
这样动作会被压到 $[-1,1]$。
如果真实环境动作范围不是 $[-1,1]$,再做缩放:
$$ a_{env}=a_{scale}\cdot a+a_{bias} $$
6. SAC 的 Critic
Critic 是 Q 网络:
$$ Q_\phi(s,a) $$
输入:
状态 s + 动作 a
输出:
一个标量 Q 值
含义是:
在状态 $s$ 下执行动作 $a$,从长期来看大概能获得多少累计回报。
例如:
Q(s, a) = 12.7
表示:
这个动作长期看大约值 12.7。
7. 为什么 SAC 有两个 Critic?Twin Q
SAC 通常有两个 Q 网络:
$$ Q_{\phi_1}(s,a),\quad Q_{\phi_2}(s,a) $$
更新 actor 或计算 target 时,会取较小值:
$$ \min\left(Q_{\phi_1}(s,a),Q_{\phi_2}(s,a)\right) $$
原因:单个 Q 网络容易高估动作价值。
强化学习中,actor 会倾向于寻找 critic 认为好的动作。如果 critic 对某些动作错误高估,actor 就会钻这个估计误差的空子。
Twin Q 的保守策略是:
两个 critic 都说好才是真的比较好;只要其中一个觉得没那么好,就保守一点。
这叫 clipped double Q-learning。
8. SAC 的完整组件
| 组件 | 作用 |
|---|---|
| Actor $\pi_\theta$ | 输入状态,输出动作分布 |
| Critic 1 $Q_{\phi_1}$ | 评价动作价值 |
| Critic 2 $Q_{\phi_2}$ | 第二个评价器,减少高估 |
| Target Critic 1 $Q_{\bar\phi_1}$ | Critic 1 的慢更新副本 |
| Target Critic 2 $Q_{\bar\phi_2}$ | Critic 2 的慢更新副本 |
| Replay Buffer | 存历史交互数据 |
| Temperature $\alpha$ | 控制探索强度 |
SAC 不是一个单独网络
它是一套训练系统:actor、两个 critic、两个 target critic、replay buffer、温度系数共同工作。9. On-policy 和 Off-policy
9.1 先定义两个策略
强化学习里有两个策略概念:
| 名称 | 含义 |
|---|---|
| behavior policy | 行为策略,负责和环境交互、采样数据 |
| target policy | 目标策略,正在被学习、优化、评估的策略 |
9.2 On-policy
On-policy 指:
$$ \text{behavior policy}=\text{target policy} $$
也就是:
当前策略自己采样数据
然后用这批数据更新自己
典型算法:PPO、A2C、TRPO、REINFORCE。
特点:
采样 → 更新 → 旧数据基本丢掉 → 再采样
因为策略更新后,旧数据不再完全代表当前策略。
9.3 Off-policy
Off-policy 指:
$$ \text{behavior policy}\neq\text{target policy} $$
也就是:
可以用旧策略采出来的数据训练当前策略
SAC 是 off-policy。
SAC 会把历史经验存在 replay buffer:
$$ (s_t,a_t,r_t,s_{t+1},d_t) $$
这些数据可能来自:
- 1 小时前的 actor;
- 10 分钟前的 actor;
- 当前 actor;
- 初始随机策略。
但 SAC 仍然可以用它们训练当前 critic 和 actor。
9.4 对比表
| 对比项 | On-policy | Off-policy |
|---|---|---|
| 数据来源 | 当前策略采样的数据 | 当前策略或旧策略的数据 |
| 旧数据能不能复用 | 通常不能 | 可以 |
| 是否用 replay buffer | 通常不用 | 通常用 |
| 样本效率 | 较低 | 较高 |
| 稳定性 | 通常较稳定 | 依赖算法设计 |
| 代表算法 | PPO、A2C、TRPO | DQN、DDPG、TD3、SAC |
SAC 为什么是 Off-policy?
SAC 的 critic 学的是:在状态 $s$ 下做动作 $a$ 的价值是多少。 只要这条 transition 真实发生过,critic 就能用它学习,不要求这个动作一定来自当前 actor。10. Replay Buffer
SAC 的 replay buffer 存储 transition:
$$ (s_t,a_t,r_t,s_{t+1},d_t) $$
一条机械臂数据可能是:
s_t = [joint1_angle, joint2_angle, gripper_x, gripper_y, target_x, target_y]
a_t = [joint1_velocity, joint2_velocity]
r_t = 0.8
s_{t+1} = 下一时刻状态
d_t = False
训练时,从 replay buffer 随机采样一个 batch:
batch_size = 256
得到:
states.shape = [256, state_dim]
actions.shape = [256, action_dim]
rewards.shape = [256, 1]
next_states.shape = [256, state_dim]
dones.shape = [256, 1]
Replay buffer 的作用:
- 提高样本利用率;
- 打破连续采样数据之间的相关性;
- 支持 off-policy 学习;
- 让历史经验可以反复训练。
11. Target Network 是什么?
一句话
**Target network 是当前 critic 的慢速副本,用来提供更稳定的 TD target。**SAC 中有:
当前 Critic:
Q_{φ1}, Q_{φ2}
目标 Critic:
Q_{φ̄1}, Q_{φ̄2}
Target critic 不是全新功能的网络,而是 critic 的延迟副本。
11.1 为什么需要 Target Network?
在普通监督学习中,标签是固定的。
例如分类任务:
输入:猫的图片
标签:cat
标签 cat 不会因为模型更新而变化。
但在强化学习中,critic 的目标本身也由神经网络估计出来:
$$ y = r + \gamma Q(s',a') $$
这里右边的 $Q(s',a')$ 也是神经网络输出。
这会导致:
Q 网络一边被训练
一边又负责生成自己的训练目标
这叫 moving target problem,移动目标问题。
11.2 不用 Target Network 会怎样?
如果直接用当前 critic 计算目标:
$$ y = r + \gamma Q_\phi(s',a') $$
右边和左边都是当前 critic。
训练会变成:
第 1 步:Qφ 预测 5,target 是 6,于是 Qφ 往 6 靠
第 2 步:Qφ 更新了,target 变成 8,于是 Qφ 又往 8 靠
第 3 步:Qφ 又更新了,target 变成 4,于是 Qφ 又往 4 靠
这就像:
老师一边让你考试,一边实时修改标准答案,而且标准答案还取决于你刚才交的卷子。
目标剧烈变化,训练容易震荡或发散。
11.3 Target Network 怎么解决?
SAC 用当前 critic 拟合目标,但目标由 target critic 生成:
$$ Q_\phi(s,a) \rightarrow y $$
其中:
$$ y = r + \gamma Q_{\bar\phi}(s',a') $$
- 当前 critic $Q_\phi$:学生,负责被训练;
- target critic $Q_{\bar\phi}$:慢变化的参考答案生成器。
这样 target 不会随着当前 critic 每一步更新而剧烈变化。
11.4 SAC 中的 Critic Target
SAC 的 target 是:
$$ y = r_t + \gamma(1-d_t)\left[\min_i Q_{\bar\phi_i}(s_{t+1},a')-\alpha\log\pi(a'|s_{t+1})\right] $$
其中:
$$ a'\sim\pi(\cdot|s_{t+1}) $$
注意里面用的是 target critic:
$$ Q_{\bar\phi_1},Q_{\bar\phi_2} $$
而不是当前 critic:
$$ Q_{\phi_1},Q_{\phi_2} $$
11.5 Target Network 怎么更新?Soft Update
Target network 通常不通过梯度更新,而是通过软更新跟随当前 critic:
$$ \bar\phi \leftarrow \tau \phi + (1-\tau)\bar\phi $$
其中:
| 符号 | 含义 |
|---|---|
| $\phi$ | 当前 critic 参数 |
| $\bar\phi$ | target critic 参数 |
| $\tau$ | 软更新系数,通常很小,例如 0.005 |
如果:
φ = 10
φ_bar = 6
τ = 0.005
那么:
$$ \bar\phi \leftarrow 0.005\times 10 + 0.995\times 6 = 6.02 $$
target critic 不会一下子从 6 变成 10,而是慢慢变成 6.02。
直觉
当前 critic 变化快,负责学习。 target critic 变化慢,负责提供稳定目标。12. Reparameterization Trick 是什么?
一句话
**Reparameterization trick 是把随机采样动作改写成“确定性函数 + 外部随机噪声”,让梯度可以穿过采样过程。**12.1 问题从哪里来?
SAC 的 actor 是随机策略:
$$ a\sim\pi_\theta(\cdot|s) $$
连续动作中通常是:
$$ a\sim\mathcal{N}(\mu_\theta(s),\sigma_\theta(s)) $$
也就是 actor 输出:
mean = μθ(s)
std = σθ(s)
然后从高斯分布采样动作。
问题是:
采样操作本身不好直接反向传播。
Actor loss 依赖动作 $a$:
$$ L_\pi = \alpha\log\pi_\theta(a|s)-Q_\phi(s,a) $$
我们希望梯度能从:
loss → action a → μ, σ → actor 网络参数 θ
传回去。
但如果 $a$ 是从采样黑箱里出来的,梯度路径不清楚。
12.2 Reparameterization 的做法
原始写法:
$$ a\sim\mathcal{N}(\mu,\sigma) $$
改写成:
$$ a = \mu + \sigma\epsilon,\quad \epsilon\sim\mathcal{N}(0,1) $$
关键变化:
随机性不再藏在采样函数里
而是单独变成 ε
动作 a 变成 μ 和 σ 的可微函数
12.3 数字例子
假设 actor 输出:
μ = 2.0
σ = 0.5
先采样外部随机噪声:
ε = -1.2
然后:
$$ a = \mu + \sigma\epsilon = 2.0 + 0.5\times(-1.2)=1.4 $$
这和从 $\mathcal{N}(2.0,0.5)$ 里采样是等价的。
但现在 $a$ 明确是 $\mu$ 和 $\sigma$ 的函数:
$$ \frac{\partial a}{\partial \mu}=1 $$
$$ \frac{\partial a}{\partial \sigma}=\epsilon $$
所以梯度可以传播。
12.4 SAC 里的实际形式:加 tanh
SAC 通常用:
$$ u = \mu_\theta(s)+\sigma_\theta(s)\epsilon $$
$$ a = \tanh(u) $$
完整流程:
state s
↓
Actor 网络
↓
μθ(s), σθ(s)
↓
采样 ε ~ N(0, I)
↓
u = μθ(s) + σθ(s) ε
↓
a = tanh(u)
这样动作落在 $[-1,1]$。
12.5 它不是取消随机性
Reparameterization trick 不是让策略不随机。
随机性仍然存在,因为 $\epsilon$ 是随机的。
它只是把:
a ~ Normal(μ, σ)
改成:
ε ~ Normal(0, 1)
a = μ + σ * ε
这样动作仍然随机,但对网络输出 $\mu,\sigma$ 可导。
13. SAC 的损失函数
13.1 Critic Loss
Critic 要拟合 TD target:
$$ y = r_t + \gamma(1-d_t)\left[\min_i Q_{\bar\phi_i}(s_{t+1},a')-\alpha\log\pi(a'|s_{t+1})\right] $$
然后两个 critic 的 loss 是:
$$ L_{Q_1}=\mathbb{E}\left[(Q_{\phi_1}(s_t,a_t)-y)^2\right] $$
$$ L_{Q_2}=\mathbb{E}\left[(Q_{\phi_2}(s_t,a_t)-y)^2\right] $$
Note
$y$ 计算时要 `stop gradient`,实现中通常放在 `torch.no_grad()` 里。13.2 Actor Loss
Actor 希望选择高 Q 且有足够随机性的动作。
最大化目标:
$$ \mathbb{E}{a\sim\pi\theta(\cdot|s)}\left[Q(s,a)-\alpha\log\pi_\theta(a|s)\right] $$
实现中通常写成最小化:
$$ L_\pi=\mathbb{E}\left[\alpha\log\pi_\theta(a|s)-\min_i Q_{\phi_i}(s,a)\right] $$
13.3 Temperature $\alpha$
$\alpha$ 控制探索强度。
| $\alpha$ 大 | $\alpha$ 小 |
|---|---|
| 更重视熵 | 更重视 reward |
| 策略更随机 | 策略更确定 |
| 探索更强 | 利用更强 |
现代 SAC 常用自动温度调节,让策略熵接近目标熵:
$$ \mathcal{H}_{target}=-\dim(A) $$
如果动作维度是 6:
target_entropy = -6
14. SAC 训练流程
flowchart TD
A[初始化 Actor、Critic、Target Critic、Replay Buffer] --> B[当前状态 s]
B --> C[Actor 根据 s 采样动作 a]
C --> D[环境执行动作]
D --> E[得到 r、s_next、done]
E --> F[存入 Replay Buffer]
F --> G[从 Buffer 随机采样 batch]
G --> H[用 Target Critic 计算 TD Target]
H --> I[更新两个 Critic]
I --> J[用 Reparameterization 采样新动作]
J --> K[更新 Actor]
K --> L[更新 alpha]
L --> M[Soft Update Target Critic]
M --> B
15. SAC 伪代码
initialize actor πθ
initialize critics Qφ1, Qφ2
initialize target critics Q̄φ1, Q̄φ2
initialize replay buffer D
initialize temperature α
for each environment step:
# 1. Actor 采样动作
a = actor.sample(s)
# 2. 环境交互
s_next, r, done = env.step(a)
# 3. 存入 replay buffer
D.add(s, a, r, s_next, done)
s = s_next
# 4. 从 buffer 采样 batch
batch = D.sample(batch_size)
states, actions, rewards, next_states, dones = batch
# 5. 更新 critic
with torch.no_grad():
a_next, logp_next = actor.sample(next_states)
q1_next = target_q1(next_states, a_next)
q2_next = target_q2(next_states, a_next)
q_next = torch.min(q1_next, q2_next)
y = rewards + gamma * (1 - dones) * (q_next - alpha * logp_next)
q1_loss = mse(q1(states, actions), y)
q2_loss = mse(q2(states, actions), y)
update(q1, q1_loss)
update(q2, q2_loss)
# 6. 更新 actor
a_new, logp = actor.sample(states) # reparameterization trick
q_new = torch.min(q1(states, a_new), q2(states, a_new))
actor_loss = (alpha * logp - q_new).mean()
update(actor, actor_loss)
# 7. 更新 alpha
alpha_loss = ...
update(alpha, alpha_loss)
# 8. 软更新 target critic
soft_update(target_q1, q1, tau)
soft_update(target_q2, q2, tau)
16. SAC 的张量形状
假设:
batch_size = 256
state_dim = 20
action_dim = 6
那么:
| 张量 | shape |
|---|---|
| states | [256, 20] |
| actions | [256, 6] |
| rewards | [256, 1] |
| next_states | [256, 20] |
| dones | [256, 1] |
| actor mean | [256, 6] |
| actor log_std | [256, 6] |
| sampled actions | [256, 6] |
| log_prob | [256, 1] |
| q1_value | [256, 1] |
| q2_value | [256, 1] |
| target_q | [256, 1] |
Important
SAC 的公式最后都要落到这些张量计算上。 它不是纯抽象,每一步都有明确的数值和 shape。17. SAC 和 PPO 的区别
| 对比项 | SAC | PPO |
|---|---|---|
| 类型 | Off-policy | On-policy |
| 是否用 replay buffer | 用 | 通常不用 |
| 样本效率 | 高 | 较低 |
| 训练数据 | 旧经验可反复使用 | 主要用当前策略采样数据 |
| 策略类型 | 随机策略 | 随机策略 |
| 探索机制 | 最大熵目标 | 策略随机性 + clip 约束 |
| 常见场景 | 机器人连续控制、真实样本珍贵 | 大规模仿真、游戏、机器人控制 |
一句话:
PPO 更像“每次用新数据稳稳更新一点”。
SAC 更像“把历史经验存起来反复学习,同时保持探索性”。
18. SAC 和 DDPG / TD3 的关系
| 算法 | 策略类型 | 探索方式 | 是否最大熵 |
|---|---|---|---|
| DDPG | 确定性策略 | 外加噪声 | 否 |
| TD3 | 确定性策略 | 外加噪声 | 否 |
| SAC | 随机策略 | 策略本身有熵 | 是 |
DDPG / TD3 actor 通常是:
$$ a = \mu_\theta(s) $$
SAC actor 是:
$$ a\sim\pi_\theta(\cdot|s) $$
SAC 的探索是策略本身的一部分,不只是外面加噪声。
19. Residual SAC 怎么理解?
普通 SAC:
$$ a_t\sim\pi_\theta(\cdot|s_t) $$
Residual SAC:
$$ a_t=a_{base}(s_t)+a_{res}(s_t) $$
其中:
$$ a_{res}(s_t)\sim\pi_\theta^{SAC}(\cdot|s_t) $$
也就是说:
SAC 不再负责输出完整动作,而是输出一个补偿量 / 残差动作。
例如:
传统控制器输出:
a_base = [0.50, -0.20]
SAC residual 输出:
a_res = [0.03, 0.01]
最终动作:
a = [0.53, -0.19]
Residual SAC 的 SAC 内部机制仍然包括:
- off-policy;
- replay buffer;
- twin Q;
- target network;
- reparameterization trick;
- entropy bonus。
只是 actor 输出的动作被解释成 residual action。
20. 为什么 SAC 适合机器人控制?
机器人控制任务通常有这些特点:
- 动作是连续的;
- 采样成本高;
- 探索不能太盲目;
- 环境动力学复杂;
- 需要稳定训练;
- 有时已经存在传统控制器。
SAC 对应的优势:
| 机器人需求 | SAC 设计 |
|---|---|
| 连续动作 | Gaussian policy 输出连续动作 |
| 样本贵 | off-policy + replay buffer |
| 避免过早陷入局部最优 | maximum entropy |
| Q 值估计容易高估 | twin Q 取 min |
| 训练目标不稳定 | target network |
| 随机策略要可训练 | reparameterization trick |
21. 常见超参数
| 超参数 | 常见值 | 含义 |
|---|---|---|
| $\gamma$ | 0.99 | 未来奖励折扣 |
| $\tau$ | 0.005 | target network 软更新速度 |
| batch size | 256 | 每次训练采样多少条数据 |
| replay buffer size | $10^6$ | 存多少历史 transition |
| learning rate | $3\times10^{-4}$ | actor / critic 学习率 |
| target entropy | $-\dim(A)$ | 目标熵 |
| $\alpha$ | 自动调节 | 探索强度 |
| hidden dim | 256 | MLP 隐藏层维度 |
常见网络结构:
Actor:
state_dim → 256 → 256 → mean, log_std
Critic:
state_dim + action_dim → 256 → 256 → Q
22. 实现 SAC 时最容易错的地方
22.1 忘记 tanh log-prob correction
因为动作经过了:
$$ a=\tanh(u) $$
所以计算 $\log\pi(a|s)$ 时不能只用原始 Gaussian 的 log prob,还要考虑 tanh 变换的修正项。
否则 entropy 项会错,训练可能不稳定。
22.2 动作范围没有正确缩放
Actor 通常输出 $[-1,1]$,但环境动作范围可能是:
[-2, 2]
[0, 1]
[-100, 100]
需要做 action scaling。
22.3 done 和 truncation 混淆
Gymnasium 中常见:
terminated
truncated
- terminated:任务真的结束;
- truncated:时间限制到了。
如果只是 time limit 截断,不一定应该当成真正终止。
22.4 target 没有 stop gradient
计算 target 时应该:
with torch.no_grad():
target_q = ...
否则 target 的计算图也会参与反向传播。
22.5 没有使用两个 Q 网络
单个 Q 网络容易高估。标准 SAC 通常使用 twin critics。
22.6 log_std 没有 clamp
Actor 输出的 log_std 通常要限制范围:
log_std = torch.clamp(log_std, -20, 2)
否则标准差可能过大或过小。
23. 三个关键机制的极简总结
23.1 Off-policy
可以用旧策略采样的数据训练当前策略。
所以 SAC 能使用 replay buffer,样本效率高。
23.2 Target Network
Q 学习的目标本身也来自 Q 网络。
如果用当前 Q 网络算 target,目标会乱跳。
所以复制一个慢速 Q 网络,专门负责算稳定 target。
23.3 Reparameterization Trick
随机采样不好反向传播。
把 a ~ N(μ, σ) 改成 a = μ + σ ε。
随机性放到 ε 里,动作变成 μ 和 σ 的可微函数。
24. 一张总览图
flowchart LR
S[状态 s] --> Actor[Actor πθ]
Actor --> Dist[输出 μ, σ]
Dist --> Sample[重参数化采样 a]
Sample --> Env[环境 Env]
Env --> R[奖励 r]
Env --> SN[下一状态 s_next]
S --> Buffer[Replay Buffer]
Sample --> Buffer
R --> Buffer
SN --> Buffer
Buffer --> Batch[采样 batch]
Batch --> Critic1[Critic Qφ1]
Batch --> Critic2[Critic Qφ2]
Batch --> Target[Target Critics Qφ̄1/Qφ̄2]
Target --> TD[TD Target]
TD --> Critic1
TD --> Critic2
Critic1 --> ActorUpdate[Actor 更新]
Critic2 --> ActorUpdate
ActorUpdate --> Actor
25. 记忆卡片
SAC 的一句话定义是什么?
SAC 是一种 off-policy、最大熵、actor-critic 强化学习算法,常用于连续动作控制。 [!question] SAC 为什么叫 Soft? 因为它的目标中加入了 entropy 项,不只追求 reward,还鼓励策略保持随机性。 [!question] SAC 为什么有两个 Critic? 为了减少 Q 值高估,取两个 Q 网络的较小值。 [!question] SAC 为什么需要 Replay Buffer? 因为 SAC 是 off-policy,可以复用历史经验,提高样本效率。 [!question] Target Network 的作用是什么? 它是 critic 的慢速副本,用来提供稳定的 TD target,缓解 moving target problem。 [!question] Reparameterization Trick 的作用是什么? 它让随机采样动作变成可微函数,使 actor loss 能通过动作反传到 actor 网络参数。 [!question] Residual SAC 和普通 SAC 的区别是什么? 普通 SAC 输出完整动作;Residual SAC 输出补偿动作,最终动作为 base action + residual action。26. 建议后续学习路径
- 05-第4课 Bellman方程:理解 Q target 的来源;
- Actor-Critic:理解 actor 和 critic 如何互相配合;
- DDPG 和 TD3:理解 SAC 的前身和对照;
- PPO:理解 on-policy 方法;
- Residual Reinforcement Learning:理解 Residual SAC / Residual PPO;
- 机器人控制中的强化学习:理解 SAC 在真实控制中的使用方式。
27. 本页反向链接建议
可以从这些笔记链接到本文:
- 强化学习
- 连续控制
- 机器人控制
- Actor-Critic
- Off-policy 强化学习
- Maximum Entropy RL
- Residual Reinforcement Learning
- PPO
- TD3
- DDPG