策略梯度(Policy Gradient)原理与PyTorch实战指南
1. Policy Gradient 基础概念解析
Policy Gradient(策略梯度)是强化学习中最核心的算法家族之一,它直接对策略进行建模和优化。与基于价值函数的方法(如Q-Learning)不同,策略梯度方法直接学习一个参数化的策略π(a|s;θ),通过调整参数θ来最大化期望回报。
核心思想 :策略梯度通过采样轨迹(trajectories)来估计梯度,然后沿着梯度方向更新策略参数。简单来说,算法会:
- 增加带来高回报动作的概率
- 减少带来低回报动作的概率
- 通过反复迭代逐渐逼近最优策略
关键特性:策略梯度是典型的on-policy算法,意味着它必须使用当前策略生成的样本进行学习。这与off-policy方法(如DQN)形成鲜明对比。
2. 策略梯度数学原理拆解
2.1 目标函数定义
策略优化的目标是最大化期望回报:
J(θ) = E[Σγ^t r_t | πθ]
其中γ是折扣因子,r_t是t时刻的即时奖励。
2.2 策略梯度定理
策略梯度定理给出了目标函数梯度的解析表达式:
∇J(θ) = E[∇logπ(a|s;θ) * Q^π(s,a)]
这个优雅的公式告诉我们:可以通过采样得到的(state, action, return)三元组来估计梯度。
2.3 实际实现中的改进
原始策略梯度存在高方差问题,实践中常用以下技术改进:
-
基线(Baseline) :减去状态值函数V(s)作为基线,降低方差:
A(s,a) = Q(s,a) - V(s) -
GAE(Generalized Advantage Estimation) :平衡偏差和方差的折中方法:
δ_t = r_t + γV(s_{t+1}) - V(s_t) A_t^GAE = Σ(γλ)^l δ_{t+l}其中λ∈[0,1]是调节参数
3. Vanilla Policy Gradient 实现详解
3.1 算法伪代码
初始化策略参数θ
for 迭代=1,2,... do
使用当前策略πθ收集轨迹样本
计算每个状态-动作对的优势估计A_t
计算策略梯度估计:g = Σ∇logπ(a_t|s_t)A_t
更新策略参数:θ ← θ + α*g
可选:更新价值函数估计V(s)
end for
3.2 PyTorch实现关键组件
import torch
import torch.nn as nn
import torch.optim as optim
class PolicyNetwork(nn.Module):
def __init__(self, obs_dim, act_dim):
super().__init__()
self.fc1 = nn.Linear(obs_dim, 64)
self.fc2 = nn.Linear(64, act_dim)
def forward(self, x):
x = torch.tanh(self.fc1(x))
return torch.softmax(self.fc2(x), dim=-1)
# 训练循环示例
def train(policy, optimizer, trajectories):
states, actions, advantages = trajectories
probs = policy(states)
dist = torch.distributions.Categorical(probs)
log_probs = dist.log_prob(actions)
# 策略梯度损失
policy_loss = -(log_probs * advantages).mean()
optimizer.zero_grad()
policy_loss.backward()
optimizer.step()
4. 实战技巧与调参经验
4.1 超参数设置指南
| 参数 | 典型值 | 作用说明 |
|---|---|---|
| 学习率(π) | 3e-4 | 策略网络的学习率 |
| 学习率(V) | 1e-3 | 价值网络的学习率 |
| GAE λ | 0.97 | 优势估计的衰减系数 |
| γ | 0.99 | 未来奖励的折扣因子 |
| batch_size | 4000 | 每次更新的样本数 |
| train_v_iters | 80 | 价值网络每轮更新次数 |
4.2 常见问题排查
-
训练不稳定 :
- 检查梯度是否爆炸(添加梯度裁剪)
- 降低学习率(特别是策略网络的学习率)
- 增加batch size减少方差
-
性能停滞 :
- 尝试不同的网络架构(如增加层宽)
- 调整GAE的λ参数(通常在0.9-0.99之间)
- 检查奖励函数设计是否合理
-
探索不足 :
- 在策略输出添加熵正则项:
entropy = -torch.sum(probs * torch.log(probs), dim=-1).mean() loss = policy_loss - 0.01*entropy # 熵系数可调
- 在策略输出添加熵正则项:
5. 进阶发展与变体算法
5.1 自然策略梯度(NPG)
通过引入Fisher信息矩阵的逆来调整更新方向:
θ ← θ + αF^{-1}∇J(θ)
其中F是策略分布的Fisher信息矩阵。
5.2 TRPO(Trust Region Policy Optimization)
通过约束策略更新的KL散度来保证稳定性:
maximize E[π(a|s)/π_old(a|s) * A]
s.t. KL(π_old||π) < δ
5.3 PPO(Proximal Policy Optimization)
通过裁剪概率比来近似实现TRPO的约束:
L(θ) = E[min(r(θ)A, clip(r(θ),1-ε,1+ε)A)]
其中r(θ)=π(a|s)/π_old(a|s)
6. 实际应用中的工程考量
-
并行采样 :使用多worker同时收集样本可以显著加速训练。在PyTorch中可以用multiprocessing模块实现:
from torch.multiprocessing import Process, Queue -
状态归一化 :对观测值进行running mean/std归一化有助于稳定训练:
class RunningMeanStd: def __init__(self, shape): self.mean = torch.zeros(shape) self.var = torch.ones(shape) self.count = 0 def update(self, x): batch_mean = x.mean(dim=0) batch_var = x.var(dim=0) # 更新全局统计量... -
模型保存与加载 :
# 保存 torch.save({ 'policy': policy.state_dict(), 'optimizer': optimizer.state_dict(), }, 'checkpoint.pth') # 加载 checkpoint = torch.load('checkpoint.pth') policy.load_state_dict(checkpoint['policy'])
在真实项目中,我发现策略梯度算法的性能对随机种子非常敏感。通常需要运行多个随机种子(如5个)并取平均性能来评估算法效果。另一个实用技巧是在训练初期保留一些随机性(如保持较高的熵系数),随着训练进展逐渐降低探索强度。
更多推荐




所有评论(0)