用四篇文章按照层层深入的方式,依次介绍强化学习基础,基于人类反馈的强化学习(RLHF),近端策略优化 (PPO) ,群相对策略优化(GRPO)。
前面两篇文章分别介绍了强化学习的主要知识点和基于人类反馈的强化学习(RLHF):
PPO 算法是现代强化学习领域的一个重要里程碑,它解决了许多早期策略梯度方法面临的问题。我们从它的动机、数学原理、实现细节和应用特点四个方面深入解析。
PPO (Proximal Policy Optimization) 算法的中文名称是"近端策略优化算法"。
这个名称直接翻译了算法的英文名称中的关键词:
"Proximal"(近端):表示该算法在更新策略时会限制新旧策略间的差异幅度
"Policy"(策略):指强化学习中的决策函数
"Optimization"(优化):表示该算法的目标是改进策略以获取更高的回报
一、PPO 的动机与背景
1.1 早期策略梯度方法的问题
传统的策略梯度方法(如REINFORCE算法)存在几个关键问题:
-
样本效率低:每个数据样本只能使用一次
-
更新步长难以控制:太大会导致策略崩溃,太小又会导致学习缓慢
-
训练不稳定:性能经常出现大幅波动
1.2 信任区域方法的出现
为解决这些问题,研究者提出了信任区域方法(Trust Region Methods),如TRPO(Trust Region Policy Optimization)。这类方法通过限制策略更新的幅度来提高稳定性,但TRPO的计算复杂度高,实现困难。
1.3 PPO的诞生
PPO由Schulman等人在2017年提出,旨在保留TRPO的优点(稳定、可靠的策略更新),同时简化实现、提高计算效率。它巧妙地通过裁剪目标函数(clipped objective function)实现了类似信任区域的效果。
二、PPO 的数学原理
2.1 目标函数
PPO的核心目标函数如下:
让我们逐部分理解这个公式:
-
是当前策略(我们要优化的策略),在状态 选择动作 的概率
-
是旧策略(用于生成训练数据的策略),在状态 选择动作 的概率
-
是在旧策略下估计的优势函数
-
是重要性权重,表示同一个动作在新旧策略下的概率比例,我们通常记为
举个例子来说明:
-
假设在某个状态 下,旧策略选择向左移动的概率是 0.2
-
而当前更新后的策略选择向左移动的概率是 0.5
-
那么重要性权重就是 0.5/0.2 = 2.5
-
这表示新策略比旧策略更"喜欢"这个动作,权重大于1
-
重要性采样的核心思想是:虽然数据是按照旧策略 收集的,但我们可以通过这个概率比值来估计,如果是按照新策略 收集数据会得到什么结果。
- 是将比率 限制在 范围内的裁剪函数
2.1.1 两个策略模型的作用
在PPO算法中出现两个策略模型(当前策略 和旧策略 )是基于实现上的需要,这与PPO的核心机制"重要性采样"和"信任区域约束"直接相关。
数据收集与参数更新分离
-
在强化学习中,我们需要收集数据(状态、动作、奖励)来更新策略
-
使用 (旧策略)与环境交互收集数据
-
使用收集到的数据来更新 (当前策略)
-
这种分离允许我们多次使用同一批数据来更新策略,提高数据效率
重要性采样的需要
-
PPO使用重要性采样来重用旧策略收集的数据
-
公式中的 就是重要性权重
-
这个比率告诉我们:如果使用新策略,这个动作的概率与使用旧策略时相比如何变化
信任区域约束的实现
-
PPO的核心创新是用裁剪目标函数来约束策略更新幅度
-
需要比较新旧策略在同一状态-动作对上的概率
-
裁剪操作防止策略变化过大
训练稳定性考虑
-
如果每次收集数据都使用最新策略,可能导致训练不稳定
-
使用固定的旧策略收集一批数据,然后多次更新当前策略,提高稳定性
两个模型在实际实现中:
-
我们只维护一组策略参数
-
在每次大的更新周期开始时,我们将当前参数 复制给
-
使用 收集数据
-
多次使用收集到的数据更新 ,计算目标函数时需要同时用到 和
-
更新周期结束后,再次将更新后的 复制给 ,开始新的周期
所以虽然概念上有两个策略模型,但实际上它们使用的是同一个神经网络架构,只是参数在不同时间点的两个快照。这种设计使PPO能够在保持训练稳定性的同时,有效利用收集到的数据。
2.2.2 重要性采样权重:一个易混淆的概念
重要性采样权重是PPO算法中一个非常容易引起混淆的点
PPO中的重要性采样权重实际意义
在PPO中,"重要性采样权重"指的是比率 ,但这个名称确实有些不恰当
PPO算法中实际发生的过程:
-
数据收集:我们首先使用旧策略 收集一批数据。这个数据收集过程就是标准的环境交互 - 智能体根据策略概率选择动作并记录发生的事情。
-
更新阶段的数据采样:当我们进入更新阶段时,通常会从收集的数据中抽取小批量样本。这种采样通常只是从收集的轨迹中随机选择。这与重要性权重完全无关。
-
重要性权重计算:在选择了小批量样本之后,我们计算该小批量中每个状态-动作对的重要性权重。这些权重不是用于采样的 - 它们用在目标函数中,目的是校正我们用旧策略收集的数据来评估新策略的事实。
为什么它被称为"重要性采样"尽管并没有进行采样
这个术语来源于统计学中的重要性采样,这是一种在只有来自不同分布(称为提议分布)的样本的情况下,估计目标分布属性的技术。
在PPO的背景下:
-
我们想要估计当前策略 下的期望回报(目标分布)
-
但我们只有来自旧策略 的样本(提议分布)
-
我们使用比率 来校正这种分布不匹配
尽管我们没有基于这些权重来采样数据(这才是真正的重要性采样),但我们使用了相同的数学原理来校正分布偏移。这就是为什么使用"重要性采样权重"这个术语,尽管实际上并没有基于这些权重进行采样。
一个具体例子来说明这一点:
-
使用策略 ,我们让智能体与环境交互,收集1000个状态-动作-奖励元组。
-
在更新阶段,我们随机选择其中的64个元组形成一个小批量。
-
对于小批量中的每个元组 ,我们计算:
-
旧策略在状态s中选择动作a的概率:
-
当前策略选择相同动作的概率:
-
这两者之间的比率:
- 我们在PPO目标函数中使用这个比率来调整更新,但我们从不用它来采样数据。
所以 PPO 中的"重要性采样权重"指的是用于目标函数计算的权重,而非用于采样数据的权重。实际发生的采样通常只是从收集的经验中进行随机采样。这是一个微妙但重要的区别,经常使首次学习PPO的人感到困惑。
2.2 裁剪机制的直观理解
裁剪机制是PPO的核心创新,它的工作原理:
- 当优势为正(好的动作):
-
如果新策略使该动作概率增加 () ,裁剪会防止增加太多
-
最多允许概率增加 ε 倍
- 当优势为负(不好的动作):
-
如果新策略使该动作概率减少 () ,裁剪会防止减少太多
-
最少允许概率减少到 ε 倍
取最小值 确保我们始终选择更保守的估计,这防止了过度优化。
2.3广义优势估计(GAE)
PPO通常使用广义优势估计来计算优势函数:
其中 是时序差分误差。
-
是折扣因子
-
控制了偏差-方差权衡
-
是状态价值函数
GAE使我们能够平衡即时奖励和长期价值,减少优势估计的方差。
三、PPO的不同版本
3.1 PPO-Clip(最常见的版本)
这就是我们通常讨论的PPO算法,使用裁剪目标函数来限制策略更新:
PPO-Clip可以有两种实现方式:
a. 纯策略梯度版本
-
只有策略网络(Actor)
-
优势函数使用蒙特卡洛回报或TD-λ估计
-
不学习价值函数,可能使用固定的基线函数或简单的回报平均值
b. Actor-Critic版本(最常用)
-
同时包含策略网络(Actor)和价值网络(Critic)
-
使用价值网络估计状态价值函数
-
基于价值函数估计计算广义优势估计(GAE)
-
总损失函数通常包括策略损失、价值函数损失和熵正则化项
3.2 PPO-Penalty
这是PPO的另一个版本,使用KL散度惩罚而非裁剪:
其中 β 是自适应系数,根据实际 KL 散度调整。
3.3 PPO的其他变体
PPO-CMA
结合了协方差矩阵自适应策略搜索,用于处理连续控制问题。
Distributed PPO
使用多个并行工作线程收集数据和计算梯度,如PPO的分布式实现DPPO。
PPO与其他技术的结合
-
PPO + RND(随机网络蒸馏)用于内在激励
-
PPO + ICM(内在好奇心模块)
-
PPO + GRPO(群相对策略优化,我们之前讨论的)
3.4 为什么Actor-Critic版本最流行?
尽管PPO有多个版本,但Actor-Critic实现确实是最常用的,因为它具有几个显著优势:
-
样本效率:Actor-Critic允许使用时序差分学习,不需要等到完整轨迹结束
-
方差降低:价值函数提供了一个良好的基线,显著降低了策略梯度的方差
-
处理连续环境:对于没有明确终止状态的连续环境特别有效
-
实践证明:在OpenAI和DeepMind等机构的大量实验中,Actor-Critic版本的PPO表现最好
3.5 实际代码实现
在实现PPO时,通常会看到类似这样的代码结构:
初始化网络
policy_net = PolicyNetwork() # Actor
value_net = ValueNetwork() # Critic (这是Actor-Critic版本的特征)
或者有时使用共享特征提取器
shared_net = SharedNetwork()
policy_head = PolicyHead(shared_net)
value_head = ValueHead(shared_net)
损失函数计算
policy_loss = compute_ppo_clip_loss(...)
value_loss = compute_value_loss(...)
entropy_loss = compute_entropy_loss(...)
总损失
total_loss = policy_loss + c1 * value_loss - c2 * entropy_loss
如果是纯策略梯度版本的PPO,就不会有价值网络和相关的价值损失计算部分。
总结来说,当提到"如果使用Actor-Critic版本的PPO"时,我是在区分最常见的Actor-Critic实现和其他可能的PPO变体。在大多数实际应用和教程中,你看到的PPO几乎都是Actor-Critic版本的实现,它已经成为事实上的标准版本。
四、PPO算法的实际实现过程:Actor-Critic版本
4.1 初始化阶段
-
随机初始化策略网络(Actor):输出动作概率分布 ,参数是
-
随机初始化价值网络(Critic):估计状态价值 ,参数是
-
这两个网络可以共享一些层,但有各自的输出头。
-
定义超参数:学习率、PPO裁剪参数 、折扣因子 、GAE参数 等
4.2 主循环开始
PPO算法是一个迭代过程,每次迭代包含以下步骤:
4.2a. 创建旧策略的副本
在每个迭代开始时:
-
将当前策略参数复制一份:
-
此时 和 是完全相同的,这个副本仅用于计算,不会被更新
4.2b. 使用旧策略收集数据
-
使用策略 与环境交互
-
收集多条完整的轨迹数据,每条轨迹都包含从开始到结束的所有时间步的信息:
-
状态序列:
-
动作序列:
-
奖励序列:
-
下一状态序列:
-
动作概率(或对数概率):
- 这样得到一个经验缓冲区 ,包含这一批交互数据
4.2c. 计算回报和优势估计
在Actor-Critic实现中,这一步非常重要:
1. 使用当前价值网络 对每个状态进行评估,输出一个标量值 ,表示从该状态开始,按照当前策略行动,预期能获得的累积折扣奖励。
**2. 计算广义优势估计(GAE)**,它告诉我们某个动作相比于平均表现有多好:
-
先基于 计算 误差:
-
再基于 误差计算优势:
-
优势函数在PPO中扮演着至关重要的角色------它告诉我们哪些动作值得强化(正优势),哪些动作应该减弱(负优势)。
3. 计算目标价值(用于更新价值网络):
- (或直接使用折扣累积奖励)
其中,状态评估过程是Actor-Critic方法的核心------"Critic"(价值网络)评判每个状态的好坏,为"Actor"(策略网络)的学习提供指导。这里的"状态"指的是我们在数据收集阶段(步骤2b)记录下来的每个时间步的环境状态 ,是智能体在每个决策点观察到的环境信息,是它做出决策的依据。
-
在机器人控制任务中,状态可能包括机器人的位置、速度、角度等物理量
-
在游戏中,状态可能是游戏画面的像素或提取的特征
-
在自然语言处理任务中,状态可能是当前的文本表示或对话历史
现在我们有了:
-
状态、动作、旧策略下的动作概率
-
每个时间步的优势估计
-
每个状态的目标价值
4.2d. 多轮策略更新
这是核心步骤,将使用同一批数据进行多轮更新:
策略与价值网络更新循环
对于 轮更新(通常 ):
- 从经验缓冲区 中随机抽取小批量数据(mini-batch)
2. 对于每个状态-动作对,执行以下操作:
策略网络更新:
-
计算当前策略下的动作概率:
-
计算重要性采样比率:
-
计算PPO裁剪目标函数:
-
计算熵奖励(鼓励探索):
价值网络更新:
- 计算价值损失函数,通过最小化预测价值与目标价值之间的均方误差来实现:
组合损失函数:
实际实现中,PPO的损失函数通常包含三部分:
-
是上述PPO目标函数(取负号是因为我们通常最小化损失而非最大化目标)
-
是值函数损失,通常是均方误差
-
是策略的熵,添加它鼓励探索
-
是权重系数
3. 计算损失函数对参数的梯度
4. 使用优化器(通常是Adam)更新策略和价值网络参数:
5. 重复以上步骤进行 轮更新,每轮使用新的随机小批量数据,但都来自同一个经验缓冲区
关键点解释:为什么要固定 用于计算重要性权重
在多轮更新过程中, 会不断变化,但我们仍然使用最初的 来计算重要性权重。这是因为:
-
数据是用 收集的,所以重要性采样必须相对于收集数据时的策略计算
-
如果每次更新后都改变 ,重要性权重计算会变得不一致
-
固定 确保我们可以多次使用同一批数据进行稳定的更新
4.2e. 循环重复
-
完成 轮更新后,回到步骤2a
-
将更新后的策略参数 再次复制给
-
使用新的策略 收集新一批数据
-
然后再次进行多轮策略与价值网络更新
整个过程持续进行,直到达到预设的迭代次数或性能目标。
4.3 实际代码实现示例
下面是一个简化的伪代码,展示Actor-Critic版本PPO的核心实现:
初始化
policy_net = PolicyNetwork()
value_net = ValueNetwork()
policy_optimizer = Adam(policy_net.parameters(), lr=policy_lr)
value_optimizer = Adam(value_net.parameters(), lr=value_lr)
主循环
for iteration in range(num_iterations):
# 复制当前策略
old_policy_net = copy.deepcopy(policy_net)
# 收集数据
trajectories = []
for _ in range(num_trajectories):
states, actions, rewards, next_states, dones = [], [], [], [], []
state = env.reset()
done = False
while not done:
# 计算动作概率并选择动作
action_probs = old_policy_net(state)
action = sample_action(action_probs)
log_prob = calculate_log_prob(action_probs, action)
# 执行动作
next_state, reward, done, _ = env.step(action)
# 存储数据
states.append(state)
actions.append(action)
rewards.append(reward)
next_states.append(next_state)
dones.append(done)
old_log_probs.append(log_prob)
state = next_state
trajectories.append((states, actions, rewards, next_states, dones, old_log_probs))
# 计算优势函数和目标价值
all_states, all_actions, all_advantages, all_targets, all_old_log_probs = [], [], [], [], []
for traj in trajectories:
states, actions, rewards, next_states, dones, old_log_probs = traj
# 计算目标价值和优势
values = value_net(states)
next_values = value_net(next_states)
# GAE计算
advantages = compute_gae(rewards, values, next_values, dones, gamma, lambda_)
targets = advantages + values
all_states.extend(states)
all_actions.extend(actions)
all_advantages.extend(advantages)
all_targets.extend(targets)
all_old_log_probs.extend(old_log_probs)
# 多轮更新
for _ in range(update_epochs):
# 生成小批量数据索引
indices = random.sample(range(len(all_states)), mini_batch_size)
batch_states = [all_states[i] for i in indices]
batch_actions = [all_actions[i] for i in indices]
batch_advantages = [all_advantages[i] for i in indices]
batch_targets = [all_targets[i] for i in indices]
batch_old_log_probs = [all_old_log_probs[i] for i in indices]
# 计算当前策略下的动作概率
current_action_probs = policy_net(batch_states)
current_log_probs = calculate_log_prob(current_action_probs, batch_actions)
# 计算重要性比率
ratios = torch.exp(current_log_probs - batch_old_log_probs)
# PPO裁剪目标函数
surr1 = ratios * batch_advantages
surr2 = torch.clamp(ratios, 1-epsilon, 1+epsilon) * batch_advantages
policy_loss = -torch.min(surr1, surr2).mean()
# 熵奖励
entropy = calculate_entropy(current_action_probs).mean()
# 价值网络损失
current_values = value_net(batch_states)
value_loss = F.mse_loss(current_values, batch_targets)
# 总损失
total_loss = policy_loss + c1 * value_loss - c2 * entropy
# 更新策略网络
policy_optimizer.zero_grad()
policy_loss.backward()
policy_optimizer.step()
# 更新价值网络
value_optimizer.zero_grad()
value_loss.backward()
value_optimizer.step()
五、Actor-Critic版本的PPO训练机器人行走例子
5.1 训练机器人学习行走的完整过程
5.1.1 初始化阶段
我们同时初始化两个网络:
-
策略网络(Actor):输入机器人状态,输出不同动作(前进、后退、左转、右转等)的概率
-
价值网络(Critic):输入机器人状态,输出对该状态价值的估计(预期未来奖励)
两个网络都是随机初始化的,所以机器人最初会做出随机动作,很可能会摔倒。
5.1.2 第1轮更新开始
首先,我们将当前策略网络的参数复制一份,作为"旧策略":
-
策略网络参数:
-
旧策略参数:
5.1.3 使用旧策略收集数据
机器人使用旧策略与环境交互,收集100步行走数据:
-
每一步包含:状态 (机器人姿态、角度等)、动作 (关节运动)、奖励 (前进距离、保持平衡等)、下一状态
-
我们还记录旧策略选择每个动作的概率:
5.1.4 评估状态价值并计算优势
这是Actor-Critic版本的关键步骤:
-
使用价值网络评估每个状态:
-
计算TD误差:
-
例如,如果机器人前进一小步获得奖励0.1,当前状态价值是2.0,下一状态价值是2.2,折扣因子是0.99
- 使用广义优势估计(GAE)计算每一步的优势值:
- 这告诉我们每个动作相对于平均表现有多好/多坏
5.1.5 多轮策略和价值网络更新
现在我们使用这100步数据进行10轮更新:
第1轮更新:
-
从100步数据中随机抽取一个小批量(如20步)
-
对于策略网络:
-
计算当前策略下每个动作的概率:
-
计算概率比:
-
应用PPO的裁剪目标函数,计算策略损失
-
计算策略熵,鼓励探索
- 对于价值网络:
-
计算当前价值预测:
-
计算目标价值(通常是实际回报或优势加当前估计)
-
计算价值损失:
- 分别更新策略网络和价值网络参数
第2轮更新:
-
再次从100步数据中随机抽取一个小批量
-
使用更新后的策略网络和价值网络重复上述过程
-
注意:虽然策略网络已更新,但概率比仍然是相对于最初收集数据的旧策略计算的
第3-10轮更新:
-
重复类似过程,每轮使用不同的随机小批量
-
策略网络和价值网络在每轮更新后都会变化
-
但我们一直使用最初的旧策略概率来计算重要性权重
5.1.6 完成一个完整迭代
经过10轮更新后:
-
策略网络已经学到了更好的行走策略
-
价值网络更准确地评估状态的价值
-
但数据已经"过时"了------它是基于旧策略收集的,而我们的策略已经变化
5.1.7 开始新迭代
回到第2步:
-
将更新后的策略网络参数复制为新的"旧策略":
-
使用这个新的旧策略收集新的100步行走数据(机器人此时应该走得更好一些)
-
使用价值网络评估新收集的状态,计算新的优势估计
-
再次进行10轮更新
5.1.8 持续迭代
这个过程不断重复,机器人的行走能力会逐渐提高:
-
策略网络学会更好的行动决策
-
价值网络更准确地评估状态价值
-
收集的数据质量也会提高,因为机器人摔倒的次数减少
5.2 关键区别:Actor-Critic与普通PPO
与普通PPO相比,Actor-Critic版本的主要区别在于:
-
两个网络并行学习:策略网络和价值网络同时学习,互相支持
-
更精确的优势估计:价值网络提供的状态评估使得优势计算更准确
-
更高效的学习:不必等到轨迹结束才能学习,TD学习允许即时更新
-
两个损失函数:同时优化策略目标和价值预测准确性
通过这种方式,Actor-Critic版本的PPO能够更高效、更稳定地学习复杂任务,如教会机器人行走这样需要精细控制和平衡的任务。
我也准备了一个可以帮你三个月入门到深度学习的籽料包:
【1.超详细的人工智能学习大纲】:一个月精心整理,快速理清学习思路!
【2.基础知识】:Python基础+高数基础
【3.机器学习入门】:机器学习经典算法详解
【4.深度学习入门】:神经网络基础(CNN+RNN+GAN)
【5.项目实战合集】:34个机器学习+36深度学习项目实战
可以关住我的公//粽//呺【迪哥谈AI】回复333 无偿获取!
六、PPO 在大语言模型中的应用
PPO (近端策略优化)算法在大语言模型(LLM)训练中的应用是现代AI发展的重要里程碑,特别是在RLHF(基于人类反馈的强化学习)领域。让我详细解释PPO如何被应用于大语言模型,以及这一过程中的特殊考虑和适应。
6.1 为什么大语言模型需要 PPO?
大语言模型通常经历三个主要的训练阶段:
-
预训练:模型在大量文本数据上进行自监督学习,学习基本的语言能力和知识
-
**监督微调(SFT)**:使用人类编写的高质量回答对模型进行微调
-
对齐:使模型的输出更符合人类偏好和价值观
在第三阶段,PPO成为了实现人类对齐的关键工具。这是因为:
-
我们很难用监督学习直接指定"好"回答的所有特征
-
人类偏好通常是复杂和微妙的,难以用固定规则定义
-
我们需要模型能够学习"为什么"某些回答比其他回答更好
6.2 RLHF框架中的 PPO 实现
在大语言模型的RLHF过程中,PPO的实现包含几个关键组件:
6.2.1 奖励模型(RM)训练
首先,我们需要训练一个奖励模型来模拟人类偏好:
-
收集人类对模型回答的偏好数据(对于同一问题,A回答比B回答更好)
-
训练奖励模型预测人类会偏好的回答
-
这个奖励模型充当PPO训练中的"奖励函数"
6.2.2 PPO在语言模型中的应用
PPO算法应用于语言模型时有一些特殊的考量:
状态-动作空间的定义
-
**状态(s)**:对话历史或当前的提示词(prompt)
-
**动作(a)**:模型生成的下一个token
-
轨迹:完整的对话或生成的回答序列
策略网络(Actor)
-
基于SFT阶段微调的语言模型
-
输入提示词,输出下一个token的概率分布
价值网络(Critic)
-
通常是一个单独的模型,架构可能与策略网络相似
-
预测从当前状态(提示词+已生成tokens)开始能获得的累积奖励
6.2.3 PPO训练流程
大语言模型的PPO训练具体流程是:
1. 初始化:
-
策略模型初始化为SFT模型
-
价值模型通常从策略模型复制,但只保留最后一层不同
-
参考模型(Reference Model)设为SFT模型的副本,用于KL散度计算
2. 数据收集:
-
选择一批提示词
-
使用当前策略模型生成回答
-
使用奖励模型对生成的回答进行评分
3. 优势估计:
-
对于每个生成序列中的token,计算奖励
-
通常,大部分token的直接奖励为0,只有序列末尾会有奖励模型给出的奖励
-
使用价值网络估计每个状态的价值,计算优势
4. 策略更新:
-
使用PPO目标函数更新策略模型
-
特别注意添加KL散度惩罚,防止新策略与原始SFT模型偏离太远
5. 重复迭代:
-
使用更新后的策略模型收集新数据
-
继续优化模型
6.3 PPO在大语言模型中的特殊适应
将PPO应用于大语言模型时,研究者们进行了一些特殊的适应和修改:
6.3.1 KL散度约束
这是最重要的修改之一。为防止语言模型"过度优化"奖励而丧失语言能力:
r_t = r_\\phi(q, o_{\\leq t}) - \\beta \\log \\frac{\\pi_\\theta(o_t\|q, o_{\
-
是奖励模型
-
是参考模型(通常是初始的SFT模型)
-
是 KL 惩罚系数
这确保了模型不会偏离其原有的语言能力,只是向人类偏好方向微调。
6.3.2 序列级别的奖励归因
与传统强化学习不同,语言生成中奖励通常只在序列末尾给出:
-
奖励模型评估整个生成文本,给出一个标量奖励
-
需要将这个奖励归因到生成过程中的每个token
解决方案包括:
-
将整个序列奖励平均分配给每个token
-
使用更复杂的归因方法,如REINFORCE或优势函数估计
6.3.3 批处理和并行化
由于大语言模型训练的计算成本,通常需要特殊的批处理策略:
-
同时处理多个提示词
-
并行生成多个回答
-
使用分布式训练架构提高效率
6.4 实际案例:ChatGPT和Claude的训练
OpenAI 的 ChatGPT 和 Anthropic 的 Claude 都使用了 PPO 作为 RLHF 阶段的关键算法:
ChatGPT训练流程
-
基于GPT-3.5的SFT模型作为起点
-
收集人类偏好数据,训练奖励模型
-
使用PPO和奖励模型迭代优化策略
-
特别关注安全性、有用性和真实性等方面
Claude训练中的创新
Anthropic在Claude训练中对PPO做了一些改进:
-
引入了"宪法AI"方法,使用一组原则指导奖励设计
-
优化了KL散度控制策略,使模型保持更好的基础能力
-
使用了更复杂的奖励分解方法,提高了训练效率