1. 策略梯度方法核心原理剖析
策略梯度(Policy Gradient)作为强化学习中Policy-based方法的典型代表,其核心思想是将策略参数化为πθ(a|s)=P(a|s,θ),通过直接优化策略参数θ来最大化期望回报。与Value-based方法(如Q-learning)不同,策略梯度不需要维护价值函数表,而是直接输出动作的概率分布。
1.1 策略参数化实现方式
在实际实现中,策略通常用神经网络表示,输入状态s,输出动作概率分布。对于离散动作空间,常用softmax输出层:
python复制import torch
import torch.nn as nn
class PolicyNetwork(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 = torch.relu(self.fc1(state))
action_scores = self.fc2(x)
return torch.softmax(action_scores, dim=-1)
对于连续动作空间,通常假设动作服从高斯分布,网络输出均值和方差:
python复制class GaussianPolicy(nn.Module):
def __init__(self, state_dim, action_dim):
super().__init__()
self.fc1 = nn.Linear(state_dim, 64)
self.fc_mean = nn.Linear(64, action_dim)
self.fc_logstd = nn.Parameter(torch.zeros(action_dim))
def forward(self, state):
x = torch.relu(self.fc1(state))
mean = self.fc_mean(x)
std = torch.exp(self.fc_logstd)
return torch.distributions.Normal(mean, std)
1.2 策略梯度定理数学推导
策略梯度定理给出了目标函数J(θ)(通常为期望回报)关于参数θ的梯度表达式:
∇θJ(θ) = Eπ[Qπ(s,a)∇θlogπθ(a|s)]
其中Qπ(s,a)是状态-动作价值函数。这个优雅的表达式表明,我们可以通过采样轨迹来估计梯度,而不需要知道环境动态。
实际实现时,常用蒙特卡洛估计:
python复制def compute_policy_gradient(trajectories, policy_net, gamma=0.99):
grads = []
for trajectory in trajectories:
R = 0
for t in reversed(range(len(trajectory))):
state, action, reward = trajectory[t]
R = gamma * R + reward
prob = policy_net(state)
log_prob = torch.log(prob[action])
grads.append(-log_prob * R) # 负号因为PyTorch默认做梯度下降
return torch.stack(grads).mean()
2. 策略梯度算法实现细节
2.1 REINFORCE算法实现
REINFORCE是最基础的策略梯度算法,其核心步骤包括:
- 用当前策略πθ采样若干轨迹
- 对每个轨迹计算回报Gt
- 估计梯度∇θJ(θ) ≈ ΣGt∇θlogπθ(at|st)
- 更新参数θ ← θ + α∇θJ(θ)
完整实现示例:
python复制def reinforce(env, policy_net, episodes=1000, lr=1e-3, gamma=0.99):
optimizer = torch.optim.Adam(policy_net.parameters(), lr=lr)
for ep in range(episodes):
state = env.reset()
trajectory = []
done = False
# 采样轨迹
while not done:
state_tensor = torch.FloatTensor(state)
action_probs = policy_net(state_tensor)
action = torch.multinomial(action_probs, 1).item()
next_state, reward, done, _ = env.step(action)
trajectory.append((state_tensor, action, reward))
state = next_state
# 计算梯度
optimizer.zero_grad()
R = 0
policy_loss = []
for t in reversed(range(len(trajectory))):
state_tensor, action, reward = trajectory[t]
R = gamma * R + reward
prob = policy_net(state_tensor)
log_prob = torch.log(prob[action])
policy_loss.append(-log_prob * R)
# 参数更新
total_loss = torch.stack(policy_loss).sum()
total_loss.backward()
optimizer.step()
2.2 基线技巧与方差缩减
原始REINFORCE算法的一个主要问题是梯度估计的方差较大。引入基线b(s)可以显著降低方差而不引入偏差:
∇θJ(θ) = Eπ[(Qπ(s,a)-b(s))∇θlogπθ(a|s)]
常见基线选择:
- 状态价值函数Vπ(s)
- 移动平均回报
- 独立学习的价值函数网络
带基线的实现改进:
python复制class ValueNetwork(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 = torch.relu(self.fc1(state))
return self.fc2(x)
def compute_advantage(trajectory, value_net, gamma=0.99):
states = torch.stack([t[0] for t in trajectory])
rewards = torch.FloatTensor([t[2] for t in trajectory])
values = value_net(states).squeeze()
next_values = torch.cat([values[1:], torch.FloatTensor([0])])
deltas = rewards + gamma * next_values - values
advantages = []
advantage = 0
for delta in reversed(deltas):
advantage = delta + gamma * advantage
advantages.append(advantage)
return torch.FloatTensor(advantages[::-1])
3. 高级策略梯度算法演进
3.1 Actor-Critic架构
Actor-Critic结合了策略梯度(Actor)和价值函数近似(Critic)的优点:
- Actor:负责选择动作(策略πθ)
- Critic:评估动作价值(价值函数Vw)
实现框架:
python复制class ActorCritic(nn.Module):
def __init__(self, state_dim, action_dim):
super().__init__()
# 共享特征提取层
self.fc1 = nn.Linear(state_dim, 64)
# Actor分支
self.actor = nn.Linear(64, action_dim)
# Critic分支
self.critic = nn.Linear(64, 1)
def forward(self, state):
x = torch.relu(self.fc1(state))
action_probs = torch.softmax(self.actor(x), dim=-1)
state_value = self.critic(x)
return action_probs, state_value
3.2 近端策略优化(PPO)
PPO通过引入clip机制防止策略更新过大,是目前最流行的策略梯度算法之一。其目标函数为:
L(θ) = E[min(rt(θ)At, clip(rt(θ),1-ε,1+ε)At)]
其中rt(θ)=πθ(at|st)/πθ_old(at|st)是概率比。
PPO-clip实现关键部分:
python复制def ppo_update(policy_net, old_policy_net, optimizer, samples, clip_eps=0.2, gamma=0.99):
states, actions, old_log_probs, returns, advantages = samples
# 计算新策略的概率比
new_probs = policy_net(states)
new_log_probs = torch.log(new_probs.gather(1, actions.unsqueeze(1)))
ratios = torch.exp(new_log_probs - old_log_probs)
# PPO-clip目标函数
surr1 = ratios * advantages
surr2 = torch.clamp(ratios, 1-clip_eps, 1+clip_eps) * advantages
policy_loss = -torch.min(surr1, surr2).mean()
# 价值函数损失
values = policy_net.critic(states)
value_loss = (returns - values).pow(2).mean()
# 总损失
loss = policy_loss + 0.5 * value_loss
# 参数更新
optimizer.zero_grad()
loss.backward()
optimizer.step()
4. 策略梯度实践中的关键问题
4.1 探索与利用的平衡
策略梯度方法容易陷入局部最优,常见解决方案:
- 熵正则化:在目标函数中加入策略熵项
python复制entropy = -(probs * torch.log(probs)).sum(dim=1).mean() loss = policy_loss - 0.01 * entropy # 熵系数通常取0.01-0.1 - 初始化策略为均匀分布
- 添加噪声(如高斯噪声)到动作选择
4.2 超参数调优经验
- 学习率:通常3e-4到1e-3(Adam优化器)
- 折扣因子γ:0.9-0.99
- 轨迹长度:足够长以包含有意义的行为(通常100-1000步)
- 批量大小:32-2048,取决于任务复杂度
- PPO中的clip范围ε:0.1-0.3
4.3 训练不稳定问题排查
当训练出现震荡或崩溃时,检查:
- 梯度爆炸:添加梯度裁剪
python复制torch.nn.utils.clip_grad_norm_(policy_net.parameters(), max_norm=0.5) - 价值函数尺度:归一化回报/优势
- 策略更新幅度:监控KL散度
- 随机种子影响:多次运行验证稳定性
5. 策略梯度在机器人控制中的应用
以机械臂抓取任务为例,策略网络设计需考虑:
- 状态空间:关节角度、末端位置、目标位置、力传感器数据
- 动作空间:关节力矩或速度指令
- 奖励函数设计:
- 成功抓取:+100
- 距离奖励:-||末端-目标||
- 平滑惩罚:-||at-at-1||
- 碰撞惩罚:-10
典型训练流程:
- 在仿真环境(如Isaac Sim)中预训练
- 使用域随机化增强泛化能力
- 迁移到真实机器人进行微调
- 部署时添加安全约束(如导纳控制)
策略梯度方法特别适合这类连续控制任务,因为:
- 能直接输出连续动作
- 可以处理高维状态空间
- 通过reward shaping可以精确引导学习过程
