强化学习入门:使用近端策略优化(PPO)求解倒立摆问题
摘要
本文旨在从理论层面深入探讨强化学习(Reinforcement Learning, RL)的运作机制。我们以经典的**倒立摆(CartPole-v1)**环境为例,首先将其形式化为马尔可夫决策过程(Markov Decision Process, MDP),然后详细阐述策略梯度(Policy Gradient)方法的基础,并最终推导出现今最稳定和常用的算法之一——近端策略优化(Proximal Policy Optimization, PPO)。每一部分理论都将与Python(PyTorch)代码实现紧密结合,展示理论公式在实践中的落地。
1. 形式化框架:马尔可夫决策过程 (MDP)
强化学习的数学基础是马尔可夫决策过程。一个MDP由五元组 $(\mathcal{S}, \mathcal{A}, P, R, \gamma)$ 定义:
- 状态空间 $\mathcal{S}$ (State Space):环境所有可能状态的集合。在CartPole中,一个状态 $s \in \mathcal{S}$ 是一个四维向量:
[s_小车位置, s_小车速度, s_杆子角度, s_杆尖速度]对应 env.observation_space。
- 动作空间 $\mathcal{A}$ (Action Space):智能体可以执行的动作集合。在CartPole中,动作是离散的:
[0 (向左推), 1 (向右推)]对应 env.action_space。
转移概率 $P(s’ | s, a)$:在状态 $s$ 执行动作 $a$ 后转移到状态 $s’$ 的概率。无模型强化学习中,这通常未知,通过与环境交互采样得到。
奖励函数 $R(s, a, s’)$:在状态 $s$ 执行动作 $a$ 转移到 $s’$ 后获得的即时奖励。在CartPole中,杆子未倒每步奖励 +1。
折扣因子 $\gamma \in [0,1]$:权衡即时奖励与未来奖励的重要性,对应代码超参数
gamma。
1.1 策略与目标
智能体的行为由策略 $\pi$ 定义,即从状态到动作的映射。在深度强化学习中,使用参数 $\theta$ 的神经网络表示策略:
$$ \pi_\theta(a|s) = \text{Pr}(a_t = a \mid s_t = s, \theta) $$
强化学习的目标是找到最优策略 $\pi^*$,最大化从初始状态开始的期望累计折扣奖励:
$$ J(\theta) = \mathbb{E}_{\tau \sim \pi_\theta} \Big[ G_0 \Big] = \mathbb{E}_{\tau \sim \pi_\theta} \Big[ \sum_{t=0}^{T} \gamma^t R(s_t, a_t, s_{t+1}) \Big] $$
其中 $\tau = (s_0, a_0, r_1, s_1, …)$ 是一条轨迹,$G_0$ 是初始回报。
代码对应:
self.actor_head = nn.Linear(64, action_dim)
action_probs = torch.softmax(self.actor_head(x), dim=-1) # π_θ(a|s)2. 策略梯度方法 (Policy Gradient Methods)
策略梯度方法直接对参数 $\theta$ 进行梯度上升优化策略。根据策略梯度定理:
$$ \nabla_\theta J(\theta) = \mathbb{E}_{\tau \sim \pi_\theta} \Big[ \sum_{t=0}^{T} \nabla_\theta \log \pi_\theta(a_t|s_t) \cdot G_t \Big] $$
其中
$$ G_t = \sum_{k=t}^{T} \gamma^{k-t} r_{k+1} $$
是从时间步 $t$ 开始的累计折扣回报。
- $\nabla_\theta \log \pi_\theta(a_t|s_t)$:得分函数,指示参数 $\theta$ 应如何调整,使动作 $a_t$ 的概率上升。
- $G_t$:权重,回报越高梯度更新幅度越大。
代码对应:
log_prob = dist.log_prob(action)
loss = -log_prob * G_t
loss.backward()2.1 基线与优势函数
为减小方差,引入基线 $b(s_t)$,通常取状态值函数 $V^\pi(s_t)$。优势函数定义为:
$$ A^\pi(s_t, a_t) = Q^\pi(s_t, a_t) - V^\pi(s_t) $$
代码对应:
advantages = rewards - state_values.detach() # A(s_t, a_t)3. 近端策略优化 (PPO) 算法
普通策略梯度对学习率敏感,容易破坏策略。PPO通过裁剪目标函数实现稳定更新。
定义概率比:
$$ r_t(\theta) = \frac{\pi_\theta(a_t|s_t)}{\pi_{\theta_{\text{old}}}(a_t|s_t)} $$
代码对应:
ratios = torch.exp(logprobs - old_logprobs.detach()) # r_t(θ)3.1 裁剪目标函数
$$ L^{CLIP}(\theta) = \mathbb{E}_t \Big[ \min\big( r_t(\theta) \hat{A}_t, \text{clip}(r_t(\theta), 1-\epsilon, 1+\epsilon) \hat{A}_t \big) \Big] $$
- $\hat{A}_t$:优势函数
- $\epsilon$:裁剪范围(如 0.2)
代码对应:
surr1 = ratios * advantages
surr2 = torch.clamp(ratios, 1-self.eps_clip, 1+self.eps_clip) * advantages
policy_loss = -torch.min(surr1, surr2).mean()3.2 完整损失函数
PPO最终目标函数结合策略损失、价值函数损失和熵奖励:
$$ L_t(\theta) = L_t^{CLIP}(\theta) + c_1 (V_\theta(s_t) - G_t)^2 - c_2 S[\pi_{\theta}](s_t) $$
- $V_\theta(s_t)$:Critic预测值
- $G_t$:实际回报
- $S[\pi_\theta](s_t)$:策略熵,用于鼓励探索
代码对应:
value_loss = 0.5 * self.MseLoss(state_values, rewards)
entropy_bonus = -0.01 * dist_entropy
loss = policy_loss + value_loss + entropy_bonus
loss.backward()
self.optimizer.step()4. 结论
本文从马尔可夫决策过程出发,推导了策略梯度方法,最终构建PPO算法。每个理论组件——策略 $\pi_\theta(a|s)$、值函数 $V(s)$、优势函数 $A(s,a)$、PPO裁剪目标——都与PyTorch代码实现一一对应。
这种“从理论到代码”的结合揭示了强化学习本质:通过与环境交互和梯度优化,智能体逐步掌握解决复杂任务的能力。