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 实际实现中的改进

原始策略梯度存在高方差问题,实践中常用以下技术改进:

  1. 基线(Baseline) :减去状态值函数V(s)作为基线,降低方差:

    A(s,a) = Q(s,a) - V(s)
    
  2. 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 常见问题排查

  1. 训练不稳定

    • 检查梯度是否爆炸(添加梯度裁剪)
    • 降低学习率(特别是策略网络的学习率)
    • 增加batch size减少方差
  2. 性能停滞

    • 尝试不同的网络架构(如增加层宽)
    • 调整GAE的λ参数(通常在0.9-0.99之间)
    • 检查奖励函数设计是否合理
  3. 探索不足

    • 在策略输出添加熵正则项:
      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. 实际应用中的工程考量

  1. 并行采样 :使用多worker同时收集样本可以显著加速训练。在PyTorch中可以用multiprocessing模块实现:

    from torch.multiprocessing import Process, Queue
    
  2. 状态归一化 :对观测值进行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)
            # 更新全局统计量...
    
  3. 模型保存与加载

    # 保存
    torch.save({
        'policy': policy.state_dict(),
        'optimizer': optimizer.state_dict(),
    }, 'checkpoint.pth')
    
    # 加载
    checkpoint = torch.load('checkpoint.pth')
    policy.load_state_dict(checkpoint['policy'])
    

在真实项目中,我发现策略梯度算法的性能对随机种子非常敏感。通常需要运行多个随机种子(如5个)并取平均性能来评估算法效果。另一个实用技巧是在训练初期保留一些随机性(如保持较高的熵系数),随着训练进展逐渐降低探索强度。

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐