策略梯度定理提供了一种计算期望回报关于策略参数 $\theta$ 梯度的方法。为了应用这一理论,需要一个实用的算法来估计和运用这个梯度。REINFORCE 算法,也叫蒙特卡洛策略梯度,正好提供了这样的方法。它直接从完整的经验片段(回合)中学习,这些片段通过当前策略 $\pi_\theta$ 采样得到。其主要思想很简洁:我们希望调整策略参数 $\theta$,使得导致更高整体回报的动作更有可能发生,而导致较低回报的动作则较少发生。REINFORCE 通过采样轨迹,并使用这些轨迹中实际获得的回报来引导参数更新,从而达成这一目标。回顾策略梯度定理: $$ \nabla_\theta J(\theta) = \mathbb{E}{\tau \sim \pi\theta} \left[ \sum_{t=0}^{T-1} \nabla_\theta \log \pi_\theta(a_t | s_t) G_t \right] $$ 这里,$J(\theta)$ 是期望的总回报,$\tau$ 表示一个根据策略 $\pi_\theta$ 采样的轨迹(片段),$G_t$ 是从时间步 $t$ 开始的总折扣回报,而 $\nabla_\theta \log \pi_\theta(a_t | s_t)$ 是在状态 $s_t$ 下采取动作 $a_t$ 的对数概率的梯度。这个项,通常称为“得分函数”,指明了参数空间中增加在状态 $s_t$ 下采取动作 $a_t$ 的概率的方向。由于我们通常无法直接计算期望 $\mathbb{E}{\tau \sim \pi\theta}[\cdot]$(因为这需要对所有可能的轨迹进行积分),REINFORCE 使用蒙特卡洛估计。我们运行当前策略 $\pi_\theta$ 来生成一个或多个完整的片段。对于每个片段,我们计算每个时间步 $t$ 的回报 $G_t$。然后,我们使用采样数据来近似梯度。REINFORCE 算法该算法步骤如下:初始化: 随机初始化策略参数 $\theta$。循环(针对每个片段): a. 生成轨迹: 在环境中运行策略 $\pi_\theta$ 以收集一个完整的片段:$\tau = (s_0, a_0, r_1, s_1, a_1, r_2, ..., s_{T-1}, a_{T-1}, r_T)$。这里,$T$ 是该片段的终止时间步。 b. 循环(针对每个时间步 $t$ 从 $0$ 到 $T-1$): i. 计算回报: 计算从时间步 $t$ 开始的回报:$G_t = \sum_{k=t+1}^{T} \gamma^{k-t-1} r_k$。请注意,$G_t$ 是在此特定轨迹中,在状态 $s_t$ 和动作 $a_t$ 之后观察到的实际折扣回报。 ii. 计算更新项: 确定此步骤的更新方向:$\nabla_\theta \log \pi_\theta(a_t | s_t) G_t$。 c. 更新参数: 使用从该片段累积的梯度来更新策略参数,通常采用随机梯度上升法: $$ \theta \leftarrow \theta + \alpha \sum_{t=0}^{T-1} \nabla_\theta \log \pi_\theta(a_t | s_t) G_t $$ $\alpha$ 为学习率。更新也可以在每一步之后或在一批片段之后进行。理解更新过程我们来分析一下更新步骤 $\theta \leftarrow \theta + \alpha \nabla_\theta \log \pi_\theta(a_t | s_t) G_t$。$\nabla_\theta \log \pi_\theta(a_t | s_t)$(得分函数): 这个向量指向参数空间($\theta$)中,能最大程度增加在采样片段中于状态 $s_t$ 实际采取的动作 $a_t$ 的对数概率的方向。$G_t$(回报): 这个标量值表示在状态-动作对 $(s_t, a_t)$ 之后轨迹的好坏。它作为得分函数的一个加权因子。如果 $G_t$ 较大且为正值,则更新会将 $\theta$ 大幅推向使动作 $a_t$ 在状态 $s_t$ 中更可能发生的那个方向。算法“强化”了此动作,因为它带来了好的结果。如果 $G_t$ 较大且为负值(或小且为正值),更新仍将 $\theta$ 推向得分函数所指示的方向,但幅度会减小,或者如果 $G_t$ 为负,甚至可能将其推离该方向。算法会弱化或甚至抑制此动作,因为它带来了不好的结果。本质上,REINFORCE 将动作概率的最大上升方向($\nabla_\theta \log \pi_\theta$)与该动作之后的回报 ($G_t$) 关联起来。与较高回报相关的动作会得到更强的“提升”。以下图表概述了基于采样片段的单个 REINFORCE 更新步骤中的信息流动。digraph REINFORCE_Update { rankdir=LR; node [shape=box, style=rounded, fontname="sans-serif", color="#495057", fontcolor="#495057"]; edge [fontname="sans-serif", color="#495057", fontcolor="#495057"]; subgraph cluster_episode { label = "片段生成(使用当前策略 πθ)"; bgcolor="#e9ecef"; color="#adb5bd"; style="filled,rounded"; traj [label="采样轨迹\nτ = (s0, a0, r1, ... sT-1, aT-1, rT)", shape=note, fillcolor="#a5d8ff", style=filled]; } subgraph cluster_calc { label = "每步 t 的计算"; bgcolor="#e9ecef"; color="#adb5bd"; style="filled,rounded"; Gt [label="计算回报 Gt\nGt = Σ γ^(k-t-1) rk", fillcolor="#b2f2bb", style=filled]; Score [label="计算得分函数\n∇θ log πθ(at|st)", fillcolor="#ffec99", style=filled]; } Update [label="更新策略参数 θ\nθ ← θ + α * Gt * ∇θ log πθ(at|st)", shape=Mdiamond, fillcolor="#ffc9c9", style=filled]; traj -> Gt [label=" 回报 (r) "]; traj -> Score [label=" 状态 (s), 动作 (a) "]; Gt -> Update [label=" 回报 (Gt) "]; Score -> Update [label=" 得分函数 "]; }流程图说明了如何使用采样轨迹中的信息来计算回报和得分函数,然后将它们结合起来更新 REINFORCE 中的策略参数。优点与缺点REINFORCE 具有以下几个优点:简洁性: 主要思想和更新规则相对直接。直接优化: 它直接针对目标函数(期望回报)优化策略。适应性强: 它能自然地适应离散和连续动作空间(通过参数化适当的概率分布)。它还可以学习最优的随机策略。然而,它也有明显的缺点:高方差: 基于单个轨迹的蒙特卡洛回报 $G_t$ 估计可能非常嘈杂。即使策略略有变化,不同的片段也可能导致回报差异很大,从而导致梯度估计 $\nabla_\theta J(\theta)$ 具有高方差。这种高方差使得学习不稳定且缓慢。样本效率低: 由于梯度估计嘈杂,它通常需要许多片段才能收敛。需要完整片段: 更新仅在片段结束后执行,这对于非常长或不终止的任务来说可能存在问题。高方差是基本 REINFORCE 算法最紧迫的问题。在下一节中,我们将讨论如何引入基线来大幅缓解这个问题,从而实现更快、更稳定的学习。实现时的考量在实现 REINFORCE 时,特别是使用神经网络时:策略表示: 策略 $\pi_\theta(a|s)$ 通常由一个以状态 $s$ 作为输入的神经网络表示。对于离散动作,网络通常输出每个动作的概率(例如,使用 softmax 输出层)。然后 $\log \pi_\theta(a_t | s_t)$ 就是对应于所采取动作 $a_t$ 的输出概率的对数。对于连续动作,网络可能会输出概率分布的参数(例如,高斯分布的均值 $\mu$ 和标准差 $\sigma$)。动作 $a_t$ 从 $\mathcal{N}(\mu(s_t; \theta), \sigma(s_t; \theta))$ 中采样得到,而 $\log \pi_\theta(a_t | s_t)$ 是所选动作在该分布下的对数概率密度函数(PDF)。梯度计算: 深度学习库(如 TensorFlow 或 PyTorch)通过自动微分处理 $\nabla_\theta \log \pi_\theta(a_t | s_t)$ 的计算。您通常会定义一个损失函数,其梯度与策略梯度更新项相匹配。一种常见方法是使用一个替代损失,如 $- \log \pi_\theta(a_t | s_t) G_t$。使用梯度下降最小化此损失等同于使用项 $\nabla_\theta \log \pi_\theta(a_t | s_t) G_t$ 对目标 $J(\theta)$ 进行梯度上升。请记住,在计算步骤 $t$ 的更新梯度时,$G_t$ 被视为一个常数因子。