2. RLHF 核心组件:奖励模型、策略模型、参考模型

好,咱们进入正题。RLHF 这套东西,说白了就是三个模型搭台唱戏。我刚开始接触的时候,也觉得这三个模型绕来绕去,容易搞混。但你拆开来看,每个角色其实都很清晰。

我个人习惯把这三个模型比作一个「师徒三人组」:

  • 策略模型——那个正在学习的学生,它负责生成回答。
  • 奖励模型——阅卷老师,给学生的回答打分。
  • 参考模型——老版本的学霸笔记,用来约束学生别跑偏。

嗯,这个比喻虽然简单,但核心逻辑全在里面了。咱们一个一个说。

2.1 奖励模型(Reward Model)—— 那个打分的人

奖励模型是 RLHF 里最关键的「裁判」。它的任务很简单:给定一个 prompt 和一个 response,输出一个标量分数,表示这个回答有多好。

你可能会问:「为什么不直接用人工打分?」原因很简单——人太慢了。你想想看,每次策略模型生成几万条数据,都让人去打分,那成本和时间谁也扛不住。所以我们需要训练一个模型来模拟人类的偏好。

核心要点:奖励模型本质上是一个回归模型,输入是文本对,输出是一个连续值。它学的是「人类觉得什么好」。

我在项目中遇到过一个问题:奖励模型很容易过拟合到某些表面特征上。比如它发现「回答越长分数越高」,或者「包含某些关键词就加分」。这其实是个大坑。

避坑指南:我曾经在训练奖励模型时,发现模型对「谢谢」这个词有莫名的偏好。只要回答里带「谢谢」,分数就高。后来排查发现,标注数据里确实有很多礼貌用语被打了高分。这提醒我们:标注数据的质量,直接决定了奖励模型的上限。

训练奖励模型通常需要以下步骤:

  1. 收集人类偏好数据:对同一个 prompt,让标注员比较两个回答,选出更好的那个。
  2. 构建 pairwise 损失函数:让模型学会区分「好回答」和「差回答」。
  3. 训练一个打分器:最终输出一个连续的奖励值。

代码实现上,一个简单的奖励模型训练流程大概长这样:

# 伪代码:奖励模型训练
for prompt, response_good, response_bad in dataloader:
    score_good = reward_model(prompt, response_good)
    score_bad = reward_model(prompt, response_bad)
    loss = -torch.log(sigmoid(score_good - score_bad))
    loss.backward()
    optimizer.step()

说白了,就是让好回答的分数比坏回答高。就这么简单。

2.2 策略模型(Policy Model)—— 那个学习的学生

策略模型就是我们最终要优化的那个大语言模型。它负责根据 prompt 生成回答,然后从奖励模型那里拿到反馈,再调整自己的参数。

你可能会问:「这不就是普通的强化学习吗?」嗯,对,也不全对。区别在于:

  • 传统 RL 的 action 空间是离散的(比如上下左右),而这里 action 空间是整个词表——几万个 token。
  • 传统 RL 的 reward 来自环境,这里的 reward 来自另一个神经网络(奖励模型)。

我个人习惯用 PPO(Proximal Policy Optimization)来训练策略模型。为什么是 PPO?因为它稳定。我试过其他算法,动不动就崩,PPO 至少能让我睡个安稳觉。

小技巧:训练策略模型时,我建议把学习率设得比预训练阶段小一个数量级。比如预训练用 1e-5,RLHF 阶段用 1e-6 甚至更低。步子迈大了,容易扯着蛋。

策略模型的更新公式大致如下:

# 伪代码:PPO 更新策略模型
for epoch in range(num_epochs):
    # 用当前策略生成回答
    responses = policy_model.generate(prompts)
    # 奖励模型打分
    rewards = reward_model(prompts, responses)
    # 计算优势函数
    advantages = compute_advantages(rewards)
    # PPO 裁剪更新
    loss = ppo_clip_loss(old_log_probs, new_log_probs, advantages)
    loss.backward()
    optimizer.step()

这里有个细节:old_log_probs 是更新前的概率,new_log_probs 是更新后的概率。PPO 通过裁剪(clip)来防止策略一步更新太大,导致模型崩掉。

2.3 参考模型(Reference Model)—— 那个定海神针

参考模型是很多人容易忽略的一个组件。它的作用是什么?防止策略模型「学歪了」。

你想想看,如果没有参考模型,策略模型可能会为了追求高奖励,生成一些奇怪的东西。比如:

  • 回答变得冗长啰嗦(因为长回答更容易拿高分)
  • 语言风格变得不自然(为了迎合奖励模型的偏好)
  • 甚至开始胡编乱造(因为编故事可能更「精彩」)

参考模型就是那个「老版本」的策略模型。它不参与训练,参数冻结。它的作用是在 KL 散度损失中作为锚点,约束新策略不要偏离太远。

核心公式:RLHF 的总损失 = PPO 损失 - β × KL(新策略 || 参考策略)

其中 β 是一个超参数,控制「探索」和「约束」之间的平衡。

我在项目中遇到过一个问题:β 设得太小,模型开始放飞自我;β 设得太大,模型又学不到新东西。这个参数调起来挺折磨人的。我建议从 0.01 开始试,观察 KL 散度的变化,再逐步调整。

注意:参考模型和策略模型的结构必须完全一样。你不能用一个 7B 的参考模型去约束一个 13B 的策略模型,那 KL 散度算出来就没意义了。

2.4 三个模型的协作流程

好,咱们把这三个模型串起来,看看它们是怎么配合的。下面这张图可以帮你理清思路:

RLHF 三模型协作流程图 策略模型 (学生:生成回答) 奖励模型 (老师:打分) 参考模型 (学霸笔记:约束) 生成回答 反馈分数 KL 散度约束 用户 Prompt 最终回答 训练流程: 1. 策略模型根据 prompt 生成回答 2. 奖励模型对回答打分 3. 参考模型通过 KL 散度约束策略更新 4. 策略模型根据奖励和 KL 散度联合更新

整个流程其实就四步:

  1. 生成:策略模型根据 prompt 生成回答。
  2. 打分:奖励模型给这个回答打分。
  3. 约束:参考模型计算 KL 散度,防止策略跑偏。
  4. 更新:策略模型根据奖励和 KL 散度联合更新参数。

嗯,这个流程说起来简单,但实际调参的时候坑不少。我建议你从一个小模型开始试,比如 1.5B 参数,跑通整个流程再上大模型。不然一次训练跑三天,结果发现奖励模型没训练好,那心态就崩了。

我的经验:刚开始做 RLHF 时,我犯过一个低级错误——忘了冻结参考模型的参数。结果参考模型跟着一起更新,KL 散度直接变成 0,整个训练失去了约束。这个错误我犯了两次才记住。嗯,希望你一次就记住。

2.5 三个模型的对比总结

组件 角色 是否参与训练 参数是否冻结 输出
策略模型 学生 生成的文本
奖励模型 老师 是(预训练阶段) 是(RLHF 阶段) 标量分数
参考模型 学霸笔记 概率分布(用于 KL 计算)

这张表我建议你存一下。每次搞混的时候翻出来看看,一目了然。

好了,三个模型的核心内容就这些。说白了,RLHF 的精髓就是让这三个模型各司其职,互相配合。策略模型负责探索,奖励模型负责评价,参考模型负责兜底。缺一个,整个系统就容易出问题。

专注资料整理