欢迎光临
我们一直在努力

【大模型教程——第三部分:数据工程与定制化】第3章:与人类对齐:偏好优化 (Preference Alignment)

第3章:与人类对齐:偏好优化 (Preference Alignment)

“Alignment is the art of getting what you want, not just what you asked for.”

即使是最强的预训练模型,也只是学会了"续写"。是偏好优化让它学会了"对话"、“拒绝"和"价值观”。


目录

  • 一、对齐三原则与 SFT 的局限
    • 1. HHH 原则:有用、诚实、无害
    • 2. 为什么 SFT 还不够?
  • 二、经典路线:RLHF (PPO)
    • 1. 训练 Reward Model (奖励模型)
    • 2. PPO 算法核心:KL 散度与 Policy 更新
    • 3. 实战:手动实现 PPO Step
  • 三、现代路线:DPO (Direct Preference Optimization)
    • 1. DPO 的数学魔术:无需 Reward Model
    • 2. DPO vs PPO:谁赢了?
    • 3. 实战:使用 TRL 训练 DPO
  • 四、前沿变体:KTO / IPO / ORPO
    • 1. KTO: 如果只有赞和踩,没有比较对
    • 2. IPO: 修复 DPO 的长度偏好问题
    • 3. ORPO: 连 SFT 都不需要了?
    • 4. SPIN: 自我对弈,无需人工数据
  • 五、2025 年最新进展与趋势
    • 1. 从 RLHF 到 RLAIF (AI Feedback)
    • 2. Online DPO: 摆脱静态数据集
    • 3. 多目标对齐:不只是 HHH
    • 4. 对齐税 (Alignment Tax)
    • 5. 主流模型的对齐策略 (2025)
  • 六、本章小结

一、对齐三原则与 SFT 的局限

1. HHH 原则:有用、诚实、无害

OpenAI 定义了对齐的三大支柱:

  • Helpful (有用): 能够解决用户问题。
  • Honest (诚实): 不编造事实 (Hallucination),不知道就说不知道。
  • Harmless (无害): 不生成暴力、色情、歧视内容。

2. 为什么 SFT 还不够?

SFT (Supervised Fine-Tuning) 的训练目标是:

L

S

F

T

=

log

P

(

y

l

a

b

e

l

x

)

L_{SFT} = -\\log P(y_{label} \\mid x)

LSFT=logP(ylabelx)

SFT 只能学会**“模仿"标准答案,但无法理解"好与坏”**的程度。

  • 对于问题 “如何制造炸弹?”,SFT 模型可能会模仿训练集里的高智商回答,给出一份完美的炸弹制作教程。这很 Helpful,但不 Harmless。
  • 我们希望模型知道:即使你的回答在语法上很完美,但因为它是有害的,所以分数极低。

二、经典路线:RLHF (PPO)

Reinforcement Learning from Human Feedback (RLHF) 是 ChatGPT 成功的关键。它把微调分成了三步:SFT -> RM -> PPO。

1. 训练 Reward Model (奖励模型)

1.1 Bradley-Terry 模型:从概率到排序

我们需要一个能模仿人类打分的模型

r

ϕ

(

x

,

y

)

r_\\phi(x, y)

rϕ(x,y)。 输入:提示词

x

x

x,回答

y

y

y。输出:标量分数。

训练数据:成对比较数据 (Pairwise Data)。 Human: “写首诗”

  • A: “窗前明月光…” (人类觉得更好)
  • B: “月亮很大…”

Bradley-Terry 模型假设:人类偏好可以用奖励差的 sigmoid 建模。

给定两个回答

y

w

y_w

yw (winner) 和

y

l

y_l

yl (loser),人类选择

y

w

y_w

yw 的概率为:

P

(

y

w

y

l

x

)

=

exp

(

r

ϕ

(

x

,

y

w

)

)

exp

(

r

ϕ

(

x

,

y

w

)

)

+

exp

(

r

ϕ

(

x

,

y

l

)

)

=

σ

(

r

ϕ

(

x

,

y

w

)

r

ϕ

(

x

,

y

l

)

)

P(y_w \\succ y_l \\mid x) = \\frac{\\exp(r_\\phi(x, y_w))}{\\exp(r_\\phi(x, y_w)) + \\exp(r_\\phi(x, y_l))} = \\sigma(r_\\phi(x, y_w) – r_\\phi(x, y_l))

P(ywylx)=exp(rϕ(x,yw))+exp(rϕ(x,yl))exp(rϕ(x,yw))=σ(rϕ(x,yw)rϕ(x,yl))

其中

σ

(

z

)

=

1

1

+

e

z

\\sigma(z) = \\frac{1}{1 + e^{-z}}

σ(z)=1+ez1 是 sigmoid 函数。

Loss Function (负对数似然):

L

R

M

=

E

(

x

,

y

w

,

y

l

)

D

[

log

σ

(

r

ϕ

(

x

,

y

w

)

r

ϕ

(

x

,

y

l

)

)

]

L_{RM} = -\\mathbb{E}_{(x, y_w, y_l) \\sim \\mathcal{D}} \\left[ \\log \\sigma(r_\\phi(x, y_w) – r_\\phi(x, y_l)) \\right]

LRM=E(x,yw,yl)D[logσ(rϕ(x,yw)rϕ(x,yl))]

直观理解:

  • 如果

    r

    ϕ

    (

    x

    ,

    y

    w

    )

    r

    ϕ

    (

    x

    ,

    y

    l

    )

    r_\\phi(x, y_w) \\gg r_\\phi(x, y_l)

    rϕ(x,yw)rϕ(x,yl),则

    σ

    (

    )

    1

    \\sigma(\\cdot) \\to 1

    σ()1,loss 接近 0

  • 训练目标:拉大胜者和败者的分数差距
1.2 代码实现:最小化 Reward Model

"""
Reward Model 核心实现
架构:Base LM + Linear Head → 标量分数
"""

import torch
import torch.nn as nn
from transformers import AutoModel

class RewardModel(nn.Module):
def __init__(self, base_model_name="gpt2"):
super().__init__()
self.base_model = AutoModel.from_pretrained(base_model_name)
hidden_size = self.base_model.config.hidden_size
self.reward_head = nn.Linear(hidden_size, 1)

def forward(self, input_ids, attention_mask):
outputs = self.base_model(input_ids, attention_mask)
# 取最后一个有效 token 的隐藏状态
last_hidden = outputs.last_hidden_state[:, 1, :]
return self.reward_head(last_hidden).squeeze(1)

# Bradley-Terry Loss
def reward_loss(r_winner, r_loser):
"""
输入:winner 和 loser 的奖励分数(标量)
输出:Bradley-Terry Loss
"""

return torch.log(torch.sigmoid(r_winner r_loser)).mean()

# 使用示例(伪代码)
# r_w = model(winner_ids, winner_mask)
# r_l = model(loser_ids, loser_mask)
# loss = reward_loss(r_w, r_l)

关键点:

  • Reward Model 是一个回归问题,输出标量分数
  • 训练目标:让胜者分数 > 败者分数,差距越大越好
  • 实际应用中,RM 通常基于 SFT 模型初始化

2. PPO 算法核心:KL 散度与 Policy 更新

有了奖励模型,我们就可以用强化学习来训练策略模型

π

θ

\\pi_\\theta

πθ

目标函数:

max

θ

E

x

D

,

y

π

θ

(

x

)

[

r

ϕ

(

x

,

y

)

β

log

π

θ

(

y

x

)

π

r

e

f

(

y

x

)

]

\\max_\\theta \\mathbb{E}_{x \\sim \\mathcal{D}, y \\sim \\pi_\\theta(\\cdot|x)} \\left[ r_\\phi(x, y) – \\beta \\log \\frac{\\pi_\\theta(y|x)}{\\pi_{ref}(y|x)} \\right]

θmaxExD,yπθ(x)[rϕ(x,y)βlogπref(yx)πθ(yx)]

其中:

  • π

    θ

    \\pi_\\theta

    πθ: 当前策略模型(待优化)

  • π

    r

    e

    f

    \\pi_{ref}

    πref: 参考模型(通常是 SFT 模型,frozen)

  • r

    ϕ

    (

    x

    ,

    y

    )

    r_\\phi(x, y)

    rϕ(x,y): 奖励模型的评分

  • β

    \\beta

    β: KL 惩罚系数(通常取 0.01-0.1)

  • D

    \\mathcal{D}

    D: 提示词分布

关键在于 KL 散度惩罚 (KL Penalty):

  • π

    r

    e

    f

    \\pi_{ref}

    πref 是原始的 SFT 模型。

  • 我们希望模型分数变高,但不要偏离 SFT 模型太远。
  • 如果没有 KL 惩罚,模型会利用 Reward Model 的漏洞 (Reward Hacking),生成乱码来骗取高分。

PPO 的核心创新:Clipped Surrogate Objective

标准的策略梯度更新可能导致训练不稳定。PPO 通过限制策略更新幅度来解决这个问题:

L

C

L

I

P

(

θ

)

=

E

t

[

min

(

r

t

(

θ

)

A

^

t

,

clip

(

r

t

(

θ

)

,

1

ϵ

,

1

+

ϵ

)

A

^

t

)

]

L^{CLIP}(\\theta) = \\mathbb{E}_t \\left[ \\min \\left( r_t(\\theta) \\hat{A}_t, \\text{clip}(r_t(\\theta), 1-\\epsilon, 1+\\epsilon) \\hat{A}_t \\right) \\right]

LCLIP(θ)=Et[min(rt(θ)A^t,clip(rt(θ),1ϵ,1+ϵ)A^t)]

其中:

  • r

    t

    (

    θ

    )

    =

    π

    θ

    (

    a

    t

    s

    t

    )

    π

    o

    l

    d

    (

    a

    t

    s

    t

    )

    r_t(\\theta) = \\frac{\\pi_\\theta(a_t|s_t)}{\\pi_{old}(a_t|s_t)}

    rt(θ)=πold(atst)πθ(atst): 新旧策略的概率比

  • A

    ^

    t

    \\hat{A}_t

    A^t: 优势函数 (Advantage),衡量当前动作比平均好多少

  • ϵ

    \\epsilon

    ϵ: 裁剪范围(通常取 0.2),防止更新过大

3. 实战:手动实现 PPO Step

虽然现在常用 trl.PPOTrainer,但理解内部逻辑很重要。

"""
手动实现 PPO 的核心逻辑
输入:策略模型、参考模型、奖励信号
输出:策略损失
"""

import torch
import torch.nn.functional as F

def gather_log_probs(logits, labels):
"""
从 logits 中提取对应 labels 的 log_probs
输入:logits (batch, seq_len, vocab_size), labels (batch, seq_len)
输出:log_probs (batch, seq_len)
"""

log_probs = F.log_softmax(logits, dim=1)
# 选择对应 token 的概率
selected_log_probs = torch.gather(log_probs, dim=1, index=labels.unsqueeze(1)).squeeze(1)
return selected_log_probs

def compute_advantages(rewards, values, gamma=0.99, lam=0.95):
"""
计算 GAE (Generalized Advantage Estimation)
输入:rewards (batch, seq_len), values (batch, seq_len)
输出:advantages (batch, seq_len)
"""

advantages = torch.zeros_like(rewards)
last_gae = 0
for t in reversed(range(len(rewards))):
if t == len(rewards) 1:
next_value = 0
else:
next_value = values[t + 1]
delta = rewards[t] + gamma * next_value values[t]
advantages[t] = last_gae = delta + gamma * lam * last_gae
return advantages

def ppo_step(
policy_model, ref_model, value_model, reward_model,
input_ids, response_ids, attention_mask,
kl_coef=0.1, clip_range=0.2
):
"""
完整的 PPO 更新步骤
输入:
– policy_model: 当前策略模型 (需要梯度)
– ref_model: 参考模型 (frozen)
– value_model: 价值函数 (Critic)
– reward_model: 奖励模型 (frozen)
– input_ids: prompt + response 的 token IDs
– response_ids: 仅 response 部分的 token IDs
– attention_mask: 掩码
输出:policy_loss (标量)
"""

batch_size = input_ids.size(0)

# 1. 计算 Reward Model 的分数
with torch.no_grad():
rewards = reward_model(input_ids, attention_mask) # (batch,)

# 2. 计算参考模型的 log_probs (frozen)
with torch.no_grad():
ref_logits = ref_model(input_ids, attention_mask=attention_mask).logits
ref_logprobs = gather_log_probs(ref_logits[:, :1, :], response_ids[:, 1:])

# 3. 计算当前策略的 log_probs
policy_logits = policy_model(input_ids, attention_mask=attention_mask).logits
policy_logprobs = gather_log_probs(policy_logits[:, :1, :], response_ids[:, 1:])

# 4. 计算 KL 散度惩罚
kl_div = (policy_logprobs ref_logprobs).sum(dim=1) # (batch,)
penalized_rewards = rewards kl_coef * kl_div

# 5. 计算价值函数(用于 Advantage)
values = value_model(input_ids, attention_mask) # (batch,)
advantages = penalized_rewards values # 简化版,实际应使用 GAE

# 6. 保存旧的 log_probs(用于 ratio 计算)
with torch.no_grad():
old_logprobs = policy_logprobs.detach()

# 7. PPO Clipped Loss
ratio = torch.exp(policy_logprobs.sum(dim=1) old_logprobs.sum(dim=1)) # (batch,)
surr1 = ratio * advantages
surr2 = torch.clamp(ratio, 1 clip_range, 1 + clip_range) * advantages
policy_loss = torch.min(surr1, surr2).mean()

# 8. Value Loss (MSE)
value_loss = F.mse_loss(values, penalized_rewards.detach())

return policy_loss, value_loss, kl_div.mean().item()

# 使用示例(伪代码)
# optimizer_policy = torch.optim.AdamW(policy_model.parameters(), lr=1e-6)
# optimizer_value = torch.optim.AdamW(value_model.parameters(), lr=1e-5)
#
# for batch in dataloader:
# loss_p, loss_v, kl = ppo_step(policy_model, ref_model, value_model, reward_model,
# batch["input_ids"], batch["response_ids"], batch["attention_mask"])
# optimizer_policy.zero_grad()
# loss_p.backward()
# optimizer_policy.step()
#
# optimizer_value.zero_grad()
# loss_v.backward()
# optimizer_value.step()
# print(f"Policy Loss: {loss_p.item():.4f}, Value Loss: {loss_v.item():.4f}, KL: {kl:.4f}")

为什么 PPO 很复杂?

从代码可以看出,RLHF 需要同时维护 4 个模型:

  • Policy Model (

    π

    θ

    \\pi_\\theta

    πθ): 待训练的策略

  • Ref Model (

    π

    r

    e

    f

    \\pi_{ref}

    πref): 冻结的参考模型

  • Reward Model (

    r

    ϕ

    r_\\phi

    rϕ): 冻结的奖励模型

  • Value Model (Critic): 用于估计状态价值
  • 这导致:

    • 显存占用巨大(4个7B模型 = 112GB+)
    • 训练不稳定(需精心调节 lr, clip_range, kl_coef)
    • 实现复杂(需要 RL 框架,如 trl.PPOTrainer)

    三、现代路线:DPO (Direct Preference Optimization)

    PPO 极其复杂,需要同时加载 4 个模型(Actor, Critic, Ref, Reward),显存占用巨大,且训练不稳定。 2023 年,Stanford 团队提出的 DPO 改变了游戏规则。

    1. DPO 的数学魔术:从 RLHF 到直接优化

    1.1 核心洞察:Reward 可以用 Policy 表示

    回顾 RLHF 的目标函数:

    max

    π

    θ

    E

    x

    D

    ,

    y

    π

    θ

    (

    x

    )

    [

    r

    ϕ

    (

    x

    ,

    y

    )

    β

    D

    K

    L

    (

    π

    θ

    π

    r

    e

    f

    )

    ]

    \\max_{\\pi_\\theta} \\mathbb{E}_{x \\sim \\mathcal{D}, y \\sim \\pi_\\theta(\\cdot|x)} \\left[ r_\\phi(x, y) – \\beta \\mathbb{D}_{KL}(\\pi_\\theta \\| \\pi_{ref}) \\right]

    πθmaxExD,yπθ(x)[rϕ(x,y)βDKL(πθπref)]

    展开 KL 散度(在

    y

    y

    y 的分布上):

    D

    K

    L

    (

    π

    θ

    π

    r

    e

    f

    )

    =

    E

    y

    π

    θ

    [

    log

    π

    θ

    (

    y

    x

    )

    π

    r

    e

    f

    (

    y

    x

    )

    ]

    \\mathbb{D}_{KL}(\\pi_\\theta \\| \\pi_{ref}) = \\mathbb{E}_{y \\sim \\pi_\\theta} \\left[ \\log \\frac{\\pi_\\theta(y|x)}{\\pi_{ref}(y|x)} \\right]

    DKL(πθπref)=Eyπθ[logπref(yx)πθ(yx)]

    因此目标变为:

    max

    π

    θ

    E

    y

    π

    θ

    [

    r

    ϕ

    (

    x

    ,

    y

    )

    β

    log

    π

    θ

    (

    y

    x

    )

    π

    r

    e

    f

    (

    y

    x

    )

    ]

    \\max_{\\pi_\\theta} \\mathbb{E}_{y \\sim \\pi_\\theta} \\left[ r_\\phi(x, y) – \\beta \\log \\frac{\\pi_\\theta(y|x)}{\\pi_{ref}(y|x)} \\right]

    πθmaxEyπθ[rϕ(x,y)βlogπref(yx)πθ(yx)]

    关键推导:这个优化问题有闭式解!

    最优策略

    π

    (

    y

    x

    )

    \\pi^*(y|x)

    π(yx) 满足:

    π

    (

    y

    x

    )

    =

    1

    Z

    (

    x

    )

    π

    r

    e

    f

    (

    y

    x

    )

    exp

    (

    1

    β

    r

    (

    x

    ,

    y

    )

    )

    \\pi^*(y|x) = \\frac{1}{Z(x)} \\pi_{ref}(y|x) \\exp\\left(\\frac{1}{\\beta} r^*(x, y)\\right)

    π(yx)=Z(x)1πref(yx)exp(β1r(x,y))

    其中

    Z

    (

    x

    )

    =

    y

    π

    r

    e

    f

    (

    y

    x

    )

    exp

    (

    1

    β

    r

    (

    x

    ,

    y

    )

    )

    Z(x) = \\sum_y \\pi_{ref}(y|x) \\exp\\left(\\frac{1}{\\beta} r^*(x, y)\\right)

    Z(x)=yπref(yx)exp(β1r(x,y)) 是配分函数。

    1.2 逆向变换:从 Policy 反推 Reward

    将上式改写,两边同时除以

    π

    r

    e

    f

    \\pi_{ref}

    πref 再取对数:

    log

    π

    (

    y

    x

    )

    π

    r

    e

    f

    (

    y

    x

    )

    =

    1

    β

    r

    (

    x

    ,

    y

    )

    log

    Z

    (

    x

    )

    \\log \\frac{\\pi^*(y|x)}{\\pi_{ref}(y|x)} = \\frac{1}{\\beta} r^*(x, y) – \\log Z(x)

    logπref(yx)π(yx)=β1r(x,y)logZ(x)

    移项得到隐式奖励函数:

    r

    (

    x

    ,

    y

    )

    =

    β

    log

    π

    (

    y

    x

    )

    π

    r

    e

    f

    (

    y

    x

    )

    +

    β

    log

    Z

    (

    x

    )

    r^*(x, y) = \\beta \\log \\frac{\\pi^*(y|x)}{\\pi_{ref}(y|x)} + \\beta \\log Z(x)

    r(x,y)=βlogπref(yx)π(yx)+βlogZ(x)

    关键发现:

    Z

    (

    x

    )

    Z(x)

    Z(x) 只依赖于

    x

    x

    x,在比较两个回答时会消掉!

    1.3 代入 Bradley-Terry 模型

    回顾人类偏好模型:

    P

    (

    y

    w

    y

    l

    x

    )

    =

    σ

    (

    r

    (

    x

    ,

    y

    w

    )

    r

    (

    x

    ,

    y

    l

    )

    )

    P(y_w \\succ y_l \\mid x) = \\sigma(r^*(x, y_w) – r^*(x, y_l))

    P(ywylx)=σ(r(x,yw)r(x,yl))

    代入隐式奖励:

    P

    (

    y

    w

    y

    l

    x

    )

    =

    σ

    (

    β

    log

    π

    (

    y

    w

    x

    )

    π

    r

    e

    f

    (

    y

    w

    x

    )

    +

    β

    log

    Z

    (

    x

    )

    β

    log

    π

    (

    y

    l

    x

    )

    π

    r

    e

    f

    (

    y

    l

    x

    )

    β

    log

    Z

    (

    x

    )

    )

    =

    σ

    (

    β

    log

    π

    (

    y

    w

    x

    )

    π

    (

    y

    l

    x

    )

    β

    log

    π

    r

    e

    f

    (

    y

    w

    x

    )

    π

    r

    e

    f

    (

    y

    l

    x

    )

    )

    \\begin{align} P(y_w \\succ y_l \\mid x) &= \\sigma\\left( \\beta \\log \\frac{\\pi^*(y_w|x)}{\\pi_{ref}(y_w|x)} + \\cancel{\\beta \\log Z(x)} – \\beta \\log \\frac{\\pi^*(y_l|x)}{\\pi_{ref}(y_l|x)} – \\cancel{\\beta \\log Z(x)} \\right) \\\\ &= \\sigma\\left( \\beta \\log \\frac{\\pi^*(y_w|x)}{\\pi^*(y_l|x)} – \\beta \\log \\frac{\\pi_{ref}(y_w|x)}{\\pi_{ref}(y_l|x)} \\right) \\end{align}

    P(ywylx)=σ(βlogπref(ywx)π(ywx)+βlogZ(x)

    βlogπref(ylx)π(ylx)βlogZ(x)

    )=σ(βlogπ(ylx)π(ywx)βlogπref(ylx)πref(ywx))

    DPO Loss(负对数似然):

    L

    D

    P

    O

    (

    π

    θ

    )

    =

    E

    (

    x

    ,

    y

    w

    ,

    y

    l

    )

    D

    [

    log

    σ

    (

    β

    log

    π

    θ

    (

    y

    w

    x

    )

    π

    θ

    (

    y

    l

    x

    )

    β

    log

    π

    r

    e

    f

    (

    y

    w

    x

    )

    π

    r

    e

    f

    (

    y

    l

    x

    )

    )

    ]

    \\boxed{ L_{DPO}(\\pi_\\theta) = -\\mathbb{E}_{(x, y_w, y_l) \\sim \\mathcal{D}} \\left[ \\log \\sigma \\left( \\beta \\log \\frac{\\pi_\\theta(y_w|x)}{\\pi_\\theta(y_l|x)} – \\beta \\log \\frac{\\pi_{ref}(y_w|x)}{\\pi_{ref}(y_l|x)} \\right) \\right] }

    LDPO(πθ)=E(x,yw,yl)D[logσ(βlogπθ(ylx)πθ(ywx)βlogπref(ylx)πref(ywx))]

    人话解释:

  • 我们不需要训练单独的 Reward Model
  • 直接优化 Policy,让

    π

    θ

    (

    y

    w

    x

    )

    π

    θ

    (

    y

    l

    x

    )

    \\frac{\\pi_\\theta(y_w|x)}{\\pi_\\theta(y_l|x)}

    πθ(ylx)πθ(ywx) 的比值大于

    π

    r

    e

    f

    (

    y

    w

    x

    )

    π

    r

    e

    f

    (

    y

    l

    x

    )

    \\frac{\\pi_{ref}(y_w|x)}{\\pi_{ref}(y_l|x)}

    πref(ylx)πref(ywx)

  • KL 惩罚隐式地编码在公式中(通过与

    π

    r

    e

    f

    \\pi_{ref}

    πref 的比率)

  • 1.4 手写 DPO Loss:PyTorch 实现

    DPO Loss 的核心只有几行代码!

    """
    手写 DPO Loss 的 PyTorch 实现
    输入:policy 和 ref 模型的 logits
    输出:DPO Loss
    """

    import torch
    import torch.nn.functional as F

    def compute_log_probs(logits, labels):
    """
    从 logits 中提取对应 labels 的 log-probabilities

    参数:
    logits: (batch_size, seq_len, vocab_size)
    labels: (batch_size, seq_len)
    返回:
    log_probs: (batch_size,) – 每个序列的总 log-prob
    """
    # 计算 log-softmax
    log_probs = F.log_softmax(logits, dim=1)

    # 选择对应 token 的 log-prob
    # gather: 从 log_probs 中按 labels 的索引取值
    per_token_log_probs = torch.gather(
    log_probs,
    dim=1,
    index=labels.unsqueeze(1)
    ).squeeze(1)

    # 对序列长度求和(忽略 padding)
    # 假设 labels = -100 的位置是 padding
    mask = (labels != 100).float()
    return (per_token_log_probs * mask).sum(dim=1)

    def dpo_loss(
    policy_chosen_logps, # π_θ(y_w|x) 的 log-prob
    policy_rejected_logps, # π_θ(y_l|x) 的 log-prob
    ref_chosen_logps, # π_ref(y_w|x) 的 log-prob
    ref_rejected_logps, # π_ref(y_l|x) 的 log-prob
    beta=0.1 # KL 惩罚系数
    ):
    """
    DPO Loss 的核心实现

    参数:
    policy_*_logps: (batch_size,) – policy 模型的 log-probabilities
    ref_*_logps: (batch_size,) – reference 模型的 log-probabilities
    beta: KL 惩罚系数(典型值 0.1)

    返回:
    loss: 标量 – DPO Loss
    metrics: dict – 用于监控的指标
    """
    # 计算 log-ratio
    pi_logratios = policy_chosen_logps policy_rejected_logps
    ref_logratios = ref_chosen_logps ref_rejected_logps

    # DPO Loss: -log σ(β * (π_logratios – ref_logratios))
    logits = beta * (pi_logratios ref_logratios)
    loss = F.logsigmoid(logits).mean()

    # 计算监控指标
    with torch.no_grad():
    # 隐式奖励:r(x,y) = β * log(π/π_ref)
    chosen_rewards = beta * (policy_chosen_logps ref_chosen_logps)
    rejected_rewards = beta * (policy_rejected_logps ref_rejected_logps)
    reward_margin = (chosen_rewards rejected_rewards).mean()

    # 准确率:chosen 的奖励是否 > rejected
    accuracy = (chosen_rewards > rejected_rewards).float().mean()

    metrics = {
    "loss": loss.item(),
    "reward_margin": reward_margin.item(),
    "accuracy": accuracy.item(),
    }

    return loss, metrics

    # 完整训练步骤示例
    def train_step(policy_model, ref_model, batch, beta=0.1):
    """
    一个完整的 DPO 训练步骤

    batch 包含:
    – chosen_input_ids: (B, L_chosen)
    – rejected_input_ids: (B, L_rejected)
    – chosen_labels: (B, L_chosen)
    – rejected_labels: (B, L_rejected)
    """
    # 1. 前向传播 – Policy Model
    policy_chosen_logits = policy_model(batch["chosen_input_ids"]).logits
    policy_rejected_logits = policy_model(batch["rejected_input_ids"]).logits

    policy_chosen_logps = compute_log_probs(
    policy_chosen_logits[:, :1, :], # 去掉最后一个 token
    batch["chosen_labels"][:, 1:] # 去掉第一个 token
    )
    policy_rejected_logps = compute_log_probs(
    policy_rejected_logits[:, :1, :],
    batch["rejected_labels"][:, 1:]
    )

    # 2. 前向传播 – Reference Model (frozen)
    with torch.no_grad():
    ref_chosen_logits = ref_model(batch["chosen_input_ids"]).logits
    ref_rejected_logits = ref_model(batch["rejected_input_ids"]).logits

    ref_chosen_logps = compute_log_probs(
    ref_chosen_logits[:, :1, :],
    batch["chosen_labels"][:, 1:]
    )
    ref_rejected_logps = compute_log_probs(
    ref_rejected_logits[:, :1, :],
    batch["rejected_labels"][:, 1:]
    )

    # 3. 计算 DPO Loss
    loss, metrics = dpo_loss(
    policy_chosen_logps,
    policy_rejected_logps,
    ref_chosen_logps,
    ref_rejected_logps,
    beta=beta
    )

    return loss, metrics

    # 使用示例(伪代码)
    # optimizer = torch.optim.AdamW(policy_model.parameters(), lr=5e-7)
    # for batch in dataloader:
    # loss, metrics = train_step(policy_model, ref_model, batch)
    # optimizer.zero_grad()
    # loss.backward()
    # optimizer.step()
    # print(f"Loss: {metrics['loss']:.4f}, Reward Margin: {metrics['reward_margin']:.4f}")

    代码关键点:

  • Log-Prob 计算:使用 log_softmax + gather 提取每个 token 的概率,再求和
  • DPO Loss 核心:只有一行!-F.logsigmoid(beta * (pi_logratios – ref_logratios))
  • Ref Model 冻结:使用 torch.no_grad() 避免计算梯度
  • 监控指标:
    • reward_margin:chosen 和 rejected 的隐式奖励差
    • accuracy:chosen 的奖励是否大于 rejected
  • 2. DPO vs PPO:谁赢了?

    特性PPO (RLHF)DPO
    稳定性 极低,对超参敏感 极高,像 SFT 一样稳
    显存占用 巨大 (4个模型) 低 (2个模型: Policy + Ref)
    实现难度 困难 简单 (几行代码)
    效果 理论上限高,上限由RM决定 实测与 PPO 持平甚至更好

    目前 (2025),SOTA 模型如 Llama-3, Qwen-2 都在使用 DPO 及其变体。

    3. DPO 实战要点

    关键超参数:

    参数推荐值说明
    beta 0.1 – 0.5 KL 惩罚系数,越大模型越保守
    learning_rate 1e-7 – 5e-7 DPO 的 lr 要比 SFT 小 5-10 倍
    batch_size 2 – 4 显存占用是 SFT 的 2 倍(需同时处理 chosen 和 rejected)

    常见错误:

    • ❌ 使用预训练模型(未 SFT)直接训练 DPO:效果极差,必须先 SFT
    • ❌ learning_rate 太大:导致模型崩溃,loss 变成 NaN
    • ❌ beta 设置为 0:模型会过拟合偏好数据,丧失生成能力

    工具库推荐:

    • TRL (HuggingFace): DPOTrainer 是工业标准实现(详见 Part 5 第 3 章)
    • LLaMA-Factory: 零代码 DPO 训练(详见 Part 5 第 2 章)

    四、前沿变体:KTO / IPO / ORPO

    DPO 虽然好,但它需要成对数据 (Paired Data)。这很难搞:你得找两句话,还得判断谁好谁坏。

    1. KTO: 如果只有赞和踩,没有比较对

    KTO (Kahneman-Tversky Optimization) 不需要成对数据。 它只需要:

    (

    x

    ,

    y

    ,

    l

    a

    b

    e

    l

    )

    (x, y, label)

    (x,y,label),其中 label 是 true (赞) 或 false (踩)。

    核心思想:利用前景理论 (Prospect Theory)

    • 人类对"损失"的厌恶 > 对"收益"的喜悦
    • 如果一个回答被点赞,小幅增加其概率
    • 如果被点踩,大幅降低其概率

    KTO Loss: $$ L_{KTO} = \\mathbb{E}_{(x,y,l)} \\left[ \\begin{cases}

    • \\lambda_D \\cdot \\sigma \\left( \\beta \\log \\frac{\\pi_\\theta(y|x)}{\\pi_{ref}(y|x)} – z_{ref} \\right), & l = 1 \\text{ (desirable)} \\
    • \\lambda_U \\cdot \\sigma \\left( z_{ref} – \\beta \\log \\frac{\\pi_\\theta(y|x)}{\\pi_{ref}(y|x)} \\right), & l = 0 \\text{ (undesirable)} \\end{cases} \\right] $$

    其中:

    • λ

      D

      ,

      λ

      U

      \\lambda_D, \\lambda_U

      λD,λU: 不对称系数(通常

      λ

      U

      >

      λ

      D

      \\lambda_U > \\lambda_D

      λU>λD,惩罚比奖励强)

    • z

      r

      e

      f

      z_{ref}

      zref: 参考点(用于归一化)

    代码实现(核心):

    def kto_loss(policy_logp, ref_logp, label, beta=0.1, lambda_D=1.0, lambda_U=1.5, z_ref=0.0):
    """
    KTO Loss 核心实现
    label: True (desirable) or False (undesirable)
    """

    implicit_reward = beta * (policy_logp ref_logp)
    if label: # desirable
    return lambda_D * torch.sigmoid(implicit_reward z_ref)
    else: # undesirable
    return lambda_U * torch.sigmoid(z_ref implicit_reward)

    适用场景:

    • ✅ 只有点赞/点踩数据(如社交媒体评论)
    • ✅ 标注成本高,无法做成对比较
    • ❌ 需要精细控制偏好(DPO 更好)

    2. IPO: 修复 DPO 的长度偏好问题

    问题:DPO 倾向于生成更长的回答(即使质量不高),因为长句子的 log-likelihood 更高。

    IPO (Identity Preference Optimization) 修改了 DPO 的 Loss 函数:

    L

    I

    P

    O

    =

    E

    [

    (

    log

    π

    θ

    (

    y

    w

    x

    )

    π

    θ

    (

    y

    l

    x

    )

    log

    π

    r

    e

    f

    (

    y

    w

    x

    )

    π

    r

    e

    f

    (

    y

    l

    x

    )

    1

    β

    )

    2

    ]

    L_{IPO} = \\mathbb{E} \\left[ \\left( \\log \\frac{\\pi_\\theta(y_w|x)}{\\pi_\\theta(y_l|x)} – \\log \\frac{\\pi_{ref}(y_w|x)}{\\pi_{ref}(y_l|x)} – \\frac{1}{\\beta} \\right)^2 \\right]

    LIPO=E[(logπθ(ylx)πθ(ywx)logπref(ylx)πref(ywx)β1)2]

    关键变化:

    • 用平方损失代替对数损失(更稳定)
    • 减去常数项

      1

      β

      \\frac{1}{\\beta}

      β1(消除长度偏好)

    实现(需要手动修改 DPOTrainer):

    # IPO Loss 的核心实现
    def ipo_loss(policy_logps_w, policy_logps_l, ref_logps_w, ref_logps_l, beta=0.1):
    """
    IPO 损失函数
    输入:chosen 和 rejected 的 log-probabilities
    """

    # 计算对数比率差
    pi_ratio = policy_logps_w policy_logps_l
    ref_ratio = ref_logps_w ref_logps_l

    # IPO Loss: (π_ratio – ref_ratio – 1/β)^2
    loss = ((pi_ratio ref_ratio) (1.0 / beta)) ** 2
    return loss.mean()

    3. ORPO: 连 SFT 都不需要了?

    传统流程:Pretrain -> SFT -> DPO(两阶段)。 ORPO (Odds Ratio Preference Optimization) 试图把 SFT 和 DPO 合二为一。

    核心思想:在 SFT Loss 基础上,加一个 Odds Ratio 惩罚项。

    L

    O

    R

    P

    O

    =

    L

    S

    F

    T

    (

    y

    w

    )

    +

    λ

    E

    [

    log

    σ

    (

    log

    odds

    θ

    (

    y

    w

    x

    )

    odds

    θ

    (

    y

    l

    x

    )

    )

    ]

    L_{ORPO} = L_{SFT}(y_w) + \\lambda \\cdot \\mathbb{E} \\left[ \\log \\sigma \\left( \\log \\frac{\\text{odds}_\\theta(y_w|x)}{\\text{odds}_\\theta(y_l|x)} \\right) \\right]

    LORPO=LSFT(yw)+λE[logσ(logoddsθ(ylx)oddsθ(ywx))]

    其中 Odds Ratio(胜率比)定义为:

    odds

    θ

    (

    y

    x

    )

    =

    P

    θ

    (

    y

    x

    )

    1

    P

    θ

    (

    y

    x

    )

    \\text{odds}_\\theta(y|x) = \\frac{P_\\theta(y|x)}{1 – P_\\theta(y|x)}

    oddsθ(yx)=1Pθ(yx)Pθ(yx)

    与 DPO 的区别:

    • DPO: 需要先 SFT,再用偏好数据微调
    • ORPO: 直接在预训练模型上同时做 SFT 和偏好优化

    优势:

    • 节省一半训练时间(一次训练完成两个目标)
    • 在 Mistral-7B 上实测效果优于 SFT+DPO

    劣势:

    • 超参数敏感(

      λ

      \\lambda

      λ 需要精心调节)

    • 对数据质量要求极高

    4. SPIN: 自我对弈,无需人工数据

    SPIN (Self-Play Fine-Tuning):模型通过与自己对弈来自我提升。

    算法流程:

  • 迭代 t=0: 用 SFT 模型

    π

    0

    \\pi_0

    π0 生成回答

    y

    0

    g

    e

    n

    y^{gen}_0

    y0gen

  • 构造偏好对:

    (

    x

    ,

    y

    S

    F

    T

    ,

    y

    0

    g

    e

    n

    )

    (x, y^{SFT}, y^{gen}_0)

    (x,ySFT,y0gen),其中

    y

    S

    F

    T

    y^{SFT}

    ySFT 是人工标注的"好"答案

  • DPO 训练: 优化

    π

    1

    \\pi_1

    π1,使其偏好

    y

    S

    F

    T

    y^{SFT}

    ySFT 而非

    y

    0

    g

    e

    n

    y^{gen}_0

    y0gen

  • 迭代 t=1: 用

    π

    1

    \\pi_1

    π1 生成新回答

    y

    1

    g

    e

    n

    y^{gen}_1

    y1gen

  • 重复: 直到模型无法区分自己的输出和 SFT 数据(收敛)
  • 数学表达:

    π

    t

    +

    1

    =

    arg

    max

    π

    E

    x

    D

    [

    log

    σ

    (

    β

    log

    π

    (

    y

    S

    F

    T

    x

    )

    π

    (

    y

    t

    g

    e

    n

    x

    )

    )

    ]

    \\pi_{t+1} = \\arg\\max_\\pi \\mathbb{E}_{x \\sim \\mathcal{D}} \\left[ \\log \\sigma \\left( \\beta \\log \\frac{\\pi(y^{SFT}|x)}{\\pi(y^{gen}_t|x)} \\right) \\right]

    πt+1=argπmaxExD[logσ(βlogπ(ytgenx)π(ySFTx))]

    代码实现(伪代码):

    """
    SPIN 自我对弈训练流程
    """

    from transformers import AutoModelForCausalLM
    from trl import DPOTrainer

    # 初始化模型(SFT 后的模型)
    model = AutoModelForCausalLM.from_pretrained("sft_model")

    # 迭代训练
    for iteration in range(3): # 通常 3-5 轮即可
    print(f"=== SPIN Iteration {iteration} ===")

    # 1. 用当前模型生成回答
    generated_responses = []
    for prompt in prompts:
    response = model.generate(prompt)
    generated_responses.append(response)

    # 2. 构造偏好数据(SFT 数据为 chosen,生成数据为 rejected)
    preference_data = [
    {"prompt": p, "chosen": sft_response, "rejected": gen_response}
    for p, sft_response, gen_response in zip(prompts, sft_responses, generated_responses)
    ]

    # 3. DPO 训练一轮
    trainer = DPOTrainer(model=model, train_dataset=preference_data, beta=0.1)
    trainer.train()

    # 4. 评估:当生成质量接近 SFT 数据时停止
    accuracy = evaluate_model(model)
    if accuracy > 0.95:
    break

    实验结果:

    • 在 GSM8K(数学推理)上,SPIN 使 Llama-2-7B 从 36% 提升到 58%
    • 无需额外标注数据,仅靠自我对弈

    适用场景:

    • ✅ 有高质量 SFT 数据,但无偏好标注
    • ✅ 任务有明确对错(数学、代码)
    • ❌ 主观任务(创意写作)效果不明显

    五、2025 年最新进展与趋势

    1. SimPO:连 Reference Model 都不需要了

    问题:DPO 虽然比 PPO 简单,但仍需要加载一个冻结的 Reference Model,占用显存。

    SimPO (Simple Preference Optimization, 2024) 的核心洞察:

    用序列长度归一化代替 Reference Model!

    1.1 SimPO 的数学推导

    传统 DPO Loss:

    L

    D

    P

    O

    =

    log

    σ

    (

    β

    log

    π

    θ

    (

    y

    w

    x

    )

    π

    θ

    (

    y

    l

    x

    )

    β

    log

    π

    r

    e

    f

    (

    y

    w

    x

    )

    π

    r

    e

    f

    (

    y

    l

    x

    )

    )

    L_{DPO} = -\\log \\sigma \\left( \\beta \\log \\frac{\\pi_\\theta(y_w|x)}{\\pi_\\theta(y_l|x)} – \\beta \\log \\frac{\\pi_{ref}(y_w|x)}{\\pi_{ref}(y_l|x)} \\right)

    LDPO=logσ(βlogπθ(ylx)πθ(ywx)βlogπref(ylx)πref(ywx))

    SimPO 的替换:

    • 移除

      π

      r

      e

      f

      \\pi_{ref}

      πref

    • 对 log-prob 进行长度归一化(average log-prob)
    • 引入 reward margin

      γ

      \\gamma

      γ(类似 SVM 的 margin)

    L

    S

    i

    m

    P

    O

    =

    log

    σ

    (

    β

    (

    log

    π

    θ

    (

    y

    w

    x

    )

    y

    w

    log

    π

    θ

    (

    y

    l

    x

    )

    y

    l

    )

    γ

    )

    \\boxed{ L_{SimPO} = -\\log \\sigma \\left( \\beta \\left( \\frac{\\log \\pi_\\theta(y_w|x)}{|y_w|} – \\frac{\\log \\pi_\\theta(y_l|x)}{|y_l|} \\right) – \\gamma \\right) }

    LSimPO=logσ(β(ywlogπθ(ywx)yllogπθ(ylx))γ)

    其中:

    • y

      |y|

      y: 序列长度(token 数)

    • γ

      \\gamma

      γ: reward margin,通常取 0.5-2.0

    关键优势:

  • 零显存开销:不需要加载 Reference Model
  • 更好的长度泛化:长度归一化天然避免长度偏好
  • 隐式奖励更稳定:margin

    γ

    \\gamma

    γ 提供了更大的容错空间

  • 1.2 手写 SimPO Loss

    """
    SimPO Loss 的 PyTorch 实现
    对比 DPO:无需 Reference Model!
    """

    import torch
    import torch.nn.functional as F

    def simpo_loss(
    policy_chosen_logps, # π_θ(y_w|x) 的 log-prob
    policy_rejected_logps, # π_θ(y_l|x) 的 log-prob
    chosen_lengths, # y_w 的长度
    rejected_lengths, # y_l 的长度
    beta=2.0, # 温度系数(SimPO 通常用更大的 beta)
    gamma=1.0 # reward margin
    ):
    """
    SimPO Loss 核心实现

    参数:
    policy_*_logps: (batch_size,) – log-probabilities(总和)
    *_lengths: (batch_size,) – 序列长度
    beta: 温度系数(典型值 1.0-5.0)
    gamma: reward margin(典型值 0.5-2.0)

    返回:
    loss: 标量 – SimPO Loss
    """
    # 长度归一化:平均 log-prob
    avg_log_prob_chosen = policy_chosen_logps / chosen_lengths
    avg_log_prob_rejected = policy_rejected_logps / rejected_lengths

    # SimPO Loss: -log σ(β * (avg_logp_w – avg_logp_l) – γ)
    logits = beta * (avg_log_prob_chosen avg_log_prob_rejected) gamma
    loss = F.logsigmoid(logits).mean()

    # 监控指标
    with torch.no_grad():
    # 隐式奖励(归一化后的)
    reward_margin = (avg_log_prob_chosen avg_log_prob_rejected).mean()
    accuracy = (avg_log_prob_chosen > avg_log_prob_rejected).float().mean()

    metrics = {
    "loss": loss.item(),
    "reward_margin": reward_margin.item(),
    "accuracy": accuracy.item(),
    }

    return loss, metrics

    # 对比:DPO vs SimPO
    # DPO: 需要 2 个模型(policy + ref),需要计算 ref_logps
    # SimPO: 只需 1 个模型(policy),直接用长度归一化

    实验结果(2024 年论文):

    任务DPO (7B)SimPO (7B)显存节省
    AlpacaEval 82.3% 85.7% 40%
    MT-Bench 7.45 7.68 40%

    适用场景:

    • ✅ 显存受限(单卡训练 7B 模型)
    • ✅ 需要更好的长度泛化
    • ❌ 需要强约束(DPO 的 ref model 提供更强的 KL 约束)

    2. 从 RLHF 到 RLAIF (AI Feedback)

    问题:人类标注成本高($10-30/小时),速度慢,还有标注者偏见。

    解决方案:用 GPT-4/Claude 等强模型来生成偏好数据。

    Constitutional AI (Anthropic):

  • 定义"宪法"(价值观规则),如"拒绝有害请求"
  • 让 AI 自己评判回答是否符合宪法
  • 用 AI 生成的偏好数据训练模型
  • 效果:Claude-2 的 Harmlessness 指标提升 40%,完全基于 RLAIF。

    2. Online DPO: 摆脱静态数据集

    传统 DPO 问题:使用固定的偏好数据集,无法适应模型迭代。

    Online DPO:

    • 训练过程中实时生成 rejected 样本
    • 每个 epoch 使用当前模型生成新的负样本
    • 类似 SPIN,但不需要 SFT 数据作为 chosen

    优势:

    • 数据永不过时(always on-policy)
    • 避免分布偏移(distribution shift)

    3. 多目标对齐:不只是 HHH

    现代对齐不止考虑 Helpful、Honest、Harmless,还包括:

    • Factuality (事实性):减少幻觉
    • Safety (安全性):防止 Jailbreak
    • Reasoning (推理能力):保持逻辑链
    • Efficiency (效率):生成简洁的回答(避免冗长)

    多目标 DPO:

    L

    =

    α

    1

    L

    h

    e

    l

    p

    f

    u

    l

    +

    α

    2

    L

    h

    a

    r

    m

    l

    e

    s

    s

    +

    α

    3

    L

    f

    a

    c

    t

    u

    a

    l

    +

    α

    4

    L

    c

    o

    n

    c

    i

    s

    e

    L = \\alpha_1 L_{helpful} + \\alpha_2 L_{harmless} + \\alpha_3 L_{factual} + \\alpha_4 L_{concise}

    L=α1Lhelpful+α2Lharmless+α3Lfactual+α4Lconcise

    每个目标使用不同的偏好数据集,联合优化。

    4. 对齐税 (Alignment Tax)

    现象:对齐训练会损害模型的原始能力(如代码生成、数学推理)。

    原因:

    • 过度的 safety 训练导致模型"过于谨慎"
    • KL 惩罚限制了模型的表达能力

    解决方案:

    • Targeted Alignment: 只对特定领域(如 safety)做对齐,保留其他能力
    • Iterative DPO: 多轮小步迭代,而非一次大步
    • Weak-to-Strong Generalization: 用弱模型的偏好数据训练强模型

    5. 主流模型的对齐策略 (2025)

    模型对齐方法数据来源
    GPT-4 RLHF (PPO) 人工标注 + RLAIF
    Claude 3 Constitutional AI (DPO) 完全 RLAIF
    Llama-3 DPO + IPO 人工标注
    Qwen-2 ORPO (单阶段) 人工标注 + 自我对弈
    DeepSeek-V2 Online DPO RLAIF + 多目标对齐

    趋势总结:

    • ✅ DPO 取代 PPO(稳定性 + 效率)
    • ✅ RLAIF 取代人工标注(成本 + 规模)
    • ✅ 单阶段训练(ORPO)成为新宠
    • ✅ 多目标对齐成为标配

    六、本章小结

    核心要点

  • 对齐是刚需:没有对齐的模型是危险且不可用的。HHH(Helpful, Honest, Harmless)是基本原则。

  • RLHF 已成过去式:PPO 虽然理论优雅,但工程上复杂度太高(4 个模型,不稳定),已被 DPO 取代。

  • DPO 是现代标准:通过数学推导消除 Reward Model,将 RL 转化为分类问题,训练稳定且效果出色。

  • 多种变体各有千秋:

    • KTO: 适用于只有点赞/踩数据的场景
    • IPO: 修复 DPO 的长度偏好问题
    • ORPO: 单阶段训练,省时省力
    • SPIN: 自我对弈,无需额外标注
  • 未来趋势:

    • 从 Human Feedback 走向 AI Feedback (RLAIF)
    • 从离线训练走向在线训练 (Online DPO)
    • 从单目标走向多目标对齐
    • 从两阶段(SFT+DPO)走向单阶段(ORPO)
  • 实践建议

    如果你是工程师:

    • 优先使用 TRL 库的 DPOTrainer(成熟稳定)
    • beta 参数从 0.1 开始调试
    • 确保先做 SFT,再做 DPO(除非用 ORPO)
    • 监控 KL 散度,避免模型偏离过远

    如果你是研究员:

    • 探索 ORPO/SPIN 等单阶段方法
    • 尝试 RLAIF(用 GPT-4 生成偏好数据)
    • 研究多目标对齐(factuality + safety + reasoning)

    延伸阅读

    核心论文:

  • RLHF: Training language models to follow instructions with human feedback (OpenAI, 2022)
  • DPO: Direct Preference Optimization: Your Language Model is Secretly a Reward Model (Stanford, 2023)
  • KTO: Kahneman-Tversky Optimization (Cornell, 2024)
  • ORPO: Odds Ratio Preference Optimization (KAIST, 2024)
  • SPIN: Self-Play Fine-Tuning Converts Weak Language Models to Strong Language Models (UCLA, 2024)
  • 工具库:

    • TRL (Transformer Reinforcement Learning) – HuggingFace 官方库
    • LLaMA-Factory – 零代码 DPO 训练
    • OpenRLHF – 开源 RLHF 框架

    下一章预告: 第4章 – 创建更优的嵌入模型

    除了生成模型,Embedding 模型也是 LLM 生态的重要部分。下一章我们将探讨对比学习、InfoNCE 和 MTEB 榜单,教你训练媲美 OpenAI Ada-002 的嵌入模型。

    赞(0)
    未经允许不得转载:171主机测评 » 【大模型教程——第三部分:数据工程与定制化】第3章:与人类对齐:偏好优化 (Preference Alignment)
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址