共计 3195 个字符,预计需要花费 8 分钟才能阅读完成。
为什么需要 Actor-Critic?
强化学习中有两种主要方法:基于价值的方法(如 Q -Learning)和基于策略的方法(如 Policy Gradient)。前者在离散动作空间表现良好但难以处理连续动作,后者虽然通用但训练方差大。Actor-Critic 结合二者优势:

- Actor(策略网络)负责生成动作,解决 ” 做什么 ” 的问题
- Critic(价值网络)评估动作好坏,提供 ” 做得怎么样 ” 的反馈
这种分工合作方式大幅提升了训练稳定性,使其成为当今最流行的强化学习架构之一,从游戏 AI 到机器人控制都有广泛应用。
核心参数更新机制
1. 策略梯度(Actor 更新)
Actor 的参数更新遵循策略梯度定理:
# 策略梯度计算公式
def compute_actor_loss(states, actions, advantages):
# 获取当前策略下动作的概率对数
log_probs = actor_network(states).log_prob(actions)
# 带优势函数的策略梯度
return -(log_probs * advantages).mean()
关键点:
- 使用 优势函数(Advantage)代替简单回报,减少方差
- 梯度更新方向是 提高优势动作的概率
- 实践中常加入熵正则项防止策略过早收敛
2. 价值函数(Critic 更新)
Critic 通过最小化 TD 误差(Temporal Difference Error)来学习:
def compute_critic_loss(states, returns):
# 预测状态价值
predicted_values = critic_network(states)
# 均方误差损失
return F.mse_loss(predicted_values, returns)
注意事项:
- 可采用 n -step TD 或 GAE(Generalized Advantage Estimation)
- 价值函数更新通常比策略更新更快(学习率更大)
主流变体对比
| 算法 | 关键改进 | 适用场景 |
|---|---|---|
| A2C | 同步多环境采样 | 单机训练 |
| A3C | 异步多进程更新 | 分布式系统 |
| PPO | 带裁剪的策略更新 | 高维连续控制 |
| SAC | 最大熵强化学习 | 需要高探索性的任务 |
完整 PyTorch 实现
网络结构定义
import torch
import torch.nn as nn
import torch.optim as optim
import torch.nn.functional as F
from torch.distributions import Categorical
class Actor(nn.Module):
def __init__(self, state_dim, action_dim):
super().__init__()
self.fc1 = nn.Linear(state_dim, 64)
self.fc2 = nn.Linear(64, action_dim)
def forward(self, state):
x = F.relu(self.fc1(state))
return F.softmax(self.fc2(x), dim=-1)
class Critic(nn.Module):
def __init__(self, state_dim):
super().__init__()
self.fc1 = nn.Linear(state_dim, 64)
self.fc2 = nn.Linear(64, 1)
def forward(self, state):
x = F.relu(self.fc1(state))
return self.fc2(x)
训练循环核心
# 初始化
actor = Actor(state_dim, action_dim)
critic = Critic(state_dim)
actor_optim = optim.Adam(actor.parameters(), lr=1e-3)
critic_optim = optim.Adam(critic.parameters(), lr=3e-3)
for episode in range(1000):
state = env.reset()
done = False
while not done:
# 采样动作
prob = actor(torch.FloatTensor(state))
m = Categorical(prob)
action = m.sample()
# 环境交互
next_state, reward, done, _ = env.step(action.item())
# 计算优势
value = critic(torch.FloatTensor(state))
next_value = critic(torch.FloatTensor(next_state))
advantage = reward + (1-done)*gamma*next_value - value
# 更新 Critic
critic_loss = F.mse_loss(value, reward + (1-done)*gamma*next_value)
critic_optim.zero_grad()
critic_loss.backward()
critic_optim.step()
# 更新 Actor
actor_loss = -m.log_prob(action) * advantage.detach()
actor_optim.zero_grad()
actor_loss.backward()
actor_optim.step()
state = next_state
调优实战技巧
学习率设置
- 典型比例:Critic 学习率是 Actor 的 3 -10 倍
- 使用学习率衰减:
scheduler = optim.lr_scheduler.StepLR(actor_optim, step_size=100, gamma=0.9)
折扣因子 γ
- 取值范围通常为 0.9-0.99
- 长期任务取较高值(0.99)
- 即时奖励重要的任务取较低值(0.9)
经验回放技巧
from collections import deque
import random
class ReplayBuffer:
def __init__(self, capacity):
self.buffer = deque(maxlen=capacity)
def push(self, state, action, reward, next_state, done):
self.buffer.append((state, action, reward, next_state, done))
def sample(self, batch_size):
return random.sample(self.buffer, batch_size)
常见问题解决
梯度异常
- 梯度爆炸:添加梯度裁剪
nn.utils.clip_grad_norm_(actor.parameters(), 0.5) - 梯度消失:使用 ReLU 激活函数 + 合适的初始化
探索不足
- 添加策略熵正则项:
entropy = -torch.sum(prob * torch.log(prob)) actor_loss -= 0.01 * entropy # 系数可调
训练波动
- 使用目标网络(Target Network)
- 增大批次大小(Batch Size)
- 尝试 PPO 的 Clipped Surrogate Objective
拓展思考
如何适应连续动作空间?关键修改:
- Actor 输出高斯分布的均值和方差
- 使用重参数化技巧(Reparameterization Trick)采样
- 调整 Critic 输出维度
推荐延伸阅读:
–《Proximal Policy Optimization Algorithms》(PPO 原论文)
– OpenAI Spinning Up 教程
– Stable Baselines3 开源实现
通过本文的实践指导,你应该已经掌握了 Actor-Critic 的核心实现要点。建议从 CartPole 等简单环境开始实验,逐步挑战更复杂任务。记住调参过程需要耐心,好的强化学习模型往往需要数百次的迭代优化。
正文完
发表至: 人工智能
近一天内
