4、策略梯度方法入门:REINFORCE算法原理、从概率分布采样动作、蒙特卡洛策略梯度推导

好,咱们今天来聊一个硬核话题——策略梯度。说实话,我刚接触强化学习那会儿,看到“梯度”两个字就头大。但后来我发现,这东西其实没那么玄乎。说白了,策略梯度就是让智能体学会“什么情况下该做什么动作”,而且是用一种很自然的方式——试错。

你想想看,我们人类是怎么学骑自行车的?摔几次,就知道什么时候该拐弯、什么时候该刹车。策略梯度也是这个道理。它不像Q-learning那样去估计每个动作的价值,而是直接优化策略本身。嗯,这就是它的核心魅力。

4.1 从值函数到策略:为什么需要策略梯度?

我之前做项目时,遇到过一个机器人抓取任务。用DQN(深度Q网络)做,效果还行,但动作空间一变大,Q值估计就崩了。为什么?因为DQN需要计算每个动作的Q值,动作一多,计算量爆炸。

策略梯度方法绕开了这个问题。它不计算Q值,而是直接输出动作的概率分布。你想想看,这多省事?

核心区别:

  • 值函数方法:先估计Q值,再根据Q值选动作(如ε-贪婪)
  • 策略梯度方法:直接优化策略参数,输出动作概率

举个例子。假设你是一个游戏角色,面前有5个方向可以走。值函数方法会先算出每个方向能得多少分,然后选最高分的那个。策略梯度方法呢?它会直接告诉你:向左走的概率是0.4,向右是0.3,向前是0.2,向后是0.1。然后你按这个概率去采样。

我个人习惯用策略梯度处理连续动作空间的问题。比如控制机械臂的关节角度,动作是连续的,Q-learning根本没法搞。这时候策略梯度就派上用场了。

4.2 REINFORCE算法:最朴素的策略梯度

REINFORCE算法,名字挺唬人,其实原理很简单。它属于蒙特卡洛策略梯度方法,也就是说,它需要跑完一整条轨迹,才能更新一次策略。

我在项目中遇到过一个问题:用REINFORCE训练一个简单的导航任务,智能体总是原地打转。后来发现,是因为奖励稀疏,智能体很难得到正向反馈。嗯,这个坑咱们后面会讲怎么避。

REINFORCE的核心思想是:如果某个动作带来了好的回报,就增加这个动作的概率;反之,就降低它的概率。

它的更新公式长这样:

θ = θ + α * ∇θ log π(a|s) * G

其中:

  • θ:策略网络的参数
  • α:学习率
  • π(a|s):在状态s下采取动作a的概率
  • G:从当前时刻到结束的累计折扣回报

说白了,就是拿“回报”当权重,去调整动作概率。回报高,权重就大,这个动作的概率就往上提;回报低,权重就小,概率就往下压。

小技巧:我在实际项目中,通常会给G减去一个baseline(比如平均回报),这样可以降低方差,让训练更稳定。这个技巧叫“带基线的REINFORCE”。

4.3 从概率分布采样动作:随机性的艺术

策略梯度方法的一个关键点,就是从概率分布中采样动作。为什么要采样?而不是直接选概率最大的那个?

你想想看,如果每次都选概率最大的,那就变成了确定性策略,失去了探索的能力。智能体可能永远发现不了更好的动作。

举个例子。假设在某个状态下,向左走的概率是0.6,向右是0.4。如果每次都选向左,那向右这个动作就永远没机会尝试了。万一向右才是最优解呢?

所以,我们按概率分布去采样。这次可能向左,下次可能向右。这样既能利用已知的好动作,又能探索未知的可能性。

我记得有一次做游戏AI,智能体学会了走一条固定的路线,但那条路线并不是最优的。后来我检查代码,发现是采样逻辑写错了——我用了argmax而不是采样。改过来之后,智能体很快就找到了更短的路径。

避坑指南:我曾经在采样时忘记设置随机种子,导致每次实验的结果都不一样,调试起来非常痛苦。建议在训练时固定随机种子,保证可复现性。

4.4 蒙特卡洛策略梯度推导:一步步拆解

好,咱们来推导一下蒙特卡洛策略梯度。别怕,我会用最通俗的方式讲。

我们的目标是最大化期望回报:

J(θ) = E[G | πθ]

其中G是整条轨迹的累计回报。我们希望找到参数θ,让J(θ)最大。

怎么求梯度?用链式法则:

∇θ J(θ) = E[∇θ log π(a|s) * G]

这个公式就是策略梯度定理的核心。它告诉我们:梯度的方向,由“对数概率的梯度”乘以“回报”决定。

为什么是对数概率?因为对数函数能把乘法变成加法,方便求导。你想想看:

∇θ log π(a|s) = (1/π(a|s)) * ∇θ π(a|s)

这样,即使π(a|s)很小,梯度也不会爆炸。嗯,数学上很优雅。

在实际计算中,我们没法求期望,所以用蒙特卡洛采样来近似:

∇θ J(θ) ≈ (1/N) * Σ ∇θ log π(at|st) * Gt

其中N是采样的轨迹数量。这就是蒙特卡洛策略梯度的由来。

推导要点总结:

  1. 定义目标函数J(θ) = 期望回报
  2. 对J(θ)求梯度,得到∇θ J(θ)
  3. 利用对数技巧,把梯度写成∇θ log π(a|s) * G的形式
  4. 用蒙特卡洛采样近似期望

4.5 完整算法流程与代码示例

说了这么多,咱们来看看REINFORCE算法的完整流程:

1. 初始化策略网络参数θ
2. 循环每个episode:
   a. 从初始状态s0开始
   b. 循环每一步t:
      - 从策略πθ采样动作at
      - 执行at,得到奖励rt和下一状态st+1
      - 记录(st, at, rt)
   c. 计算每个时刻的累计回报Gt = Σ γ^(k-t) * rk
   d. 更新策略参数:
      θ = θ + α * Σ ∇θ log π(at|st) * Gt
3. 直到收敛

下面是一个简单的PyTorch实现片段:

import torch
import torch.nn as nn
import torch.optim as optim

class PolicyNetwork(nn.Module):
    def __init__(self, state_dim, action_dim):
        super().__init__()
        self.fc = nn.Sequential(
            nn.Linear(state_dim, 128),
            nn.ReLU(),
            nn.Linear(128, action_dim),
            nn.Softmax(dim=-1)
        )
    
    def forward(self, state):
        return self.fc(state)

# 训练循环
policy = PolicyNetwork(state_dim, action_dim)
optimizer = optim.Adam(policy.parameters(), lr=0.001)

for episode in range(1000):
    states, actions, rewards = [], [], []
    state = env.reset()
    
    # 收集一条轨迹
    while True:
        probs = policy(state)
        action = torch.multinomial(probs, 1).item()
        next_state, reward, done, _ = env.step(action)
        
        states.append(state)
        actions.append(action)
        rewards.append(reward)
        
        if done:
            break
        state = next_state
    
    # 计算累计回报
    G = 0
    returns = []
    for r in reversed(rewards):
        G = r + 0.99 * G
        returns.insert(0, G)
    
    returns = torch.tensor(returns)
    
    # 计算损失并更新
    loss = 0
    for s, a, G in zip(states, actions, returns):
        probs = policy(s)
        log_prob = torch.log(probs[a])
        loss -= log_prob * G
    
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()

个人经验:这段代码里,我用了torch.multinomial来采样动作,而不是argmax。这样能保证探索性。另外,学习率α我一般设0.001左右,太大容易发散,太小收敛太慢。

4.6 知识体系与核心逻辑

为了让你更直观地理解本章的知识结构,我画了一张流程图:

策略梯度方法核心逻辑 策略梯度方法 REINFORCE算法 概率分布采样 蒙特卡洛梯度推导 核心:用累计回报G 调整动作概率 θ = θ + α·∇logπ·G 核心:按概率随机选择 保证探索与利用平衡 torch.multinomial() 核心:用采样近似期望 ∇J ≈ (1/N)Σ∇logπ·G 对数技巧简化计算 输出:优化后的策略网络

这张图把本章的三个核心内容串起来了。从左到右:REINFORCE算法是框架,概率分布采样是动作选择方式,蒙特卡洛梯度推导是数学基础。三者缺一不可。

4.7 常见问题与避坑指南

最后,分享几个我在项目中踩过的坑:

  • 梯度方差大:REINFORCE的梯度方差通常很大,训练不稳定。我建议用带基线的版本,或者引入优势函数。
  • 奖励设计:稀疏奖励会让REINFORCE很难收敛。我曾经试过给每一步都加一个小奖励,效果立竿见影。
  • 学习率敏感:策略梯度对学习率很敏感。我一般先用0.001试,如果loss震荡就调小,如果收敛太慢就调大。
  • 采样效率低:REINFORCE是on-policy的,每次更新都要重新采样。如果环境交互成本高,可以考虑用重要性采样改成off-policy。

重要提醒:千万不要在还没跑完一个episode时就更新策略!REINFORCE需要完整的轨迹来计算累计回报G。我刚开始学的时候犯过这个错,结果模型怎么都学不会。

好了,策略梯度入门就讲到这里。记住一句话:REINFORCE虽然简单,但它是理解更高级策略梯度方法(如PPO、A2C)的基础。把这个搞懂了,后面的路就好走了。

可可精品资料库