























在一个RLHF的流程中,包含了trainer 和 rollout两个过程,其中trainer是训练强化学习的部分,而rollout则是执行模型推理的部分。
在PPO策略中,trainer的主要目的则是为了训练策略模型,它包括了策略模型、RM奖励模型、价值模型,其中RM是人工手动标签离线训练好的模型。rollout阶段是生成数据标签阶段。
策略模型是优化的关键,也是待优化的模型。
在rollout阶段会通过前向操作输出问题的答案,基于用户指令生成回复样本,并记录每个 token 生成的概率。
在trainer过程是待优化的参数,通过 PPO 损失函数更新权重,学习 “生成高奖励回复” 的能力。
价值模型也是critic/value模型,是评估模型输出是否高出平均标准的模型,输入用户指令 + 生成的回复上下文(状态 st),输出一个标量值 V(st),代表该状态下的期望平均奖励。
在verl中采用权重共享 + 独立预测头的方式运行,也就是说,一般和策略模型共享相同的transformers权重,但是在头上添加了预测头,来预测平均奖励。
作用:
核心计算公式:
\(A_t=r−V(st)\)
这里A_t是模型要预测的值,其中r是奖励模型给出的结果,V(St)是价值模型对状态 st 的预测期望值,A_t则是模型输出比期望多多少的值。
奖励奖励模型是一个与策略模型Qwen7B类似的模型,不过不输出连续的字段,而只生成对多个问答的分数。
输入:模型关于输入的多个回答,输出:每个回答对应的分数,以下是AceCodeRM的分数。
一般训练时模型是经过人为标签训练而成的,在一些代码的场景中,奖励模型也可以是沙箱运行的结果。
输入:
question = """\
Given an array of numbers, write a function runningSum that returns an array where each element at index i is the sum of all elements from index 0 to i (inclusive).
For example:
Input: nums = [1,2,3,4]
Output: [1,3,6,10]
"""
program_with_3_errors = """\
def runningSum(nums):
result = []
current_sum = 0
for i in range(1, len(nums)):
result.append(nums[i])
current_sum += nums[i]
return result
"""
program_with_2_errors = """\
def runningSum(nums):
result = []
current_sum = 0
for i in range(0, len(nums)):
result.append(nums[i])
current_sum += nums[i]
return result
"""
program_with_1_errors = """\
def runningSum(nums):
result = []
current_sum = 0
for i in range(0, len(nums)):
result.append(current_sum)
current_sum += nums[i]
return result
"""
program_correct = """\
def runningSum(nums):
result = []
current_sum = 0
for num in nums:
current_sum += num
result.append(current_sum)
return result
"""
program_chats = [
[
{
"content": question,
"role": "user",
},
{
"role": "assistant",
"content": program
}
] for program in [program_with_3_errors, program_with_2_errors, program_with_1_errors, program_correct]
]
输出:
print("RM Scores:", rm_scores)
print("Score of program with 3 errors:", rm_scores[0].item())
print("Score of program with 2 errors:", rm_scores[1].item())
print("Score of program with 1 errors:", rm_scores[2].item())
print("Score of correct program:", rm_scores[3].item())
"""
RM Scores: tensor([-20.5058, -1.7867, 0.4395, 23.0689], device='cuda:0',
grad_fn=<SqueezeBackward0>)
Score of program with 3 errors: -20.505754470825195
Score of program with 2 errors: -1.7866804599761963
Score of program with 1 errors: 0.43949759006500244
Score of correct program: 23.068859100341797
与预期值越接近,便得到越高的分数。
在 Verl 中,PPO 的优化目标是让策略模型生成高奖励回复,核心约束是 “策略更新幅度不能过大”,避免训练崩溃。
PPO的训练流程可分为4个阶段:1. Rollout 数据生成 2. 优势函数计算 3. PPO 策略更新 4. 迭代闭环
RM模型训练的目的是根据用户的单个输入和多个输出,给多个输出打分,倾向性更好的模型将得到更好的分数,输出的是一个分数向量。
在有些场景下,奖励模型也可以是实时运行的沙箱,比如代码场景。
rollout目标是产出 PPO 训练所需的带标签数据,是RLHF训练的前置操作。
输入:用户指令集 + 旧策略模型 (优化前的 7B 模型) + 奖励模型
流程:
这个过程可以视为是收集训练片段的过程,可以认为是训练的离线标签收集过程,得到的是每个token在上下文的情况下的执行概率,得到的回报等。
在 Trainer 模块中执行,目标是计算 优势值 At—— 衡量 “当前动作的奖励是否优于平均水平”,是 PPO 策略更新的核心依据。
输入:Rollout 产出的 batch 数据 + 价值模型 \(Vϕ\)
流程:
这一步是根据训练数据,得到价值模型对每个状态的的回报预测值。
价值函数此时是否和策略函数是同步的?
目标是通过 Clip 截断损失更新策略模型权重,同时优化价值模型。
输入: batch 数据 + 归一化优势值 \(A_t\) + 策略模型 \(π_θ\) + 价值模型\(V_ϕ\)
流程:
3.1:计算策略损失 \(L_{clip}\),这一步的clip非常关键,它限定了策略的更新幅度
3.2:计算价值损失 \(L_{vf}\)
vf_coef(默认 0.5)平衡价值损失与策略损失的占比。3.3:计算熵损失 Lent(鼓励回复多样性)
ent_coef(默认 0.01)控制多样性强度,系数越大回复越多样。3.4:总损失计算与反向传播
输出:更新后的新策略模型 \(πθnew\)
PPO 不是一次性更新,而是多轮迭代,流程如下:
num_epochs)或奖励收敛两阶段的特点总结:1. 在rollout阶段要加载两个模型,此时模型的运行峰值极高,需要较大的显存和IO速度 2. 在trainer阶段则更多的是计算密集,峰值显存和对应的波动都比较小,但是因为有梯度计算,在计算耗费上会比较多。
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。