Contents

强化学习:什么是PPO算法

Contents

PPO(Proximal Policy Optimization,近端策略优化) 算法是深度强化学习里非常重要的一类 策略梯度(Policy Gradient) 方法,被广泛应用于游戏智能体、机器人控制等场景。


1. 背景与问题

在强化学习(RL)中,我们有一个智能体(agent)与环境交互:

  • 状态 $s_t$
  • 动作 $a_t$
  • 奖励 $r_t$
  • 策略 $\pi_\theta(a|s)$:给定状态选择动作的概率分布,参数化为 $\theta$

目标是最大化期望回报:

$$ J(\theta) = \mathbb{E}_{\tau \sim \pi_\theta} \Big[ \sum_{t=0}^T \gamma^t r_t \Big] $$


传统的 策略梯度方法(如 REINFORCE)会直接用蒙特卡洛方法估计梯度更新策略,但存在:

  1. 方差很大(更新不稳定)
  2. 更新过大可能导致策略崩溃

于是提出 TRPO(Trust Region Policy Optimization),它通过约束新旧策略的 KL 散度,避免更新过大。但是 TRPO 实现复杂,需要解约束优化问题。

PPO 就是对 TRPO 的简化,保留稳定性,又方便实现。


2. PPO 的核心思想

核心目标:在更新策略时,不要让新策略和旧策略差别过大。

定义 概率比值

$$ r_t(\theta) = \frac{\pi_\theta(a_t | s_t)}{\pi_{\theta_{\text{old}}}(a_t | s_t)} $$

  • 如果 $r_t(\theta) > 1$,表示新策略更倾向于采取这个动作。
  • 如果 $r_t(\theta) < 1$,表示新策略更不倾向于这个动作。

我们希望提升 优势函数(Advantage Function)

$$ A_t = Q(s_t, a_t) - V(s_t) $$

表示在状态 $s_t$ 下,采取动作 $a_t$ 比平均水平好多少。


3. PPO 的目标函数

PPO 提出了 Clipped Surrogate Objective(裁剪代理目标)

$$ L^{CLIP}(\theta) = \mathbb{E}_t \Big[ \min \big( r_t(\theta) A_t, \ \text{clip}(r_t(\theta), 1-\epsilon, 1+\epsilon) A_t \big) \Big] $$

解释:

  • 第一项:和普通策略梯度类似,鼓励动作优势大时增加概率。
  • 第二项:限制更新幅度,如果 $r_t(\theta)$ 偏离 $[1-\epsilon, 1+\epsilon]$ 太远,就把它裁剪回去,避免更新过大。
  • 最终取 min,即“宁可保守更新,也不要过大更新”。

这样就实现了类似 TRPO 的“信任域”效果,但更简单。


4. PPO 的训练步骤

  1. 采样数据:用旧策略 $\pi_{\theta_{\text{old}}}$ 跑一批轨迹,收集 $(s_t, a_t, r_t)$。

  2. 估计优势函数: 常用 GAE(Generalized Advantage Estimation),平衡偏差和方差:

    $$ A_t = \sum_{l=0}^\infty (\gamma \lambda)^l \delta_{t+l}, \quad \delta_t = r_t + \gamma V(s_{t+1}) - V(s_t) $$

  3. 优化目标:最大化 $L^{CLIP}(\theta)$,同时加上 值函数误差熵正则项

    $$ L(\theta) = L^{CLIP}(\theta) - c_1 (V_\theta(s_t) - R_t)^2 + c_2 H(\pi_\theta(\cdot|s_t)) $$

    • 第二项保证价值估计准确
    • 第三项增加探索性(熵项)
  4. 多次迭代更新:在同一批数据上反复优化几步,然后更新旧策略参数 $\theta_{\text{old}} \leftarrow \theta$。


5. PPO 的优点

✅ 实现简单(相比 TRPO 不需要二阶优化) ✅ 稳定收敛(限制策略更新幅度) ✅ 泛化性强(适用于离散动作和连续动作空间) ✅ 在 Atari 游戏、MuJoCo 控制任务上表现优秀(OpenAI 主推算法之一)


6. PPO 在代码里的实现框架(简化版)

for iteration in range(N):
    # 1. 用旧策略收集一批数据
    states, actions, rewards, dones, log_probs = collect_trajectories(policy_old)
    
    # 2. 计算优势函数 A_t
    advantages = compute_gae(rewards, values, dones)
    
    # 3. 更新策略
    for _ in range(K_epochs):
        r_t = exp(new_log_prob - old_log_prob)   # 概率比
        surr1 = r_t * advantages
        surr2 = torch.clamp(r_t, 1-ε, 1+ε) * advantages
        loss = -torch.min(surr1, surr2).mean() + value_loss + entropy_loss
        
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
    
    # 4. 更新旧策略
    policy_old.load_state_dict(policy.state_dict())

7. 总结

PPO 的关键点是:

  • 目标函数引入裁剪,避免策略更新过大
  • 保守更新,提升稳定性
  • 结合值函数和熵正则,平衡学习和探索

因此 PPO 成为了当前最常用、最实用的强化学习算法之一。