RLHF 基础概念 #
强化学习基础 #
RLHF 的核心是强化学习(Reinforcement Learning,RL),理解强化学习的基本概念对于掌握 RLHF 至关重要。
强化学习框架 #
text
┌─────────────────────────────────────────────────────────────┐
│ 强化学习框架 │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────┐ │
│ │ 环境 │ │
│ │ Environment │ │
│ └─────────────┘ │
│ ↑ │ │
│ │ 状态 S │ 奖励 R │
│ │ ↓ │
│ ┌─────────────┐ │
│ │ 智能体 │ │
│ │ Agent │ │
│ └─────────────┘ │
│ │ │
│ │ 动作 A │
│ ↓ │
│ │
│ 核心要素: │
│ ├── 状态(State):环境的当前情况 │
│ ├── 动作(Action):智能体可以执行的操作 │
│ ├── 奖励(Reward):环境对动作的反馈 │
│ └── 策略(Policy):智能体的行为策略 │
│ │
└─────────────────────────────────────────────────────────────┘
马尔可夫决策过程(MDP) #
强化学习问题通常建模为马尔可夫决策过程:
text
MDP 定义:
├── 状态空间 S:所有可能的状态
├── 动作空间 A:所有可能的动作
├── 转移概率 P(s'|s,a):在状态 s 执行动作 a 后转移到 s' 的概率
├── 奖励函数 R(s,a):在状态 s 执行动作 a 获得的奖励
└── 折扣因子 γ:未来奖励的折扣系数
目标:找到最优策略 π*,使得期望累积奖励最大
π* = argmax E[Σ γ^t R(s_t, a_t)]
语言模型作为强化学习问题 #
text
┌─────────────────────────────────────────────────────────────┐
│ 语言模型的 RL 建模 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 状态(State): │
│ ├── 当前已生成的 token 序列 │
│ └── 输入提示(prompt) │
│ │
│ 动作(Action): │
│ └── 下一个要生成的 token │
│ │
│ 奖励(Reward): │
│ ├── 奖励模型给出的评分 │
│ └── 通常在序列结束时给出 │
│ │
│ 策略(Policy): │
│ └── 语言模型本身 π(a|s) = P(token|context) │
│ │
│ 轨迹(Trajectory): │
│ └── 完整的生成序列 [token_1, token_2, ..., token_n] │
│ │
└─────────────────────────────────────────────────────────────┘
策略梯度方法 #
RLHF 使用策略梯度方法优化语言模型:
text
策略梯度定理:
────────────────────────
∇J(θ) = E[∇log π_θ(a|s) * Q^π(s,a)]
直观理解:
- 增加高奖励动作的概率
- 降低低奖励动作的概率
- 通过采样估计期望
REINFORCE 算法:
────────────────────────
θ = θ + α * ∇log π_θ(a|s) * G_t
其中 G_t 是从时刻 t 开始的累积奖励
偏好数据收集 #
偏好数据是 RLHF 的核心输入,数据质量直接决定最终效果。
偏好数据格式 #
text
┌─────────────────────────────────────────────────────────────┐
│ 偏好数据结构 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 单条偏好数据: │
│ { │
│ "prompt": "用户输入的问题或指令", │
│ "chosen": "更好的回复", │
│ "rejected": "较差的回复", │
│ "metadata": { │
│ "annotator_id": "标注者ID", │
│ "timestamp": "标注时间", │
│ "confidence": "标注置信度" │
│ } │
│ } │
│ │
│ 多选排序数据: │
│ { │
│ "prompt": "用户输入", │
│ "responses": [ │
│ {"text": "回复1", "rank": 1}, │
│ {"text": "回复2", "rank": 2}, │
│ {"text": "回复3", "rank": 3}, │
│ {"text": "回复4", "rank": 4} │
│ ] │
│ } │
│ │
└─────────────────────────────────────────────────────────────┘
数据收集流程 #
text
步骤 1:提示收集
────────────────────────
├── 从用户交互中收集
├── 人工设计多样化提示
├── 覆盖不同任务类型
└── 确保分布合理
步骤 2:回复生成
────────────────────────
├── 使用 SFT 模型生成多个回复
├── 调整温度参数增加多样性
├── 通常生成 4-9 个候选
└── 记录生成参数
步骤 3:人工标注
────────────────────────
├── 标注者对回复排序
├── 提供标注指南
├── 多人标注取共识
└── 质量控制和审核
步骤 4:数据处理
────────────────────────
├── 清洗异常数据
├── 标注一致性检查
├── 构建训练数据集
└── 划分训练/验证/测试集
标注指南设计 #
text
标注维度:
├── 有用性(Helpfulness)
│ └── 回复是否解决了用户的问题
│
├── 真实性(Truthfulness)
│ └── 信息是否准确、有无幻觉
│
├── 安全性(Safety)
│ └── 是否包含有害内容
│
├── 连贯性(Coherence)
│ └── 回复是否逻辑清晰、语言流畅
│
└── 指令遵循(Instruction Following)
└── 是否正确理解和执行指令
标注规则:
├── 明确各维度的权重
├── 提供正反面示例
├── 定义边界情况处理
└── 定期校准标注标准
数据质量控制 #
text
质量控制措施:
├── 标注者培训
│ ├── 详细培训材料
│ ├── 标注练习和测试
│ └── 定期反馈和校准
│
├── 多人标注
│ ├── 每条数据多人标注
│ ├── 计算标注一致性
│ └── 仲裁不一致样本
│
├── 自动检测
│ ├── 异常检测算法
│ ├── 标注者可信度评估
│ └── 自动过滤低质量数据
│
└── 持续监控
├── 监控标注质量指标
├── 定期审核
└── 反馈改进标注流程
奖励信号设计 #
奖励信号是强化学习的核心,好的奖励设计决定了模型优化的方向。
奖励函数的作用 #
text
┌─────────────────────────────────────────────────────────────┐
│ 奖励函数的作用 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 引导优化方向: │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 高奖励 → 增加该行为的概率 │ │
│ │ 低奖励 → 降低该行为的概率 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 编码人类偏好: │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 奖励模型学习人类偏好模式 │ │
│ │ 将复杂的价值观编码为标量奖励 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 平衡多目标: │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ R_total = α * R_helpfulness │ │
│ │ + β * R_safety │ │
│ │ + γ * R_truthfulness │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
Bradley-Terry 模型 #
RLHF 使用 Bradley-Terry 模型将偏好排序转化为概率:
text
Bradley-Terry 模型:
────────────────────────
假设回复 y_w 比 y_l 好的概率:
P(y_w > y_l | x) = σ(r(x, y_w) - r(x, y_l))
其中:
├── x 是提示
├── y_w 是被选择的回复
├── y_l 是被拒绝的回复
├── r(x, y) 是奖励函数
└── σ 是 sigmoid 函数
损失函数:
────────────────────────
L = -E[log σ(r(x, y_w) - r(x, y_l))]
目标:最大化被选择回复获得更高奖励的概率
奖励模型架构 #
python
import torch
import torch.nn as nn
from transformers import AutoModelForCausalLM
class RewardModel(nn.Module):
def __init__(self, base_model_name, hidden_size=4096):
super().__init__()
self.base_model = AutoModelForCausalLM.from_pretrained(
base_model_name
)
self.value_head = nn.Sequential(
nn.Linear(hidden_size, hidden_size // 2),
nn.ReLU(),
nn.Linear(hidden_size // 2, 1)
)
def forward(self, input_ids, attention_mask=None):
outputs = self.base_model(
input_ids=input_ids,
attention_mask=attention_mask,
output_hidden_states=True
)
last_hidden = outputs.hidden_states[-1]
last_token_hidden = last_hidden[:, -1, :]
reward = self.value_head(last_token_hidden)
return reward
奖励塑造 #
text
原始奖励:
────────────────────────
r(x, y) = 奖励模型输出
加入 KL 约束:
────────────────────────
r_total(x, y) = r(x, y) - β * KL(π_θ || π_ref)
其中:
├── π_θ 是当前策略
├── π_ref 是参考策略(SFT 模型)
├── β 是 KL 惩罚系数
└── 防止模型偏离太远
多目标奖励:
────────────────────────
r_total = α * r_preference
+ β * r_safety
+ γ * r_format
- δ * KL_penalty
KL 散度约束 #
KL 散度约束是 RLHF 训练稳定性的关键。
为什么需要 KL 约束? #
text
问题:奖励模型不完美
────────────────────────
├── 奖励模型可能存在漏洞
├── 模型可能学会"欺骗"奖励模型
├── 生成奖励高但实际质量差的输出
└── 这种现象称为"奖励黑客"(Reward Hacking)
问题:语言能力退化
────────────────────────
├── 过度优化可能导致语言能力下降
├── 生成不自然或重复的内容
├── 失去预训练获得的知识
└── 模型变得"过于安全"而失去有用性
解决方案:KL 约束
────────────────────────
├── 限制策略与参考模型的偏离程度
├── 保持语言能力的同时优化偏好
├── 平衡探索和利用
└── 提高训练稳定性
KL 散度计算 #
text
KL 散度定义:
────────────────────────
KL(P || Q) = Σ P(x) * log(P(x) / Q(x))
在 RLHF 中:
────────────────────────
KL(π_θ || π_ref) = E_x,y [log π_θ(y|x) - log π_ref(y|x)]
实际计算:
────────────────────────
对于序列 y = [y_1, y_2, ..., y_n]:
KL = Σ_t [log π_θ(y_t|y_<t, x) - log π_ref(y_t|y_<t, x)]
KL 约束的实现 #
python
def compute_kl_penalty(policy_logprobs, ref_logprobs):
kl = policy_logprobs - ref_logprobs
return kl.mean()
def rlhf_loss(policy_model, ref_model, reward_model,
input_ids, beta=0.1):
policy_outputs = policy_model(input_ids)
ref_outputs = ref_model(input_ids)
policy_logprobs = policy_outputs.log_probs
ref_logprobs = ref_outputs.log_probs
reward = reward_model(input_ids)
kl_penalty = compute_kl_penalty(policy_logprobs, ref_logprobs)
loss = -(reward - beta * kl_penalty).mean()
return loss
价值函数与优势估计 #
价值函数和优势估计是 PPO 算法的核心组件。
价值函数 #
text
状态价值函数 V(s):
────────────────────────
从状态 s 开始,遵循策略 π 的期望累积奖励
V^π(s) = E[Σ γ^t r_t | s_0 = s]
动作价值函数 Q(s,a):
────────────────────────
在状态 s 执行动作 a,然后遵循策略 π 的期望累积奖励
Q^π(s,a) = E[Σ γ^t r_t | s_0 = s, a_0 = a]
在 RLHF 中:
────────────────────────
├── 状态:已生成的 token 序列
├── 价值函数估计未来奖励的期望
├── 用于计算优势函数
└── 帮助减少方差
优势函数 #
text
优势函数定义:
────────────────────────
A(s,a) = Q(s,a) - V(s)
直观理解:
────────────────────────
├── A > 0:该动作比平均好
├── A < 0:该动作比平均差
└── A = 0:该动作是平均水平
GAE(Generalized Advantage Estimation):
────────────────────────
A_t = Σ_l (γλ)^l δ_{t+l}
其中 δ_t = r_t + γV(s_{t+1}) - V(s_t)
GAE 平衡偏差和方差:
├── λ = 0:低方差,高偏差
├── λ = 1:高方差,低偏差
└── 通常 λ = 0.95
价值模型实现 #
python
class ValueModel(nn.Module):
def __init__(self, base_model_name, hidden_size=4096):
super().__init__()
self.base_model = AutoModelForCausalLM.from_pretrained(
base_model_name
)
self.value_head = nn.Linear(hidden_size, 1)
def forward(self, input_ids, attention_mask=None):
outputs = self.base_model(
input_ids=input_ids,
attention_mask=attention_mask,
output_hidden_states=True
)
hidden_states = outputs.hidden_states[-1]
values = self.value_head(hidden_states)
return values.squeeze(-1)
探索与利用 #
在 RLHF 训练中,平衡探索和利用是关键。
探索策略 #
text
温度采样:
────────────────────────
P(token) = softmax(logits / T)
├── T 高:更多探索,输出更随机
├── T 低:更多利用,输出更确定
└── 通常 T = 1.0 用于训练
Top-k 采样:
────────────────────────
只从概率最高的 k 个 token 中采样
├── 过滤掉低概率选项
├── 平衡多样性和质量
└── 通常 k = 50
Top-p(核)采样:
────────────────────────
从累积概率达到 p 的最小 token 集合中采样
├── 动态调整候选数量
├── 更灵活的探索控制
└── 通常 p = 0.9
探索与利用的平衡 #
text
训练早期:
├── 更多探索
├── 较高的温度
├── 发现更多可能的回复
└── 避免过早收敛
训练后期:
├── 更多利用
├── 较低的温度
├── 精细优化已发现的好的行为
└── 提高最终性能
实际策略:
├── 使用固定的中等温度
├── 或者逐渐降低温度
├── 结合 KL 约束自然限制探索范围
└── 监控奖励和 KL 散度变化
关键超参数 #
PPO 相关超参数 #
| 参数 | 典型值 | 说明 |
|---|---|---|
| learning_rate | 1e-6 ~ 5e-6 | 策略模型学习率 |
| value_learning_rate | 1e-5 ~ 1e-4 | 价值模型学习率 |
| batch_size | 64 ~ 512 | 批次大小 |
| mini_batch_size | 8 ~ 64 | 小批次大小 |
| ppo_epochs | 2 ~ 4 | PPO 更新轮数 |
| clip_range | 0.1 ~ 0.3 | PPO 裁剪范围 |
| gamma | 0.99 ~ 1.0 | 折扣因子 |
| gae_lambda | 0.9 ~ 0.99 | GAE 参数 |
KL 约束相关超参数 #
| 参数 | 典型值 | 说明 |
|---|---|---|
| kl_penalty | 0.01 ~ 0.1 | KL 惩罚系数 |
| target_kl | 0.1 ~ 10 | 目标 KL 散度 |
| adaptive_kl | True | 是否自适应调整 |
奖励模型相关超参数 #
| 参数 | 典型值 | 说明 |
|---|---|---|
| rm_learning_rate | 1e-5 ~ 5e-5 | 奖励模型学习率 |
| rm_batch_size | 64 ~ 256 | 奖励模型批次大小 |
| rm_epochs | 1 ~ 3 | 奖励模型训练轮数 |
下一步 #
现在你已经掌握了 RLHF 的基础概念,接下来学习 奖励模型,深入了解奖励模型的训练细节!
最后更新:2026-04-05