共计 2102 个字符,预计需要花费 6 分钟才能阅读完成。
背景痛点
强化学习新手在选择算法时常常面临以下困惑:
- 样本效率低 :传统 Q -learning 需要大量交互数据才能收敛,而策略梯度方法对样本利用率更高但方差较大
- 超参数敏感 :DQN 系列算法对学习率、目标网络更新频率等参数极其敏感,调试成本高
- 动作空间限制 :DQN 无法直接处理连续动作空间,需要额外设计离散化方案
- 训练稳定性差 :原始策略梯度方法容易因策略突变导致训练崩溃
这些痛点使得算法选型成为新手入门的第一个关键决策点。
算法横向对比
| 维度 | A2C | DQN | PPO |
|---|---|---|---|
| 更新方式 | 同步多 worker 采样 + 策略梯度 | 经验回放 +TD 误差最小化 | 重要性采样 + 策略裁剪 |
| 适用场景 | 连续 / 离散动作空间 | 仅离散动作空间 | 连续 / 离散动作空间 |
| 收敛速度 | 中等(并行加速) | 较慢(样本效率低) | 较快(策略约束稳定) |
| 超参敏感性 | 中等(需调学习率) | 高(多参数耦合) | 低(clip 范围鲁棒) |
| 实现复杂度 | 中等(需设计网络结构) | 低(标准实现多) | 高(需处理 IS 权重) |
A2C 核心实现
网络结构定义
import torch
import torch.nn as nn
import torch.optim as optim
class ActorCriticNetwork(nn.Module):
def __init__(self, n_inputs, n_actions):
super().__init__()
self.fc_shared = nn.Sequential(nn.Linear(n_inputs, 128),
nn.ReLU())
self.fc_actor = nn.Linear(128, n_actions) # 策略头
self.fc_critic = nn.Linear(128, 1) # 价值头
def forward(self, x):
x = self.fc_shared(x)
return torch.softmax(self.fc_actor(x), dim=-1), self.fc_critic(x)
Advantage 计算
优势函数 $A_t$ 的 GAE(Generalized Advantage Estimation) 实现:
$$
A_t = \sum_{k=0}^{T-t-1} (\gamma\lambda)^k \delta_{t+k}
$$
其中 TD 误差 $\delta_t = r_t + \gamma V(s_{t+1}) – V(s_t)$
def compute_advantages(rewards, values, gamma=0.99, lambda_=0.95):
advantages = torch.zeros_like(rewards)
running_advantage = 0
for t in reversed(range(len(rewards)-1)):
delta = rewards[t] + gamma * values[t+1] - values[t]
running_advantage = delta + gamma * lambda_ * running_advantage
advantages[t] = running_advantage
return advantages
策略梯度更新
策略目标函数:
$$
J(\theta) = \mathbb{E}[\log \pi_\theta(a|s) A_t]
$$
价值损失函数:
$$
L_v = (R_t – V_\theta(s_t))^2
$$
def update_model(optimizer, states, actions, advantages, returns):
policy, values = model(states)
probs = policy.gather(1, actions.unsqueeze(1))
# 策略梯度损失
policy_loss = -(torch.log(probs) * advantages.detach()).mean()
# 价值损失
value_loss = nn.MSELoss()(values.squeeze(-1), returns)
# 熵正则项
entropy_loss = -0.01 * (policy * torch.log(policy)).sum(-1).mean()
optimizer.zero_grad()
(policy_loss + 0.5*value_loss + entropy_loss).backward()
optimizer.step()
实验验证
在 CartPole-v1 环境中的训练曲线对比:

- A2C 在 100 个 episode 内达到最大奖励(200 分)
- DQN 需要约 300 个 episode 才能稳定
- PPO 收敛最快但计算开销更大
避坑指南
- 学习率设置 :
- 建议初始值 1e- 3 到 1e-4
-
使用线性衰减:
lr = max(1e-5, lr * 0.99) -
并行 worker 数量 :
- CPU 核心数×2 通常是最佳实践
-
过多 worker 会导致梯度冲突
-
折扣因子选择 :
- 短期任务:gamma=0.9~0.95
- 长期任务:gamma=0.99~0.999
延伸思考
- 架构创新 :如何将 Transformer 的 self-attention 机制引入 A2C 的观测编码器?
- 多任务学习 :能否用 A2C 框架实现不同任务间的策略迁移?
参考文献
正文完
