共计 1450 个字符,预计需要花费 4 分钟才能阅读完成。
为什么选择 Actor-Critic?
想象你在训练一个游戏 AI 玩《超级马里奥》:

- DQN 需要处理庞大的动作空间(跳跃 + 方向组合),且无法输出连续动作(如力度控制)
- PPO 虽然稳定但实现复杂,涉及重要性采样等概念
- A2C 就像『自行车』:既有 Actor 直接输出动作策略,又有 Critic 评估动作价值,结构清晰适合入门
核心实现四步走
1. 策略网络(Actor)设计
策略网络输出动作概率分布,损失函数包含两个关键部分:
# 伪代码示例
probs = actor(state) # 通过神经网络获得动作概率
log_probs = torch.log(probs) * advantage # 优势加权
entropy = -torch.sum(probs * log_probs) # 策略熵
loss = -(log_probs.mean() + 0.01*entropy) # 带熵正则项的损失
- 熵正则项(0.01 系数)防止策略过早收敛到局部最优
2. 价值网络(Critic)实现
Critic 评估状态价值,使用 TD 误差作为优化目标:
def compute_td_error(rewards, values, next_values, gamma=0.99):
returns = rewards + gamma * next_values * (1 - dones)
return returns - values # TD 误差
3. GAE 优势估计实战
GAE 平衡偏差与方差,关键参数 λ 控制平滑程度:
def compute_gae(rewards, values, gamma=0.99, lambda_=0.95):
deltas = rewards + gamma * values[1:] - values[:-1]
advantages = torch.zeros_like(rewards)
running_add = 0
for t in reversed(range(len(deltas))):
running_add = deltas[t] + gamma * lambda_ * running_add
advantages[t] = running_add
return advantages
4. 完整训练循环
for epoch in range(1000):
# 并行采集数据
states, actions, rewards = envs.step(...)
# 计算 GAE 优势
values = critic(states)
advantages = compute_gae(rewards, values)
# 双网络更新
actor_loss = compute_actor_loss(advantages)
critic_loss = F.mse_loss(returns, values)
# 梯度裁剪(通常设 0.5)torch.nn.utils.clip_grad_norm_(actor.parameters(), 0.5)
避坑指南
学习率设置
- 典型值:Actor 网络 3e-4,Critic 网络 1e-3
- 过大学习率会导致策略崩溃(突然变成随机动作)
折扣因子 γ
- 稀疏奖励任务(如围棋获胜)需要 γ 接近 0.99
- 密集奖励任务(如赛车游戏)可用 0.9-0.95
性能优化技巧
- 并行环境采样:同时运行 8 -16 个环境实例加速数据收集
- 梯度裁剪:Critic 网络梯度范数限制在 0.5-1.0 之间
- 归一化优势:对 GAE 结果做 batch 归一化
进阶思考
- 如何通过共享网络底层参数减少计算量?
- 当 Critic 的 loss 持续下降但 Actor 性能不提升时,可能是什么原因?
- 怎样设计自适应熵系数让探索更智能?
完整代码示例见 GitHub 仓库(链接需替换为实际项目地址)
正文完
发表至: 人工智能
近一天内
