如何训练一个 Reward Model:RLHF 的核心组件详解

发布于:2025-07-03 ⋅ 阅读:(24) ⋅ 点赞:(0)

Reward Model(奖励模型)是 RLHF 的核心,决定了模型“觉得人类偏好什么”的依据。本文将系统介绍如何从零开始训练一个 reward model,包括数据准备、模型结构、损失函数、训练方法与注意事项。

什么是 Reward Model?

Reward Model(RM)是一个评分器:它输入一个文本(通常是 prompt + 模型回答),输出一个实数分值(reward),表示这个回答的“人类偏好程度”。

它不是分类器,也不是生成器,而是一个 打分器

在 RLHF 流程中,RM 的作用是:

  1. 替代人工给生成内容打分;

  2. 指导 PPO 等算法优化语言模型,让它生成更“优质”的回答。

训练 Reward Model 的流程

步骤概览:

  1. 准备人类偏好数据(pairwise comparisons);

  2. 构建 backbone 模型(Transformer);

  3. 添加 reward head(输出 scalar);

  4. 使用 pairwise loss 进行训练;

  5. 验证 reward model 能正确排序人类偏好。

1. 数据准备:Pairwise Preference Data

Reward Model 通常使用 人类偏好数据对(Preference Pairs) 训练。

每条样本形式为:

{
  "prompt": "Explain what is RLHF.",
  "chosen": "RLHF is a method where humans guide the training...",
  "rejected": "RLHF is a way of training GPT models by ... (low quality)"
}

这意味着:在给定 prompt 下,chosenrejected 更好。

数据来源:

  • OpenAI 的 summarize-from-feedback

  • Anthropic HH (Helpful–Harmless) dataset

  • 自定义对比打分数据(通过众包等获得)

2. 模型结构设计

✅ Backbone 模型

Reward model 通常使用预训练语言模型作为 backbone,比如:

  • bert-base-uncased(RoBERTa 更好)

  • gpt2(decoder-only 模型)

  • llama, chatglm, baichuan, qwen, etc.

✅ Reward Head

在模型顶部添加一个 Dense 层,输出一个 scalar:

class RewardModel(tf.keras.Model):
    def __init__(self):
        self.backbone = TFAutoModel.from_pretrained("bert-base-uncased")
        self.reward_head = tf.keras.layers.Dense(1)  # 输出 reward 分数
    def call(self, input_ids, attention_mask):
        output = self.backbone(input_ids, attention_mask=attention_mask)
        cls_embedding = output.last_hidden_state[:, 0, :]
        reward = self.reward_head(cls_embedding)
        return tf.squeeze(reward, axis=-1)

对于 decoder-only 模型(如 GPT、LLaMA),常用策略是取最后一个 token 的 hidden state 或均值池化。

3. 损失函数:Pairwise Logistic Loss

Reward Model 不预测具体分数,而是学习排序关系

给定一个 batch:

  • r_chosen = RM(prompt + chosen)

  • r_rejected = RM(prompt + rejected)

目标:使 r_chosen > r_rejected

损失函数(pairwise loss)定义为:

L=−log⁡(σ(rchosen−rrejected))\mathcal{L} = -\log(\sigma(r_{\text{chosen}} - r_{\text{rejected}}))

实现(PyTorch):

def pairwise_loss(reward_chosen, reward_rejected):
    return -torch.log(torch.sigmoid(reward_chosen - reward_rejected)).mean()

这种损失称为 BPR Loss / Bradley-Terry loss / RankNet loss,是训练 ranking 模型的标准做法。

4. 输入构建策略

输入内容:

将 prompt 和 response 拼接成一段文本输入 reward model。

例如:

input_text = prompt + response
tokenized = tokenizer(input_text, padding=True, truncation=True, return_tensors="pt")

为了避免模型“偏向 prompt”,你可以只喂 response,也可以打上特殊分隔符(如 <|sep|>)。

5. 训练技巧

项目 推荐设置
Optimizer AdamW
Learning Rate 1e-5 ~ 5e-6
Batch Size 8 ~ 64
Max Token Length 512 ~ 1024
Regularization gradient clipping, weight decay
Evaluation accuracy of ranking, NDCG

评估方式

你可以用如下指标评估 reward model 的排序能力:

  • Pairwise accuracy(多少对判断正确)

  • Kendall’s Tau / Spearman correlation

  • NDCG(对于多选排序数据)

常见问题 FAQ

Reward 值范围有限制吗?

→ 理论上是任意 float,但实践中建议控制范围(如 [-5, 5])防止 PPO 梯度不稳定。

Reward Model 一定要用 LLaMA 吗?

→ 不一定。小模型如 RoBERTa 也可以。只有当你追求极高一致性或生成风格对齐时,才建议用同架构。

可以多头训练 reward model 吗?

→ 是的,可以扩展为多任务结构,如同时预测 helpfulness 和 harmlessness。

总结:训练一个 Reward Model 的完整流程

步骤 内容
数据准备 收集 prompt + chosen/rejected 对
模型选择 使用 BERT / GPT / LLaMA 等作为 backbone
输入构造 拼接 prompt 与 response,做 tokenization
构建 reward head 加一个 dense 输出实数分值
训练 loss 使用 pairwise logistic loss
评估指标 ranking accuracy、NDCG、Kendall Tau
输出范围 推荐做归一化或限制范围

推荐工具库

  • transformers

  • trl — PPO / DPO 强化训练

  • wandb — 训练日志可视化

  • datasets — 读取 OpenAI / Anthropic 公开数据

参考开源项目

附加: 利用 Reward Model 和 RLHF 微调 LLaMA3

现在我们已经训练好了 Reward Model,接下来我们将它用于 微调 LLaMA3 模型,使其生成更符合人类偏好的内容。这一步通常称为 RLHF 的第二阶段:使用强化学习优化语言模型策略

背景:RLHF 三阶段流程

阶段 目标 方法
1. SFT(监督微调) 初步学习任务 用人类标注样本微调 LLM
2. Reward Model 训练 模拟人类偏好 用人类比较训练 RM
3.RLHF(PPO/DPO) 提升生成质量 用 RM 做 reward,强化训练 LLM

我们现在要做的,就是第三阶段的 PPO 微调

1. 准备工作

模型

  • Policy 模型(被优化者)LLaMA3-8BLLaMA3-7B

  • Reward 模型(打分者):你在前面阶段训练得到的 RM,可是小模型如 RoBERTa,也可以是 LLaMA3。

工具

我们使用 Hugging Face 的 trl 包,它封装了 PPO 的训练过程。

安装依赖:

pip install trl transformers datasets accelerate bitsandbytes

2. PPO 微调 LLaMA3(代码示例)

下面是使用 trl 对 LLaMA3 模型进行 PPO 微调的一个精简范例。

from transformers import AutoTokenizer, AutoModelForCausalLM
from trl import PPOTrainer, PPOConfig
import torch

#  加载 Policy 模型(LLaMA3)
model_name = "meta-llama/Meta-Llama-3-8B"
policy_model = AutoModelForCausalLM.from_pretrained(model_name, device_map="auto", load_in_4bit=True)
tokenizer = AutoTokenizer.from_pretrained(model_name)
tokenizer.pad_token = tokenizer.eos_token

#  加载 Reward Model(之前训练的)
reward_model = AutoModelForCausalLM.from_pretrained("your-reward-model-checkpoint").eval().to("cuda")

#  配置 PPOTrainer
config = PPOConfig(
    model_name=model_name,
    learning_rate=1e-5,
    batch_size=4,
    mini_batch_size=1,
    gradient_accumulation_steps=4,
    log_with="wandb",  # optional
)

ppo_trainer = PPOTrainer(config=config, model=policy_model, tokenizer=tokenizer)

#  示例 prompt 数据
prompts = [
    "Explain how quantum computing works.",
    "What are some good ways to improve sleep quality?",
    "Why is the sky blue?"
]

for prompt in prompts:
    # Tokenize input
    inputs = tokenizer(prompt, return_tensors="pt").to("cuda")

    # 生成 response
    response_ids = policy_model.generate(**inputs, max_new_tokens=64)
    response = tokenizer.decode(response_ids[0], skip_special_tokens=True)

    # 构建 reward model 输入
    full_input = prompt + response
    reward_input = tokenizer(full_input, return_tensors="pt", padding=True, truncation=True).to("cuda")

    # 使用 Reward Model 打分
    with torch.no_grad():
        reward_logits = reward_model(**reward_input).logits
        reward_score = reward_logits[:, -1].mean().item()

    # PPO step
    ppo_trainer.step([prompt], [response], [reward_score])

    print(f"Prompt: {prompt}")
    print(f"Response: {response}")
    print(f"Reward Score: {reward_score:.4f}")

3.训练建议与技巧

项目 推荐
Batch Size 4 ~ 16
Learning Rate 1e-5 ~ 5e-6
生成长度 控制在 64~128 token,便于稳定奖励
数据 使用指令 + 多样领域 prompt
LoRA 可选,节省资源(qLoRA + PPO)
Mixed Precision 推荐使用 FP16 / bfloat16
训练时长 PPO 通常训练 10k~50k steps

4. 奖励信号设计建议

  • 奖励值的尺度很重要,避免 reward 值过大或过小;

  • 建议 reward 范围控制在 -5 ~ +5;

  • 可加入 KL penaltyKL control 来防止模型发散。

总结:使用 Reward Model 强化微调 LLaMA3

步骤 工具 目标
✅ 准备 Reward Model transformers 提供打分
✅ 加载 LLaMA3 AutoModelForCausalLM 微调目标模型
✅ 使用 PPOTrainer trl 根据 reward 优化生成行为
✅ 控制训练稳定性 KL 约束、clip、reward 范围 保证输出多样性和一致性

拓展方向

  • 使用 DPO 替代 PPO(无需 reward scalar,直接对比 pair);

  • 使用 Preference Transformer 将 RM 与生成过程融合;

  • 多任务 RM(评分 helpfulness、toxicity 等多维指标);

  • 强化风格 / 语调一致性:RM 评分“像人说话”的程度。


网站公告

今日签到

点亮在社区的每一天
去签到