共计 2802 个字符,预计需要花费 8 分钟才能阅读完成。
背景痛点
在强化学习中,Actor-Critic 框架结合了策略梯度(Actor)和价值函数(Critic)的优点,能够实现更稳定和高效的训练。然而,在实际应用中,Actor-Critic 网络仍然面临一些常见的参数更新问题:

- 梯度消失 :当策略更新步长过小时,梯度信号可能变得极其微弱,导致训练停滞。
- 更新不稳定 :策略和 Critic 的更新可能相互干扰,导致训练过程出现震荡或发散。
- 高方差问题 :由于策略梯度的蒙特卡洛性质,梯度估计的方差可能较高,影响收敛速度。
这些问题直接影响了模型的收敛速度和稳定性,因此需要深入理解参数更新机制和损失函数设计,以优化训练效果。
技术解析
参数更新公式推导
Actor-Critic 的核心思想是通过 Critic 提供的优势函数(Advantage Function)来指导 Actor 的策略更新。具体来说,策略梯度可以表示为:
$$\nabla_\theta J(\theta) = \mathbb{E}{\pi\theta} [\nabla_\theta \log \pi_\theta(a|s) \cdot A^\pi(s, a)]$$
其中,$A^\pi(s, a)$ 是优势函数,通常定义为 $A^\pi(s, a) = Q^\pi(s, a) – V^\pi(s)$。Critic 的目标是通过最小化价值函数的误差来估计 $V^\pi(s)$ 或 $Q^\pi(s, a)$,其损失函数为:
$$L(\phi) = \mathbb{E}{\pi\theta} [(V_\phi(s) – R)^2]$$
其中,$R$ 是实际的回报值。
损失函数设计对比
不同的 Actor-Critic 变体在损失函数设计上有所不同,以下是两种常见方法的对比:
- A2C(Advantage Actor-Critic):
- Actor 的损失函数直接使用优势函数加权策略梯度。
- Critic 的损失函数为均方误差(MSE)。
- 优点:实现简单,计算高效。
-
缺点:对高方差敏感,可能导致训练不稳定。
-
PPO(Proximal Policy Optimization):
- 通过引入策略更新的裁剪机制(Clipping)限制策略变化幅度。
- 损失函数包含策略比率裁剪项和 Critic 的误差项。
- 优点:训练更稳定,适合复杂任务。
- 缺点:实现稍复杂,超参数调优要求更高。
代码实现
以下是一个基于 PyTorch 的 Actor-Critic 网络实现,包含网络结构、参数更新和损失函数计算。
import torch
import torch.nn as nn
import torch.optim as optim
import torch.nn.functional as F
class ActorCritic(nn.Module):
def __init__(self, state_dim, action_dim, hidden_dim=128):
super(ActorCritic, self).__init__()
# Actor 网络(策略网络)self.actor = nn.Sequential(nn.Linear(state_dim, hidden_dim),
nn.ReLU(),
nn.Linear(hidden_dim, action_dim),
nn.Softmax(dim=-1)
)
# Critic 网络(价值网络)self.critic = nn.Sequential(nn.Linear(state_dim, hidden_dim),
nn.ReLU(),
nn.Linear(hidden_dim, 1)
)
def forward(self, state):
action_probs = self.actor(state)
state_value = self.critic(state)
return action_probs, state_value
# 定义损失函数和优化器
model = ActorCritic(state_dim=4, action_dim=2)
optimizer = optim.Adam(model.parameters(), lr=0.001)
# 参数更新逻辑
def update_policy(states, actions, rewards, next_states, dones, gamma=0.99):
states = torch.FloatTensor(states)
actions = torch.LongTensor(actions)
rewards = torch.FloatTensor(rewards)
next_states = torch.FloatTensor(next_states)
dones = torch.FloatTensor(dones)
# 计算 Critic 的损失(均方误差)_, current_values = model(states)
_, next_values = model(next_states)
target_values = rewards + gamma * next_values * (1 - dones)
critic_loss = F.mse_loss(current_values, target_values.detach())
# 计算 Actor 的损失(策略梯度)action_probs, _ = model(states)
log_probs = torch.log(action_probs.gather(1, actions.unsqueeze(1)))
advantages = target_values - current_values.detach()
actor_loss = -(log_probs * advantages).mean()
# 更新参数
optimizer.zero_grad()
total_loss = actor_loss + critic_loss
total_loss.backward()
optimizer.step()
性能考量
在 Actor-Critic 训练中,以下超参数对性能有显著影响:
- 学习率(Learning Rate):过大的学习率可能导致训练不稳定,过小则收敛缓慢。建议从较小的值(如 0.001)开始尝试。
- 折扣因子(Gamma):控制未来回报的权重,通常设置在 0.9 到 0.99 之间。
- 批量大小(Batch Size):较大的批量可以减少梯度方差,但会增加计算开销。
避坑指南
- 训练不稳定 :
-
解决方法:使用 PPO 等稳定算法,或引入梯度裁剪(Gradient Clipping)。
-
梯度消失 :
-
解决方法:适当增大学习率,或使用 Advantage Normalization。
-
高方差问题 :
- 解决方法:增加批量大小,或使用 GAE(Generalized Advantage Estimation)。
开放性问题
- 如何设计更高效的优势函数估计方法,以进一步降低方差?
- 在连续动作空间中,Actor-Critic 网络的结构和损失函数需要如何调整?
- 如何结合多步回报(Multi-step Returns)来优化 Critic 的更新?
