PPO流程的个人疑问集锦 Q & A

文中大部分为GPT生成,并由我个人理解后添加了注解。

PPO流程的个人疑问集锦 Q & A_第1张图片

PPO流程的个人疑问集锦 Q & A_第2张图片

1. PPO Loss 和 Actor Loss 是一个东西吗?

PPO流程的个人疑问集锦 Q & A_第3张图片

个人理解:

上图中:

  • PPO-clip Loss指的是用了clip的Actor loss(含kl散度罚项),用来鼓励actor模型在不过度偏离ref模型以及old actor模型的前提下,对齐人类偏好;
  • LM Loss指的是(交叉)熵损失函数,用来促进actor生成更多样的输出;
  • MSE Loss指的是critic loss,用来促进critic的价值打分value更接近真实收益return(在不过度偏离old critic的前提下)。

但是实际上,一般:

  • 我们用actor loss(已包含kl散度罚项)、critic loss、LM loss指代这三种loss

  • 而ppo loss则是将这三个loss用超参数耦合起来

    类似:

    PPO流程的个人疑问集锦 Q & A_第4张图片

下面仅给出一般情况下的理解

一般来说:

Actor Loss

  • 是指 策略网络(Actor) 的损失。
  • 它的目标是:更新策略,使其获得更高的预期回报(expected return)。

PPO Loss

  • 是Proximal Policy Optimization(PPO)算法设计的整体损失函数。

  • 包括:

    • Actor Loss(策略损失)
    • Critic Loss(价值函数损失)
    • (可选)Entropy Bonus(鼓励探索的项)

PPO 中的 Actor Loss 具体形式:

PPO 的 Actor Loss 有一个特殊设计,叫做 Clipped Objective,如下:

L^{\text{CLIP}}(\theta) = \mathbb{E}_t \left[ \min \left( r_t(\theta) \hat{A}_t,\ \text{clip}(r_t(\theta), 1 - \epsilon, 1 + \epsilon)\hat{A}_t \right) \right]

其中:

  • :新旧策略的概率比。
  • :优势函数(Advantage)。
  • :裁剪参数,防止策略变化太大。

这个裁剪形式就是 PPO 特有的 Actor Loss。

总结关系如下表:

Actor Loss PPO Loss
指代 策略网络的损失 PPO算法的总损失
是否包含Critic ✅(通常包括 critic 和 entropy)
数学形式 常用 Clipped Objective 通常是:Actor Loss + Critic Loss + Entropy Bonus
是否特指 PPO ❌(其他算法也有) ✅(是PPO特有设计)

所以:

  • 在 PPO 中,Actor Loss 是 PPO Loss 的一部分;
  • 但在说 “Actor Loss” 时,我们通常只指“优化策略的那一部分”;
  • 而 “PPO Loss” 是整个训练目标,包括策略、价值、熵等多项指标的加权和。

2. ref模型接受的输入究竟是什么?

ppo中,actor基于prompt生成response,以及response所选出的各token id对应的概率,也就是logprobs,

我们将prompt + response拼成一个完整序列送给ref进行前向(注意ref模型只做一次前向,而不是生成!),

然后获取actor生成的response中的各token id所对应的ref给出的概率,作为ref_logprobs,

进而与logprobs做kl散度计算来约束actor的更新。

在 PPO 中,actor 的 response 会和 prompt 拼接成一个完整的序列,送入 reference model(也就是 pre‑trained LM 或 SFT model,简称 ref)进行一次前向传播,用来获取每个 token 的 log-probabilities。这些就是所谓的 ref_logprobs​。

流程总结:

  1. 拼接序列
    把 prompt(环境状态)和 actor 生成的 response(模型行为)拼接成一整段文本序列。

  2. 丢给 reference model 前向计算
    用这个完整序列在 ref 模型上前向计算,从而获得 response 部分每个 token 的概率(用 log-prob 表示)。

    注意!

    这里相当于用actor生成的response中的各token的token id,去索引ref做完前向之后对应位置上的token id所对应的概率!

  3. 记录 token log‑probabilities
    得到的 log-probabilities 就是 ref_logprobs​,对应 actor 输出的每个 token。

  4. 用于 KL 惩罚和计算 reward
    PPO 的 reward 包括两个部分:一是 reward model 打分,二是 KL penalty —— 即 actor logprobs 与 ref logprobs 差值,防止偏离太远。

问题回答:

  • ref接收的输入就是prompt + actor生成的response;
  • ref_logprobs 就是 actor的response中的每个 token 在 reference 模型(freeze 后)前向计算得到的 log-prob。
  • 这些值同时用于构造 KL penalty,也用在 PPO 的 reward 计算中。

3.PPO整个流程中,actor和critic以及old actor和old critic的更新顺序

个人理解:

在更小一层的PPO epochs循环中,我们更新了new Actor和new Critic,

然后当这个PPO epochs结束之后,我们立刻将new Actor的参数赋给了old Actor, 然后将new Critic的参数赋给了old Critic

(虽然实际上我们不会保存old actor和old critic的参数,因为太占空间了,事实上我们保存的是old模型的经验的快照,在ppo epochs中我们直接更新actor和critic!)

(此外critic其实没有新旧之说,我们仅保存大循环开始时critic对response的打分序列values,用这个values来clip后续critic的更新)

(具体见后续问题)

下面用清晰的步骤和小粒度对齐,说明 PPO 中 newActor​、newCritic​ 和 oldActor​(旧策略)之间的更新顺序与流程:

小循环 & 大循环中的更新逻辑:

  1. 大循环:多次 iterations(或 epochs)

    每个 iteration 包括采样、更新等完整步骤。

    (快照old模型)

  2. 小循环(单次 iteration 里的 PPO epochs)

    使用同一批体验数据,进行多轮梯度更新。

    (更新new模型,在ppo epochs全部跑完后将new模型赋给old模型)

每次 iteration 的完整流程细节:

  1. 采样阶段(Sampling)
    使用当前策略 actor θₖ​ 与环境交互,收集 trajectories,并记录动作 log prob。这 log prob 即代表 “旧策略” 在采样时做出的判断。

  2. 计算 Advantage & Return
    利用当前 critic φₖ​ (可以理解为old critic,实际上就是大循环开始时的critic模型)估计值value,以及reward的打分(含kl散度),

    结合奖励信号计算 TD‑error 或 GAE→得出 Aₜ, Rₜ。

  3. 快照旧策略
    将当前 actor θₖ​ 复制一份为 θ_old​,此时就固定为旧策略,用于后续多个 PPO epoch 中计算比值 rₜ(medium.com)。

  4. 训练小循环(多个 PPO epochs)
    对同一批数据,执行 K 个 epoch 的小批训练(batch):

    • Actor 更新(newActor θ):计算 clipped surrogate loss,用 θ_old​ 的 log‑prob 比较当前策略,进行梯度上升。

    • Critic 更新(newCritic φ):用均方误差最小化 V_φ(sₜ) 与 Return 的差距,同步调整参数。

    • 顺序:

      同一个 batch 上,多数实现是 先 actor,再 critic 或者 分开独立 optimize,

      但都是 多轮使用相同 θ_old 的旧策略。

  5. 结束本次 iteration
    当所有 epoch 完成:

    • ​newActor​ 参数成为下一次 sampling 用的 actor θₖ₊₁​;
    • ​newCritic​ 参数更新日常评估值函数;
    • ​θ_old​ 将在下次 iteration 的小循环中再次快照。

总结一句话:

  • 在一个 iteration 内:

    小循环中:不断更新 newActor 和 newCritic,但“旧策略 θ_old”保持不变;

    小循环结束时:整个 newActor(和 newCritic)替代旧参数,成为下一轮 iteration 的 actor 和 critic。

回答问题:

“也就是说在更小一层的循环中,我们更新了newActor和newCritic, 然后当这个PPO epochs结束之后,我们立刻将newActor赋给了oldActor, 然后将newCritic赋给了oldCritic, 是这样吗?”

完全正确:

  • 小循环(PPO epochs)中,oldActor​ 一直是之前快照的版本。
  • Epoch 结束后,newActor(更新完的 actor)就会替换 oldActor​ 为下一次 iteration 的快照。
  • Critic 没有“旧策略”之说,直接用 newCritic​ 更新。

4. old actor和old critic的权重需要保存吗?

个人理解:

实际上我们并没有保存Old Actor和Old Critic的权重,

而是我们将它们所生成的一些旧经验用快照冻结, 然后保存到了一个buffer里面,

然后我们在ppo Epochs里面持续更新原来的Actor和Critic。

许多 PPO 的实现并不保存完整的 oldActor​、oldCritic​ 网络参数,

而是通过 将旧策略生成的经验(如 log π_old​)冻结并缓存到 buffer,

在多个 epoch 内反复使用这些旧经验来训练,不断更新原来的 Actor 和 Critic。

下面详细说明这种关键机制。

PPO 中对“旧策略”处理的两种方式:

  1. 最直观的做法:保存完整网络快照

    • 在采样结束后,用 θ_old = θ_current​ 来保存旧策略参数。
    • 多 epoch 中,仍旧使用这个完整快照网络来重新计算旧策略 log‑prob。
    • 优点:回放使用的是实际的旧网络,确保一致性;
    • 缺点:存储网络快照复杂,计算开销更大。
  2. 常见高效实现:只缓存 旧策略的 log‑prob

    • 在采样时,actor 输出时同时保存这个动作在当时策略下的 log π_old​ 到 buffer。

    • 在多个 PPO epoch 中,无需再调用一个旧策略网络,

      只需 从 buffer 中读取旧的 log π_old​,

      并与当前策略生成的新 log π_new​ 作对比,计算比例:

      r _ t ​ =exp(log π _{ new} ​ (a _ t ​ ∣s _ t ​ )−log π _{ old} ​ )

    • 这就等效于“冻结旧策略”的效果,但效率更高。

      reddit 上也指出:

      “after collecting data using the old policy, we do k epochs update, so the policy in each epoch is the new policy compared to the old log probabilities saved in Replay Buffer”(reddit.com)

      即:用 buffer 冻结旧 log‑prob,更新时直接对比,不需要保存旧模型。

总结与对照表:

方法 是否存网络快照 使用旧策略方式 优点 缺点
快照网络 每 epoch 调用旧模型 精准、逻辑清晰 存储和计算量大
缓存 log‑prob buffer 里读取旧 log‑prob 高效、简洁,常用 不保留网络状态,只保留行为统计

回答问题:

“我们并没有保存 OldActor 和 OldCritic 的权重,而是将旧经验快照冻结到 buffer,然后持续更新 Actor 和 Critic是吗?”

完全正确,且是 PPO 常见且推荐的实现方式。


5. ref、old actor、old critic、reward(重要)、new actor、new critic获得的输入和输出

详细、清晰地给出ref、old actor、old critic、reward、new actor、new critic获得的输入和输出

(其中你需要明确给出reward的输出相当于给非结尾的token不附加reward模型打分,给response结尾附加reward模型打分,但是response每个token位置都有加入kl散度约束来作为该token的reward的一部分)

本问题的重点在于reward模型的输出究竟是一个序列还是一个标量)

个人理解:

reward模型接收prompt + response作为输入,

然后我们给response处的各token打分,

在这里我们要求reward模型给response非结尾处的token都打0分(无reward奖励),

只给response结尾处附上一个整体的reward打分。

实际上reward模型是可以做到逐token打分的,这里只是只取最后一个token生成的打分值(也就是对应整体的打分)而已!

这样,目前的rewards其实相当于一个[0, 0, ..., reward_score]​的序列。

然后我们为rewards加上actor和ref模型之间的kl散度,

这样就得到了我们最终期望的rewards序列(也就是获得了response中每个token对应的reward打分)。

这样的设计公式如下:

"select * from blocks where id='20250624002126-0jv0w6s'"

目的是:

  • 当 时,我们更加关心Actor是否有在Ref的约束下生产token
  • 当 时,我们不仅关心Actor是否遵从了Ref的约束,也关心真正的即时收益

具体详见:(3)重新设计 R_{t}

以下是基于标准 RLHF + PPO 实现(以 TRL PPOTrainer 为例)的详细流程图,说明每个模型:reference model(ref)、old actor、old critic、reward model、new actor、new critic 在训练中的输入与输出,以及如何将 KL 散度约束 与 reward 模型评分 融入 token‑级别的 reward:

一、 采集阶段(Rollout):

模块 输入 输出
old actor(即当前策略) Prompt(x) Response tokens y = (y₁…yᴺ),及其 log‑probs π_old(yₜ
reward model Prompt+Response 完整序列 (x,y) reward_score = r(x,y)(一个 scalar,仅在整个 response 结尾计算一次)
  • reward_score 只在 yᴺ(结尾 token)处被添加!!!
  • 之前的每个 token t < N 暂无 reward 模型直接评分!!!

二、风控与评价阶段(Ref 前向 & Critic):

  1. reference model(ref)

    • 输入:相同的 (x, y)
    • 输出:每个生成 token 的 log‑probs π_ref(yₜ|x, y_
    • 用于计算 KL penalty,防止策略偏离原始语言模型(newfacade.github.io, en.wikipedia.org)。
  2. old critic(value/value head)

    • 输入:prompt + response 序列(x, y)

    • 输出:每个 time‑step 的估值 V_old(x, y_

      此处下标小于t的解释详见:7. 为什么PPO 中,critic 的输入使用的是当前时刻之前的上下文 (x, y_{

三、构造 token‑级 rewards + advantage:(重要)

对每个 token t:

  • reward from reward model:

    • 如果 t = N(response 结尾),r_t = reward_score。
    • 否则,r_t = 0。
  • KL penalty(每个 token 都计算):

    • klₜ = log π_old(yₜ) − log π_ref(yₜ)

综合 token reward:

​​​​

随后使用 gamma 折扣累计至各步,得到 return-to-go R̂ₜ。

再计算优势:

Aₜ = R̂ₜ − V_old(x, y_

四、PPO 更新阶段:

在一个批次内,使用下面步骤更新 actor 和 critic:

  1. 新 actor(new policy π_new)

    • 输入:相同 prompt,生成整个 batch 的 y 并记录新 log‑probs π_new(yₜ)

    • 使用 PPO-clip 目标函数更新:

      其中 (en.wikipedia.org)。

  2. 新 critic(new value V_new)

    • 输入:prompt+response
    • 输出:预测 V_new(x, y_
    • 最小化目标:均方误差:

流程总结图:

prompt x
 ├─▶ old actor ─▶ response y, actor log‑probs

拼接完整序列 (x,y)
 ├─▶ reward model ─▶ reward_score at token N
 ├─▶ reference model ─▶ ref log‑probs for every token

每个 token 的生成上下文 (x,y_{

总结要点:

  • Reference model:只做一次前向,输出 ref log‑probs(不会生成文本)。
  • Reward model:只对整个 response 结尾打分。
  • KL constraint:对每个 token 施加 log‑prob 差值惩罚。
  • Critic:为每个 time‑step 提供 baseline 估值用于优势计算。
  • Actor 更新:结合 token‑级 KL 惩罚和结尾的 reward 模型评分,通过 PPO clip 优化策略。

6. 给出清晰明确分层的ppo流程

以下是一个层级清晰、结构明确的 RLHF + PPO 流程,帮助梳理每个阶段各模型的输入输出及它们之间的关系:

第 1 层:数据采集(Rollout)

目的:使用旧策略生成回应并打标签。

  • 输入:Prompt

  • 模型:旧 actor()

    • 功能:采样响应
    • 输出:sequence of tokens ,及对应 log-probs
  • 模型:奖励模型(Reward model)

    • 输入:拼接完整序列
    • 输出:一组标量 reward score ,仅在 结束时提供一次

第 2 层:评价与打分

目的:为每个 token 打分 —— 引入 KL 惩罚及计算 critic 的 baseline。

  • 模型:Reference model(冻结 LM)

    • 输入:完整序列
    • 输出:每个生成 token 的 log-probs
  • 模型:旧 critic(Value model)

    • 输入:每个 token 的生成上下文

      此处下标小于t的解释详见:7. 为什么PPO 中,critic 的输入使用的是当前时刻之前的上下文 (x, y_{

    • 输出:每个 time‑step 的状态价值估计


第 3 层:构造 Token‑级 Reward & Advantage

目的:根据模型输出构建 token‑级 reward,并计算 advantage。

  1. KL 惩罚(每个 token):

  2. Reward 分配:

    • 对所有 ,
    • 对结尾 token ,
  3. 累积折扣收益(Return-to-go):

  4. 优势估计(Aₜ):


第 4 层:PPO 更新(Actor 和 Critic)

目的:依据 PPO 的目标函数更新策略与价值网络。

  • 新 actor()

    • 输入:原 batch 的 prompt 序列

    • 输出:新 log-probs

    • 损失函数(PPO-Clip + KL penalty):

      L_{\text{actor}} = \mathbb{E}_t \left[ \min \Big( r_t A_t,\; \text{clip}(r_t,1-\epsilon,1+\epsilon) A_t \Big) \right] - \beta\,\mathbb{E}_t[\text{kl}_t]

      其中

  • 新 critic()

    • 输入:prompt + past tokens
    • 输出:每 step 的新值估计
    • 损失:

小结:

  • 层级划分:Rollout → 评价打分 → 构造 reward → PPO 更新;
  • Token 级 Reward:每个位置都有 KL 惩罚;结尾 token 额外加 reward model 评分;
  • Actor & Critic:并行训练,actor 用 PPO clip + KL penalty,critic 用 MSE fitting return。

7. 为什么PPO 中,critic 的输入使用的是当前时刻之前的上下文 (x, y_{

PPO流程的个人疑问集锦 Q & A_第5张图片

个人理解:

如图中所示也可以看出,其实左边的value模型接收的输入是t时刻的状态,但是实际上一共有1~T个时刻!

所以我们可以理解为,这样写是要求value模型必须是一个causal因果模型,

value只能依赖当前状态(prompt + 已生成的可见的前文)去给当前状态打分,而不能看到未来的信息!因为它的任务是预估未来的信息。

但是在实际操作中,我们已经获得了prompt + actor给出的完整response,

因此我们在操作上,就是将整个序列塞给value作为输入!

不过我们又做了一个causal mask + teacher forcing的事情来让value打分。

其中:

  • causal mask是指,对于T长度的response,我们逐token打分,且当前token只能看到之前的tokens
  • teacher forcing是指,对于T长度的response,我们的输出不会影响输入(也就是说不是自回归的),我们只是一个一个token去给response中的所有token位置(状态)打分!从而获得一个values序列。

在 PPO 中,critic 的输入使用的是当前时刻之前的上下文 (x, y_

为什么是 y_

  1. 模拟马尔可夫状态(Markov State)
    在 RL 中,每个 time-step 的状态表示环境当前状况,即当前所见的历史信息。在文本生成中,step 的状态是 prompt 和已经生成的 tokens ,即 (x, y_
  2. 时间一致性
    critic 的目标是预测从这个状态开始,到未来所有奖励的期望值 。如果 critic 知道了后续 token(甚至结尾 token),它就“偷看未来”了,估值会过高,违反 causal consistency。
  3. 符合 Advantage/Gare 等估计机制
    critic 项用来计算优势 。这里的 应严格基于 当前时刻可见的上下文,这样 才是合理的差值(ar5iv.labs.arxiv.org)。

总结:

  • 状态设计:每个 token 对应一个状态,stateₜ = (prompt, 已生成 tokens)
  • critic 输入:
  • critic 图片:是未来回报的估计,不包含未来信息,保证模型的泛化能力和训练稳定性

批量对 prompt+付出的每个位置 y_


8. 在ppo实际操作中如何实现critic 的输入仅使用当前时刻之前的上下文 (x, y_{

再po一次第七个问题的个人理解:

个人理解:

如图中所示也可以看出,其实左边的value模型接收的输入是t时刻的状态,但是实际上一共有1~T个时刻!

所以我们可以理解为,这样写是要求value模型必须是一个causal因果模型,

value只能依赖当前状态(prompt + 已生成的可见的前文)去给当前状态打分,而不能看到未来的信息!因为它的任务是预估未来的信息。

但是在实际操作中,我们已经获得了prompt + actor给出的完整response,

因此我们在操作上,就是将整个序列塞给value作为输入!

不过我们又做了一个causal mask + teacher forcing的事情来让value打分。

其中:

  • causal mask是指,对于T长度的response,我们逐token打分,且当前token只能看到之前的tokens
  • teacher forcing是指,对于T长度的response,我们的输出不会影响输入(也就是说不是自回归的),我们只是一个一个token去给response中的所有token位置(状态)打分!从而获得一个values序列。

问题:

但是我们不是一次性生成了所有prompt + response的吗?所以具体critic只用y_

是的,你的理解完全正确 ——在 PPO 中,新旧 critic 的输入方式可以通过 teacher forcing + causal mask 实现,只看历史 tokens 而不泄露未来信息。


为什么只用 而不包括 ?

  • 因果一致性(Causality):critic 的目标是预测当前状态下(即 step t 时,已生成的上下文 = prompt + )的价值 ,不应看到未来的对话内容。
  • 避免“偷看”信息:如果 critic 知道后续 tokens,它就会过度拟合,无法正确估值,会导致优势计算不准确。

实现方式:只需一次前向,使用 teacher forcing + causal mask

  • 因为你在 rollout 阶段已经生成了整个响应 sequence ,所以 critic 只要:

    1. 以输入序列 [x, y_1, …, y_{t-1}, y_t]​ 前向,并
    2. 用 causal mask 来确保当前 step 的预测不看未来 tokens,就等于在每个 t 步输入了 (x, y_{
  • 这就是典型的 teacher forcing。不需要手动循环 t,只需一个 batch forward + causal mask,即可获得所有 time-step 的 value 输出。


小结:

  • 输入:完整序列 [x, y_1…y_N]​
  • 注意力机制:decoder 使用 causal mask,确保 step t 只能看到 <= t​ 步输入
  • 输出:critic 在每个 position t 输出 ,即合理的价值估计

TRL/PPOTrainer 就是这样在一次 batch 数据前向中完成多时刻的 critic 估值的,无需显式循环,非常高效。

你可能感兴趣的:(PPO流程的个人疑问集锦 Q & A)