策略梯度(Policy Gradient):直接优化策略的强化学习方法 —— 用 “修课心情” 理解核心逻辑

策略梯度(Policy Gradient, PG)是强化学习中 “直接优化策略” 的核心算法 —— 它不通过 Q 表间接学习,而是直接调整策略参数,让智能体更倾向于选择能带来高回报的动作。这种思路就像 “修课选方向”:不纠结于 “每门课好不好”(类似 Q 值),而是直接调整 “选课策略”(类似 RL 的策略),最终让总 GPA(类似累积回报)最高,直观又高效。

本文将用 “修课心情” 的通俗类比拆解 PG 的核心原理,对比 Q-Learning 的差异,再通过完整实操代码落地,帮你快速掌握这种 “直接优化” 的强化学习思路。

一、PG 的核心定位:为什么需要 “直接优化策略”?

之前学的 Q-Learning(价值型 RL)通过学习 “状态 - 动作价值(Q 值)” 间接推导最优策略,但存在两个明显局限:

  1. 仅适用于离散动作空间(如上下左右),无法处理连续动作(如机器人关节角度、自动驾驶车速);
  2. Q 值估计易受噪声影响,当状态 / 动作空间复杂时,Q 表或 Q 网络难以准确拟合。

而 PG(策略型 RL)的核心突破是 “直接优化策略”:

  • 策略本身是可参数化的模型(如神经网络),输入状态,输出动作或动作概率;
  • 通过 “梯度上升” 最大化累积回报,直接调整策略参数,无需中间 Q 值估计;
  • 天然支持连续动作空间,对复杂场景适应性更强。

通俗类比(修课心情)

  • Q-Learning:先打听每门课的 “预期分数”(Q 值),再选分数最高的课;
  • PG:不打听单门课分数,直接根据 “过去选课的总 GPA”(累积回报)调整选课偏好,比如 “之前选 AI 类课总拿高分,以后多选这类课”。

二、PG 的核心原理:用 “梯度上升” 让好动作更易被选中

PG 的核心逻辑只有一句话:计算策略的梯度,沿着梯度方向更新参数,让 “能带来高累积回报的动作” 被选中的概率越来越高。就像修课中,若选 “AI 课” 的总回报(分数)高,就调整选课策略,下次更倾向于选 AI 课。

1. 通俗理解:“加权更新”—— 好动作多选,坏动作少选

PG 的优化本质是 “加权调整动作概率”:

  • 若某个动作 A 在状态 S 下带来的累积回报 G 很高(好动作),就增大 “状态 S 下选 A” 的概率;
  • 若累积回报 G 很低(坏动作),就减小该动作的概率;
  • 权重就是累积回报 G,回报越高,调整幅度越大。

2. “修课心情” 深度类比

RL 组件 修课场景类比 核心逻辑
策略 π(参数 θ) 选课偏好(如 “倾向选 AI 课”) 状态(学期需求)→ 动作(选课)的概率分布
动作 A 选某一门课(如《机器学习》) 策略输出的可选选项
累积回报 G 该门课的 “最终总收益”(分数 + 技能提升) 动作带来的长期价值
梯度上升 调整选课偏好 让 “总收益高的课” 下次更易被选中
基线(Baseline) 平均 GPA 避免个别极端分数影响,让调整更稳定

比如:若选《机器学习》的总回报(90 分 + 技能提升)远高于平均 GPA(基线),就大幅提升下次选 AI 类课的概率;若选《量子力学》的回报(60 分 + 难度大)低于基线,就降低选这类课的概率。

3. 核心数学原理(简化版)

无需复杂推导,记住两个关键公式即可:

  • 目标函数:最大化所有轨迹(状态 - 动作 - 回报序列)的累积回报期望J(θ)=Eτ∼πθ​​[G(τ)]其中τ是一条轨迹(如 “选课→上课→得分” 的完整流程),G(τ)是这条轨迹的累积回报。

  • 梯度更新公式:沿着梯度方向调整参数 θ(梯度上升,因为要最大化目标函数)∇θ​J(θ)≈N1​∑i=1N​∑t=0T−1​∇θ​logπθ​(Ai,t​∣Si,t​)⋅(Gi,t​−b)关键部分解释:

    1. logπθ​(A∣S):动作 A 在状态 S 下的对数概率,梯度越大,调整空间越大;
    2. (G−b):加权系数(b 是基线,如平均累积回报),正数表示 “好动作”,负数表示 “坏动作”;
    3. 核心逻辑:用(G−b)加权更新,好动作的概率被放大,坏动作被缩小。

三、PG 与 Q-Learning 的核心区别:一张表看懂

对比维度 策略梯度(PG) Q-Learning(价值型)
优化对象 直接优化策略 π(参数化模型) 间接优化(通过 Q 值推导策略)
动作空间 支持离散 + 连续动作 仅支持离散动作(需离散化连续动作)
稳定性 方差大(需基线优化) 方差小,但易受 Q 值估计偏差影响
适用场景 复杂状态 / 动作空间、连续控制 简单离散场景(如迷宫、小游戏)
核心优势 无需 Q 值估计,直接高效 实现简单,适合入门

四、实操:用 Policy Gradient 玩转 CartPole(PyTorch 实现)

我们继续用 CartPole 环境(小车平衡杆)实现 PG,对比之前的 Q-Learning,感受 “直接优化策略” 的优势。

1. 环境说明(同之前 Q-Learning)

  • 状态 S:4 维连续向量(小车位置、速度、杆角度、角速度);
  • 动作 A:2 种离散动作(0 = 左移,1 = 右移);
  • 回报 R:每保持平衡 1 步 + 1 分,杆倒下游戏结束。

2. 完整代码(分步骤解释)

python

运行

# 安装依赖
# pip install gym numpy torch

import gym
import numpy as np
import torch
import torch.nn as nn
import torch.optim as optim

# ---------------------- 1. 定义策略网络(直接优化的“策略模型”) ----------------------
class PolicyNetwork(nn.Module):
    def __init__(self, state_dim=4, action_dim=2):
        super().__init__()
        # 简单神经网络:输入状态(4维)→ 输出动作概率(2维)
        self.network = nn.Sequential(
            nn.Linear(state_dim, 32),
            nn.ReLU(),
            nn.Linear(32, 16),
            nn.ReLU(),
            nn.Linear(16, action_dim),
            nn.Softmax(dim=-1)  # 输出动作概率分布(和为1)
        )

    def forward(self, x):
        return self.network(x)  # 输入状态,输出动作概率

    def select_action(self, state):
        # 输入状态→生成动作概率→随机采样动作(体现随机性策略)
        state_tensor = torch.tensor(state, dtype=torch.float32).unsqueeze(0)
        action_probs = self.forward(state_tensor)
        action_dist = torch.distributions.Categorical(action_probs)  # 分类分布
        action = action_dist.sample()  # 随机采样动作
        return action.item(), action_dist.log_prob(action)  # 返回动作和对数概率

# ---------------------- 2. 计算累积回报(带折扣+基线) ----------------------
def compute_discounted_returns(rewards, gamma=0.99, baseline=True):
    """
    计算每条轨迹的折扣累积回报,并可选减去基线(减少方差)
    """
    discounted_returns = []
    running_add = 0
    # 反向计算折扣回报(从最后一步往回算)
    for r in reversed(rewards):
        running_add = r + gamma * running_add
        discounted_returns.insert(0, running_add)
    
    # 减去基线(所有轨迹的平均回报),减少更新方差
    if baseline:
        baseline_val = np.mean(discounted_returns)
        discounted_returns = [r - baseline_val for r in discounted_returns]
    
    # 标准化回报(进一步稳定训练)
    discounted_returns = torch.tensor(discounted_returns, dtype=torch.float32)
    discounted_returns = (discounted_returns - discounted_returns.mean()) / (discounted_returns.std() + 1e-8)
    return discounted_returns

# ---------------------- 3. 训练策略网络(梯度上升最大化回报) ----------------------
def train_policy_gradient(episodes=1000, gamma=0.99, lr=1e-3):
    env = gym.make("CartPole-v1")
    state_dim = env.observation_space.shape[0]
    action_dim = env.action_space.n

    # 初始化策略网络、优化器(Adam)
    policy_net = PolicyNetwork(state_dim, action_dim)
    optimizer = optim.Adam(policy_net.parameters(), lr=lr)

    for episode in range(episodes):
        # 存储单条轨迹的:对数概率、即时回报
        log_probs = []
        rewards = []
        state = env.reset()
        done = False

        # 生成一条轨迹(玩一局游戏)
        while not done:
            # 选动作(策略网络输出概率→采样)
            action, log_prob = policy_net.select_action(state)
            # 执行动作,获取环境反馈
            next_state, reward, done, _ = env.step(action)
            
            # 记录对数概率和回报
            log_probs.append(log_prob)
            rewards.append(reward)
            
            state = next_state

        # 计算累积回报(带基线和标准化)
        discounted_returns = compute_discounted_returns(rewards, gamma)
        
        # 计算损失(目标是最大化回报→等价于最小化负的“对数概率×回报”)
        loss = 0
        for log_prob, ret in zip(log_probs, discounted_returns):
            loss -= log_prob * ret  # 负号:梯度上升→转为梯度下降优化
        loss = loss / len(log_probs)  # 平均损失,稳定训练

        # 梯度更新(标准反向传播)
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

        # 打印训练进度
        total_reward = sum(rewards)
        if (episode + 1) % 100 == 0:
            print(f"第{episode+1}轮 | 总回报:{total_reward:.0f} | 平均损失:{loss.item():.4f}")

    # 测试训练效果(可视化)
    test_env = gym.make("CartPole-v1", render_mode="human")
    state = test_env.reset()
    done = False
    while not done:
        action, _ = policy_net.select_action(state)
        state, _, done, _ = test_env.step(action)
        test_env.render()
    test_env.close()

    return policy_net

# 启动训练
if __name__ == "__main__":
    trained_policy = train_policy_gradient(episodes=1000)

3. 代码核心逻辑(对应 PG 原理)

  • 策略网络:直接输出动作概率,用 Categorical 分布采样动作(体现随机性策略);
  • 累积回报:带基线和标准化,减少训练方差,让模型更稳定;
  • 损失计算:负的 “对数概率 × 回报”,通过梯度下降间接实现梯度上升(最大化回报);
  • 梯度更新:每局游戏结束后(一条轨迹)更新一次参数,批量更新更稳定。

4. 预期效果

  • 训练 1000 轮后,平均总回报≥200(杆能长时间保持平衡);
  • 对比 Q-Learning:PG 训练速度更快,对连续状态空间的适配性更好。

五、PG 的关键优化技巧:让训练更稳定高效

1. 基线(Baseline):减少方差

  • 核心作用:避免个别高回报轨迹导致参数更新波动过大;
  • 实现:用所有轨迹的平均累积回报作为基线,将(G−b)作为加权系数,让好动作的判断更客观。

2. 折扣回报与标准化

  • 折扣回报:用γ(0.9-0.99)加权未来回报,让智能体 “有远见”;
  • 回报标准化:将累积回报归一化(均值 0,方差 1),避免不同轨迹的回报尺度差异导致更新失衡。

3. 策略随机性

  • PG 的策略是随机性的(输出动作概率分布),天然具备 “探索能力”,无需像 Q-Learning 那样设计ϵ-greedy;
  • 训练后期,策略会逐渐收敛到 “近似确定性”(最优动作的概率趋近于 1)。

4. 学习率调整

  • 初始学习率建议 1e-3~1e-4,过大易震荡,过小训练过慢;
  • 可使用学习率调度器(如 ReduceLROnPlateau),根据训练效果动态调整。

六、总结:PG 的核心要点与学习建议

  1. 核心逻辑:直接优化策略,通过梯度上升最大化累积回报,好动作多选、坏动作少选,无需 Q 值估计;
  2. 通俗记忆:修课选方向→根据总 GPA 调整选课策略,让高分课的选择概率越来越高;
  3. 适用场景:连续动作空间、复杂状态 / 动作场景(如机器人控制、自动驾驶);
  4. 学习顺序:
    • 入门:用 CartPole 跑通 PG 代码,理解 “直接优化策略” 的流程;
    • 进阶:学习 PG 的变体(如 A2C、PPO),解决 PG 方差大的问题;
    • 实操:尝试连续动作环境(如 Pendulum),感受 PG 的天然优势。

PG 是强化学习从 “离散动作” 走向 “连续动作” 的关键算法,掌握它后,你能应对更多实际场景(如机器人关节控制、无人机路径规划),也是后续学习高级 RL 算法(如 PPO、SAC)的基础。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐