Llama-factory 详细学习笔记:第六章:DPO (直接偏好优化) 实战 (难点)

第六章:DPO (直接偏好优化) 实战 (难点)

在SFT之后,我们的模型学会了“说话”,但它的回答可能仍然是“正确的废话”,或者在面对开放性问题时,其回答的安全性、有用性和真实性仍有待提高。传统的解决方案是强化学习(RLHF),即先训练一个奖励模型(RM),再用这个RM作为环境,通过复杂的强化学习算法(如PPO)来优化语言模型。然而,RLHF流程复杂、训练不稳定、且对计算资源要求极高,令许多开发者望而却步。

直接偏好优化 (Direct Preference Optimization, DPO) 的出现,如同一道曙光,彻底改变了这一局面。它以一种极其优雅和高效的方式,实现了与RLHF相媲美甚至更好的对齐效果,但训练成本和复杂度却大大降低。本章将深入剖析DPO的核心思想、重难点配置,并通过详尽的实战步骤,带你完整地跑通一个DPO训练流程,真正让你的模型“更懂人心”。

6.1 为什么需要 DPO? (轻理论:替代 PPO,让模型更符合人类偏好)

要理解DPO的革命性,我们首先要明白传统RLHF的痛点。

  • 传统RLHF的四步“炼丹法” (复杂且昂贵):
    1. SFT阶段:先对基座模型进行监督微调,得到一个能对话的基础策略模型 (SFT Model)。
    2. RM阶段:收集人类偏好数据 (prompt, chosen_response, rejected_response),训练一个奖励模型 (Reward Model),让它学会给回答打分。
    3. PPO阶段 (瓶颈):这是最复杂的一步。需要同时在GPU内存中加载四个模型
      • 正在训练的策略模型 (Policy Model)。
      • 用于计算奖励分数的奖励模型 (Reward Model)。
      • 一个SFT模型的冻结副本,用于计算KL散度惩罚,防止模型“走火入魔”。
      • 一个用于生成经验的生成模型(有时与策略模型是同一个)。
        这个阶段通过PPO算法,让策略模型生成回答,奖励模型打分,然后根据分数更新策略模型,整个过程涉及大量的采样和复杂的超参数调试,非常不稳定。
    4. 评估阶段:对优化后的模型进行人工或自动评估。
PPO 训练实战(可选,用于对比)

为了让你更直观地感受 PPO 训练的复杂性,我们在这里提供一个使用 Llama-factory 进行 PPO 训练的命令示例。请注意,运行此步骤的前提是你已经完成了 SFT 阶段和 RM 阶段的训练。

  • PPO 训练的前提:
    1. SFT 模型: 假设我们已有一个训练好的 SFT 适配器,存放在 saves/Qwen1.5-7B/lora/sql_generator_v1
    2. RM 模型: 假设我们已有一个训练好的奖励模型适配器,存放在 saves/Qwen1.5-7B/lora/sql_reward_model_v1
    3. PPO 数据: PPO 训练时,通常只需要一个包含一系列 prompt(指令)的数据集即可,模型会根据这些 prompt 生成回答,并由奖励模型打分。假设我们有一个 ppo_prompts.jsonl 文件,并已注册为 sql_ppo_prompts
  • 脚本核心参数解读 (与 DPO 对比):
    • --stage ppo: 切换到 PPO 模式。这是启动 PPO 训练的开关。
    • --adapter_name_or_path ...: 指定 SFT 模型的适配器,它将作为 PPO 训练的初始策略模型
    • --reward_model ...: 这是 PPO 独有的关键参数。你需要明确提供一个已经训练好的奖励模型 (RM) 的路径。在训练过程中,这个 RM 会被加载进来,用于给策略模型生成的回答打分,从而产生梯度信号。
    • 内存消耗:请注意,这个命令启动后,除了策略模型和其 SFT 参考模型外,还需要额外加载一个奖励模型。这就是我们在理论部分提到的 PPO 资源消耗大的原因之一。
    • 超参数:PPO 还有许多独特的超参数,如 kl_coeff (功能类似 DPO 的 beta)、ppo_score_norm 等,这些参数的调试通常比 DPO 更为复杂和敏感,进一步增加了训练的不稳定性。

PPO 训练脚本 (train_ppo_sql.sh):

#!/bin/bashexportCUDA_VISIBLE_DEVICES="0" llamafactory-cli train \ --stage ppo \ --do_train \ --model_name_or_path Qwen/Qwen1.5-7B-Chat \ --adapter_name_or_path saves/Qwen1.5-7B/lora/sql_generator_v1 \ --reward_model saves/Qwen1.5-7B/lora/sql_reward_model_v1 \ --dataset sql_ppo_prompts \ --template default \ --finetuning_type lora \ --lora_rank 8\ --lora_alpha 16\ --lora_target all \ --output_dir saves/Qwen1.5-7B/lora/sql_ppo_v1 \ --per_device_train_batch_size 1\ --gradient_accumulation_steps 4\ --lr_scheduler_type cosine \ --logging_steps 5\ --save_steps 100\ --learning_rate 1e-5 \ --num_train_epochs 1.0\ --plot_loss \ --fp16 

通过这个具体的训练命令,我们可以清晰地看到,相较于 DPO,PPO 流程不仅多了一个训练 RM 的步骤,而且在最终的对齐训练阶段,配置也更为复杂,需要管理的模型和路径更多。

  • DPO的“神来之笔”:
    DPO的作者们通过精妙的数学推导发现,整个复杂的PPO优化目标,可以等价地转换为一个简单的、类似SFT的分类损失函数核心思想 (高度简化):
    DPO认为,我们不需要一个显式的奖励模型。偏好数据 (chosen, rejected) 本身就隐式地定义了奖励。DPO的损失函数直接利用这一点,其目标是:增大模型生成 chosen 回答的概率,同时减小生成 rejected 回答的概率。更具体地说,DPO通过计算模型对 chosenrejected 回答的对数概率差,并将其与一个由参考模型(即SFT模型)计算出的隐式奖励进行对比,构建了一个简单的损失函数。训练过程就是最小化这个损失,直接将偏好“注入”到模型中。
  • DPO的压倒性优势:
特性传统RLHF (PPO)直接偏好优化 (DPO)
训练流程极其复杂 (SFT -> RM -> PPO)极其简单 (SFT -> DPO)
模型需求训练时需加载多个模型,内存占用巨大训练时只需加载策略模型和参考模型,内存友好
稳定性PPO训练不稳定,对超参数敏感,容易崩溃非常稳定,本质上是监督学习,收敛性好
效率采样过程耗时,训练速度慢无需采样,训练速度远快于PPO
效果效果好,但调试成本高效果与PPO相当甚至更好,且实现简单

结论: DPO以其简洁、稳定、高效的特性,已成为当今大模型对齐的首选方案,极大地降低了让模型更符合人类偏好的技术门槛。


6.2 DPO 的数据准备 (重难点)

DPO在数据层面延续了它的优雅——它直接复用RM阶段的偏好数据,无需任何额外处理。这是DPO流程简洁性的关键所在。

复用 RM 的数据 (Query, chosen, rejected)
  • 数据格式: DPO训练所需的数据格式与第五章介绍的奖励建模 (RM) 完全一致。每一条数据样本都是一个JSON对象,包含一个指令 (instruction/input),以及一个包含两个元素的 output 列表,分别代表“更受欢迎的回答”(chosen)和“不太受欢迎的回答”(rejected)。

实践示例:
假设我们有一个名为 dpo_data.jsonl 的文件:

{"instruction":"作为一名旅行规划师,请为一对希望进行为期一周的浪漫海岛游的夫妇推荐一个目的地,并简述理由。","output":[{"content":"我强烈推荐马尔代夫。那里有一流的水上别墅,提供极致的私密性和奢华体验。你们可以享受清澈的潟湖、白色的沙滩和丰富的水下活动,是蜜月和浪漫之旅的完美选择。"},{"content":"去马尔代夫吧,那儿不错。"}]}{"instruction":"如何修复一个漏水的水龙头?","output":[{"content":"修复漏水水龙头通常分几步:1. 关闭总水阀。2. 用扳手拧开水龙头手柄下的压盖螺母。3. 取出内部的垫圈或O形圈,这是最常见的磨损部件。4. 更换新的垫圈后,按相反顺序重新组装。如果问题依旧,可能需要更换整个阀芯。"},{"content":"你得先关掉水,然后把它拆开,换掉坏了的零件,再装回去。"}]}

在这个例子中,chosen 的回答明显比 rejected 的回答更详细、更专业、更有用。DPO的目标就是让模型学会这种“品味”。

--dataset 参数的设置
  • 在CLI或Web UI中指定:
    • CLI: --dataset my_dpo_dataset
    • Web UI: 在“数据集”下拉菜单中选择 my_dpo_dataset

注册 dataset_info.json: 与RM阶段一样,你必须在 data/dataset_info.json 中注册你的DPO数据集,并且必须设置 "ranking": true 来告诉Llama-factory这是一个偏好数据集。

// in data/dataset_info.json{// ... other datasets"my_dpo_dataset":{"file_name":"dpo_data.jsonl","ranking":true}}

数据质量是DPO成功的基石。高质量的偏好对应该具备:

  • 清晰的偏好差异: chosenrejected 之间的优劣应该是一目了然的。如果两个回答质量相近,会让模型感到困惑。
  • 多样性: 覆盖多样的指令类型、主题和偏好维度(如事实性、安全性、创造性、详细程度等)。
  • chosen回答的质量: chosen 回答本身也应该是高质量的。如果 chosen 回答也存在事实错误,模型在学习偏好的同时也会学到这些错误。

6.3 DPO 的训练配置 (重难点)

这是本章最核心、最关键的部分。DPO的配置有其独特性,理解这些配置是成功进行DPO训练的前提。

关键: DPO 训练需要 两个 模型 (训练中的模型 + SFT 后的参考模型)

正如6.1节理论部分所述,DPO的损失函数中,需要一个固定的参考模型 (Reference Model) 来衡量当前策略模型 (Policy Model) 的变化程度,以防止其偏离原始SFT模型太远。

  • 策略模型 (Policy Model):
    • 角色: 这是我们正在训练和优化的模型。它的参数会在每个训练步骤中被更新。
    • 起点: 策略模型的初始状态,必须是已经完成SFT的模型。我们不能用一个原始的基座模型来做DPO,因为它首先需要具备基本的指令跟随能力。
  • 参考模型 (Reference Model):
    • 角色: 这是一个权重被冻结、不参与训练的模型副本。它只用于在前向传播中计算 chosenrejected 回答的对数概率,为损失函数提供一个基准。
    • 来源: 参考模型就是SFT模型本身
  • Llama-factory 中的实现机制:
    Llama-factory 的设计非常巧妙,它简化了这个“双模型”的配置:
    1. 你通过 --model_name_or_path 参数,加载你已经训练好的SFT模型
    2. Llama-factory 在内部会用这个路径加载两次模型
      • 一次作为策略模型,并附加LoRA权重(如果你用LoRA的话),使其变为可训练状态。
      • 另一次作为参考模型,并将其权重完全冻结。
    3. 这样,你就无需手动管理两个模型的加载,框架会自动处理。
--dpo_beta 参数的实践意义

dpo_beta 是DPO训练中最重要的一个超参数

  • 是什么?beta 是DPO损失函数中,控制KL散度惩罚项权重的系数。KL散度衡量的是策略模型和参考模型在输出概率分布上的差异。
  • 实践意义 (调参关键): beta 的值决定了DPO训练的**“保守”程度**。
    • 较低的 beta (如 0.01, 0.05):
      • 含义: 对KL散度的惩罚较弱。模型会更“大胆”地去拟合偏好数据,即更专注于拉开 chosenrejected 的概率差距。
      • 优点: 可能在你的目标偏好上学得更充分,模型风格变化更明显。
      • 风险: 容易过拟合偏好,导致模型忘记了SFT阶段学到的通用语言能力。可能会生成一些符合偏好但重复、啰嗦或不自然的文本,这就是所谓的“KL塌陷”。
    • 较高的 beta (如 0.5, 1.0):
      • 含义: 对KL散度的惩罚很强。模型在学习偏好的同时,被一股强大的力量“拽”着,不允许它离SFT参考模型太远。
      • 优点: 训练更稳定,能很好地保持SFT模型的通用性和语言风格,在其基础上进行“微调”。
      • 风险: 可能学习偏好不充分,chosenrejected 之间的差异不够明显,模型提升有限。
  • 如何选择?
    • 黄金起点: 原始DPO论文和大量实践证明,beta = 0.1 是一个极其鲁棒和优秀的默认值。对于绝大多数任务,你都应该从 0.1 开始。
    • 调参建议:
      • 如果DPO训练后,你发现模型在偏好任务上表现很好,但通用对话能力下降,或者说话变得很奇怪,尝试增大 beta (如 0.2 or 0.3)。
      • 如果DPO训练后,你感觉模型和SFT版本相比没什么变化,提升不明显,可以尝试减小 beta (如 0.05),让它学得更“激进”一些。

6.4 实战:跑通一个 DPO 训练

现在,我们将所有理论知识串联起来,一步步完成一个完整的DPO流程。我们的目标是,在第五章SFT训练出的SQL生成模型的基础上,进一步通过DPO让它更偏爱格式规范、带有注释的SQL语句。

步骤 1:先 SFT 一个基础模型

这是DPO的绝对前提。我们必须先有一个具备基础能力的SFT模型。我们复用第五章的SFT脚本,并假设其输出保存在 saves/Qwen1.5-7B/lora/sql_generator_v1

SFT脚本 (train_sft_for_dpo.sh):

#!/bin/bash# (此脚本已在第五章运行过,这里仅作回顾) llamafactory-cli train \ --stage sft \ --do_train \ --model_name_or_path Qwen/Qwen1.5-7B-Chat \ --dataset sql_gen_custom \ --finetuning_type lora \ --output_dir saves/Qwen1.5-7B/lora/sql_generator_v1 \# ... 其他SFT参数 ... ```**关键产物**: `saves/Qwen1.5-7B/lora/sql_generator_v1` 文件夹,包含了LoRA适配器权重。 
步骤 2:使用该 SFT 模型作为起点来启动 DPO

现在,我们进入DPO阶段。

  • 脚本核心参数解读 (重中之重):
    • --stage dpo: 切换到DPO模式。这是启动DPO训练的开关,Llama-factory会自动加载DPO Trainer和对应的损失函数。
    • --model_name_or_path Qwen/Qwen1.5-7B-Chat: 注意!这里依然是原始的基座模型
    • --adapter_name_or_path saves/Qwen1.5-7B/lora/sql_generator_v1: 这才是DPO的真正起点。Llama-factory会先将这个SFT阶段训练好的LoRA适配器加载到基座模型上,形成完整的SFT模型。然后,以此为基础,创建策略模型和参考模型。
    • --learning_rate 1e-5: DPO的学习率通常需要设置得比SFT更小。因为偏好对齐是一个更精细的微调过程。1e-55e-6 是一个很好的范围。
    • --dpo_beta 0.1: 设置核心超参数 beta 为推荐的默认值 0.1
    • --output_dir: DPO训练产物的输出目录,不要和SFT的目录混淆。
  • 监控训练过程:
    当你运行此脚本后,观察终端输出的日志。除了 loss 之外,你应该重点关注以下几个指标:
    • rewards/chosen: 策略模型赋予 chosen 回答的平均奖励分数。
    • rewards/rejected: 策略模型赋予 rejected 回答的平均奖励分数。
    • rewards/accuracy: 关键指标。表示在当前batch中,模型正确地给予 chosen 回答比 rejected 回答更高分数的样本比例。一个健康的DPO训练,这个值应该稳定在50%以上,并逐渐提升,通常能达到70%~90%。
    • rewards/margins: chosenrejected 奖励分数的平均差值。这个值应该是正数并逐渐增大,表示模型正在成功地拉开好坏回答的差距。

DPO训练脚本 (train_dpo_sql.sh):

#!/bin/bashexportCUDA_VISIBLE_DEVICES="0" llamafactory-cli train \ --stage dpo \ --do_train \ --model_name_or_path Qwen/Qwen1.5-7B-Chat \ --adapter_name_or_path saves/Qwen1.5-7B/lora/sql_generator_v1 \ --dataset sql_dpo_custom \ --template default \ --finetuning_type lora \ --lora_rank 8\ --lora_alpha 16\ --lora_target all \ --output_dir saves/Qwen1.5-7B/lora/sql_dpo_v1 \ --per_device_train_batch_size 1\ --gradient_accumulation_steps 4\ --lr_scheduler_type cosine \ --logging_steps 5\ --save_steps 100\ --learning_rate 1e-5 \ --num_train_epochs 1.0\ --plot_loss \ --fp16 \ --dpo_beta 0.1

DPO数据准备:
假设我们创建了 dpo_sql_preference.jsonl,内容如下,并已注册为 sql_dpo_custom

{"instruction":"查询'用户表'中所有年龄大于30岁的用户的姓名和邮箱。","output":[{"content":"-- 查询30岁以上用户的核心信息\nSELECT \n name, \n email \nFROM \n user_table \nWHERE \n age > 30;"},{"content":"SELECT name, email FROM user_table WHERE age > 30;"}]}

这里,chosen 的回答包含了注释和更好的格式,是我们希望模型学习的偏好。

至此,你已经完整地掌握了从理论到实践的DPO全流程。通过先SFT再DPO的两步走策略,你可以将一个通用的语言模型,先塑造成一个特定领域的“专家”,再进一步教会它“品味”,使其回答不仅“正确”,而且“优秀”,更符合人类的期望和偏好。下一章,我们将讨论如何将我们辛辛苦苦训练出的模型(无论是SFT还是DPO的产物)真正地应用起来,包括模型合并、部署推理和评估。

Llama-factory 详细学习笔记 目录

以下是整个系列的8章目录,点击章节标题即可跳转阅读,可直接访问:

Read more

Openclaw高星开源框架:三省六部·用古代官制设计的 AI Agent 协作架构

Openclaw高星开源框架:三省六部·用古代官制设计的 AI Agent 协作架构

作者:cft0808 项目地址:https://github.com/cft0808/edict |许可:MIT 概述 三省六部·Edict 是一个基于中国古代官制设计的 AI 多 Agent 协作架构。它把唐朝以来运行了一千多年的三省六部制搬到了 AI 世界,创建了一套具有分权制衡、专职审核、完全可观测特性的 Agent 协作系统。 项目目前 6.9k+ Stars,581 Fork,Star 增长很快。 核心设计思想 问题:为什么大多数 Multi-Agent 框架不好用? 当前主流的多 Agent 框架(CrewAI、AutoGen、LangGraph)通常采用「自由对话」模式: Agent A

在家也能做 AI 导演!本地部署 Wan2.1 视频生成模型全攻略

在家也能做 AI 导演!本地部署 Wan2.1 视频生成模型全攻略

文章目录 * 前言 * 1.软件准备 * 1.1 ComfyUI * 1.2 文本编码器 * 1.3 VAE * 1.4 视频生成模型 * 2.整合配置 * 3. 本地运行测试 * 4. 公网使用Wan2.1模型生成视频 * 4.1 创建远程连接公网地址 * 5. 固定远程访问公网地址 * 总结 前言 Wan2.1 模型搭配 ComfyUI 框架,能实现文本转视频、图片转动画等功能,生成的视频质量可媲美专业工具,普通 PC 就能运行,特别适合自媒体创作者、短视频团队和 AI 爱好者快速制作动态内容,无需复杂技术背景也能上手,且完全开源免费,性价比很高。 使用时发现,选择模型版本要结合显卡配置:

Python + AI:打造你的智能害虫识别助手

Python + AI:打造你的智能害虫识别助手

Python + AI:打造你的智能害虫识别助手 在农业生产中,病虫害是影响作物产量和品质的“隐形杀手”。传统的害虫识别依赖人工巡查,不仅耗时耗力,还容易因经验不足导致误判、漏判。而随着智慧农业的普及,AI技术正成为破解这一难题的关键——今天,我们就用Python从零搭建一个智能害虫识别助手,让电脑替你“火眼金睛”辨害虫,轻松搞定农作物病虫害预警! 一、为什么要做这个项目? 智慧农业的核心是“精准、高效、低成本”,而害虫识别正是其中的典型场景: * 对农户:无需专业植保知识,拍照就能识别害虫种类,快速匹配防治方案; * 对开发者:这是一个“小而美”的实战项目,覆盖AI开发全流程,从数据处理到模型部署,学完就能落地; * 技术价值:融合Python、深度学习、Web部署,是入门AI+垂直领域应用的绝佳案例。 这个项目不需要你有深厚的AI功底,只要掌握Python基础,跟着步骤走,就能做出一个能实际使用的智能识别工具。 二、项目核心技术栈 先明确我们要用到的工具,都是行业主流、

OpenClaw国产平替来了!CoPaw个人助理告别复杂配置,新手10分钟上手,普通人也能薅爆国产AI羊毛

OpenClaw国产平替来了!CoPaw个人助理告别复杂配置,新手10分钟上手,普通人也能薅爆国产AI羊毛

第一章:CoPaw 是什么?国产 AI 数字搭档的核心魅力 现在市面上的 AI 智能助理不少,但要么门槛高得劝退普通人,要么功能单一没灵魂。而 CoPaw 不一样——它是通义实验室(阿里) 靠着 AgentScope 智能体生态做的国产 AI 数字搭档,既是 OpenClaw 的平替升级款,还把**「好用」** 和**「实用」** 拉满了,就算你不是技术出身,也能轻松拿捏专属智能助理。 跟传统 AI 工具比,CoPaw 最戳人的点就是既会干活又有温度: * 有长期记忆还懂你:能自定义专属人设,不管是称呼、性格还是相处模式,都由你说了算。系统会自动记着你的偏好、待办和重要决定,越用越合心意,再也不用面对冷冰冰的问答机器人; * 电脑杂活全包揽:重复又繁琐的活直接甩给它就行——定时清理桌面、查天气查股价、编辑