2. PPO的广义优势估计(GAE)实现

任务目标

在连续控制任务中,实现PPO算法中的广义优势估计(GAE),并通过调整λ参数观察其对训练稳定性与收敛速度的影响。本案例聚焦GAE核心逻辑,不涉及完整PPO策略更新。

环境依赖

需要 numpy(数组计算)与 gymnasium(连续控制环境)。安装命令:

pip install numpy gymnasium

GAE核心实现

GAE通过指数加权平均多个TD残差来平衡偏差与方差。当λ=0时退化为一步TD误差,λ→1时接近蒙特卡洛回报。以下代码实现GAE计算,并在Pendulum-v1环境中模拟一次轨迹,展示不同λ下的优势估计差异。

import numpy as np
import gymnasium as gym

def compute_gae(rewards, values, dones, gamma=0.99, lam=0.95):
    """
    计算广义优势估计(GAE)
    rewards: 奖励序列, shape [T]
    values: 价值函数预测, shape [T+1] (含最后一个状态的value)
    dones: 终止标志, shape [T]
    gamma: 折扣因子
    lam: GAE平滑参数
    返回: advantages shape [T], returns shape [T]
    """
    T = len(rewards)
    advantages = np.zeros(T)
    gae = 0.0
    for t in reversed(range(T)):
        # 若t+1是终止状态,则下一个value为0
        next_value = values[t+1] * (1 - dones[t])
        delta = rewards[t] + gamma * next_value - values[t]
        gae = delta + gamma * lam * (1 - dones[t]) * gae
        advantages[t] = gae
    returns = advantages + values[:T]
    return advantages, returns

# 在Pendulum-v1中采样一条轨迹并计算GAE
env = gym.make("Pendulum-v1")
obs, _ = env.reset(seed=42)
gamma, lam = 0.99, 0.95
rewards, values, dones = [], [], []
value_net = lambda o: 0.0  # 简化:假设价值函数恒为0

for _ in range(200):
    action = env.action_space.sample()  # 随机策略采样
    next_obs, reward, terminated, truncated, _ = env.step(action)
    done = terminated or truncated
    rewards.append(reward)
    values.append(value_net(obs))
    dones.append(done)
    obs = next_obs
    if done:
        break
values.append(value_net(obs))  # 追加最后一个状态的value

adv_low, _ = compute_gae(np.array(rewards), np.array(values), np.array(dones), gamma, 0.0)
adv_high, _ = compute_gae(np.array(rewards), np.array(values), np.array(dones), gamma, 0.99)

print(f"轨迹长度: {len(rewards)}")
print(f"λ=0.0 优势均值: {adv_low.mean():.4f}, 标准差: {adv_low.std():.4f}")
print(f"λ=0.99 优势均值: {adv_high.mean():.4f}, 标准差: {adv_high.std():.4f}")
env.close()

运行与验证

直接执行上述脚本。预期输出显示:λ=0.99的优势估计标准差显著大于λ=0.0(因方差更高),但均值接近。若需观察训练稳定性差异,可将GAE接入PPO更新循环,对比不同λ下策略熵或奖励曲线的波动幅度——λ较小时训练更稳定但收敛慢,λ接近1时收敛快但波动大。

判定标准

  • 代码能无错运行并输出两条轨迹的统计量
  • λ=0.99的标准差大于λ=0.0的标准差(因高λ保留更多长期信息,方差增大)
  • 修改λ值后重新运行,优势估计随之变化,说明GAE参数生效

常见问题

  • dones处理:终止状态后的value应置0,否则优势估计会错误引入未来奖励
  • values长度:需比rewards多一个元素(最后一个状态的value),否则索引越界
  • λ调参:连续控制任务通常取0.9~0.99,λ过小导致偏差大,过大则方差高