1. 策略梯度方法入门:从直觉到数学
第一次接触策略梯度(Policy Gradients)这个概念时,我正试图训练一个玩Atari游戏的AI。当时最让我困惑的是:为什么不像监督学习那样直接给出正确动作?后来才明白,强化学习的核心在于让智能体通过试错自己发现最优策略。策略梯度方法正是实现这一目标的经典算法。
策略梯度属于策略优化方法的直接代表,与基于价值函数的方法(如Q-learning)形成鲜明对比。它的核心思想是通过参数化策略并沿性能梯度方向更新参数,逐步提高获得高回报动作的概率。想象你在教小狗做动作:当它偶然做出你想要的行为时,你立即给予奖励,这个行为后续出现的概率就会提高——策略梯度本质上就是在数学上实现这个过程。
关键区别:价值函数方法(如DQN)先评估状态或动作的价值,再从中推导策略;而策略梯度直接参数化并优化策略本身,更适合连续动作空间和高维问题。
2. 策略梯度核心原理拆解
2.1 策略参数化与目标函数
策略π(a|s;θ)表示在状态s下采取动作a的概率,由参数θ决定。我们的目标是找到最大化期望回报的θ:
J(θ) = E[Σγ^t r_t | πθ]
其中γ是折扣因子。通过梯度上升更新参数:
θ ← θ + α∇θ J(θ)
这个看似简单的公式背后蕴含着几个关键点:
- 梯度指向回报增长最快的方向
- 学习率α控制更新步长
- 期望回报包含从初始状态到终止的整个轨迹
2.2 策略梯度定理的推导
经过推导(详见附录数学细节),策略梯度可表示为:
∇θ J(θ) = E[∇θ log π(a|s;θ) Q^π(s,a)]
这个优雅的公式告诉我们:
- 梯度与动作概率的对数梯度成正比
- 用动作价值Q^π(s,a)作为权重
- 只需知道动作的相对优劣,无需绝对价值
在实际实现时,我们常用蒙特卡洛采样来估计这个期望:
∇θ J(θ) ≈ 1/N Σ_i Σ_t ∇θ log π(a_t^i|s_t^i;θ) G_t^i
其中G_t^i是从时刻t开始的累积回报。
3. 策略梯度算法实现详解
3.1 基础算法实现步骤
以REINFORCE算法为例,其伪代码如下:
- 初始化策略参数θ
- for 每个episode:
a. 根据π(a|s;θ)生成轨迹{s1,a1,r1,...,sT,aT,rT}
b. for t=1到T:
i. 计算累积回报G_t = Σ_{k=t}^T γ^{k-t} r_k
ii. 更新θ ← θ + α γ^t G_t ∇θ log π(a_t|s_t;θ) - 返回优化后的策略参数θ
实现提示:在实际编码时,通常会对G_t进行归一化(减去均值除以标准差)以减少方差。
3.2 代码实现关键点
用Python实现REINFORCE的核心部分:
python复制def train(self, episodes):
for ep in range(episodes):
states, actions, rewards = [], [], []
state = self.env.reset()
# 生成轨迹
while True:
action = self.policy_net.get_action(state)
next_state, reward, done, _ = self.env.step(action)
states.append(state)
actions.append(action)
rewards.append(reward)
state = next_state
if done: break
# 计算累积回报
returns = []
G = 0
for r in reversed(rewards):
G = r + self.gamma * G
returns.insert(0, G)
# 归一化
returns = torch.tensor(returns)
returns = (returns - returns.mean()) / (returns.std() + 1e-9)
# 策略梯度更新
for state, action, G in zip(states, actions, returns):
log_prob = torch.log(self.policy_net(state)[action])
loss = -log_prob * G
self.optimizer.zero_grad()
loss.backward()
self.optimizer.step()
4. 策略梯度的改进与变体
4.1 基线方法降低方差
原始策略梯度的一个主要问题是高方差。引入基线b(s)后,梯度估计变为:
∇θ J(θ) = E[∇θ log π(a|s;θ) (Q^π(s,a)-b(s))]
常见基线选择:
- 状态价值函数V^π(s)
- 移动平均回报
- 神经网络估计的V(s)
经验分享:在实践中,我发现使用独立网络估计V(s)作为基线效果最好,但需要小心两个网络的训练平衡。
4.2 优势函数与Actor-Critic
将Q(s,a)-V(s)定义为优势函数A(s,a),得到Actor-Critic框架:
∇θ J(θ) = E[∇θ log π(a|s;θ) A(s,a)]
典型实现如A2C(Advantage Actor-Critic):
- Actor:策略网络,负责动作选择
- Critic:价值网络,评估状态价值
- 两者协同更新,平衡偏差与方差
4.3 近端策略优化(PPO)
PPO通过限制策略更新幅度来保证稳定性,其目标函数为:
L(θ) = E[min(r(θ)A, clip(r(θ),1-ε,1+ε)A)]
其中r(θ)=π_new(a|s)/π_old(a|s)是新旧策略概率比。
5. 策略梯度的实战应用与调优
5.1 典型问题与解决方案
问题1:训练不稳定,回报波动大
- 对策:减小学习率,增加批量大小,使用PPO等稳定算法
问题2:探索不足,陷入局部最优
- 对策:在策略中增加熵正则项:L = E[A(s,a)logπ(a|s)] + βH(π)
- 其中H(π)是策略熵,β控制探索强度
问题3:高维动作空间收敛慢
- 对策:对连续动作使用高斯策略,离散动作使用softmax
5.2 超参数调优指南
基于我多个项目的经验,推荐以下调优顺序:
-
首先确定合适的折扣因子γ:
- 短期任务:0.9-0.99
- 长期任务:0.99-0.999
-
调整学习率(通常3e-4到1e-5)
-
设置合适的批量大小(32到2048不等)
-
最后微调熵系数等正则项
实用技巧:使用Adam优化器通常比SGD更稳定,初始学习率设为3e-4是个不错的起点。
6. 策略梯度在复杂环境中的应用案例
6.1 机器人控制
在MuJoCo的Humanoid环境中,策略梯度方法能学习到复杂的平衡和行走策略。关键点:
- 使用高斯策略表示连续动作
- 状态包含关节角度、速度等50+维特征
- 需要处理延迟奖励问题
6.2 游戏AI训练
在星际争霸II等RTS游戏中:
- 动作空间包含数万种可能
- 采用分层策略梯度架构
- 宏观策略决定整体战术
- 微观策略控制单位动作
6.3 自然语言生成
将文本生成视为强化学习问题:
- 动作:选择下一个词
- 奖励:BLEU等评估指标
- 使用self-critical序列训练方法
7. 策略梯度的局限性与前沿发展
7.1 主要局限性
- 样本效率低:需要大量与环境交互
- 高方差:梯度估计不稳定
- 局部最优:容易陷入次优策略
- 超参数敏感:需要仔细调参
7.2 最新研究方向
- 离线强化学习:从固定数据集学习
- 多智能体策略梯度:处理竞争与合作
- 元学习策略梯度:快速适应新任务
- 结合模仿学习:利用专家示范
8. 数学附录:策略梯度定理证明
对于感兴趣的读者,以下是策略梯度定理的简要推导:
从目标函数出发:
J(θ) = ∫ p(τ;θ)R(τ) dτ
其中p(τ;θ)是轨迹τ的概率,R(τ)是其回报。
计算梯度:
∇θ J(θ) = ∫ ∇θ p(τ;θ) R(τ) dτ
= ∫ p(τ;θ) ∇θ log p(τ;θ) R(τ) dτ
= E[∇θ log p(τ;θ) R(τ)]
而轨迹概率可分解为:
p(τ;θ) = p(s0) Π π(at|st;θ) p(st+1|st,at)
因此:
∇θ log p(τ;θ) = Σ ∇θ log π(at|st;θ)
最终得到:
∇θ J(θ) = E[Σ ∇θ log π(at|st;θ) R(τ)]
通过引入因果关系和基线,可进一步优化为前面给出的形式。