今天分享一个可运行的 DPO(Direct Preference Optimization)训练脚本,基于 Qwen2.5-7B-Instruct,用 LoRA 微调,并且包含详细注释,方便大家直接复用。
使用 ModelScope Swift 框架 (https://github.com/modelscope/ms-swift)
直接偏好优化 DPO (Direct Preference Optimization),单卡案例
原理详解
DPO是2023年提出的一种直接偏好优化方法,它的革命性在于无需训练独立的奖励模型,而是直接从人类偏好数据中学习。
核心思想
DPO的核心思想是将RLHF问题重新表述为一个分类问题。它直接利用偏好对比数据,通过最大化偏好回复的概率与非偏好回复概率的差值来优化模型。
训练脚本
#!/bin/bash
# Qwen2.5-7B-Instruct DPO 训练示例脚本
# 指定 GPU (单卡 24GB 显存)
export CUDA_VISIBLE_DEVICES=0
# 启动 RLHF 训练
swift rlhf \
--rlhf_type dpo \ # 选择对齐方法:DPO (Direct Preference Optimization)
--model Qwen/Qwen2.5-7B-Instruct \ # 使用 Qwen2.5-7B-Instruct 作为基座模型
--train_type lora \ # 训练方式:LoRA 微调,节省显存
--dataset hjh0119/shareAI-Llama3-DPO-zh-en-emoji \ # 偏好数据集(人类偏好数据格式:prompt / chosen / rejected)
--split_dataset_ratio 0.01 \ # 拆分 1% 数据作为验证集
--torch_dtype bfloat16 \ # 使用 bfloat16 提高显存利用率
--num_train_epochs 1 \ # 训练轮数(示例设置为 1,可根据需求调整)
--per_device_train_batch_size 1 \ # 单设备训练 batch size
--per_device_eval_batch_size 1 \ # 单设备评估 batch size
--learning_rate 1e-4 \ # 学习率
--lora_rank 8 \ # LoRA rank
--lora_alpha 32 \ # LoRA scaling 系数
--target_modules all-linear \ # 应用 LoRA 的模块(线性层)
--gradient_accumulation_steps 16 \ # 梯度累积,等效于更大 batch size
--eval_steps 50 \ # 每 50 step 评估一次
--save_steps 50 \ # 每 50 step 保存一次 checkpoint
--save_total_limit 2 \ # 最多保存 2 个 checkpoint,避免磁盘占满
--logging_steps 5 \ # 每 5 step 打印一次日志
--max_length 2048 \ # 输入序列最大长度
--output_dir output/dpo-qwen2.5 \ # 模型保存路径
--warmup_ratio 0.05 \ # 学习率预热比例
--dataloader_num_workers 4 \ # 数据加载线程数
--dataset_num_proc 4 \ # 数据集处理线程数
--rpo_alpha 0.1 # RPO/DPO 正则化参数 (对比项,保持分布稳定)
数据要求
DPO 训练需要 人类偏好数据,格式为:
{
"prompt": "请写一首关于春天的诗",
"chosen": "春风吹绿了江南的柳,花开满城映日辉。",
"rejected": "春天来了,天气变暖了。"
}
字段解释
- prompt:模型输入(问题/任务)
- chosen:优选答案(人类更喜欢)
- rejected:劣选答案(人类不喜欢)
数据集 hjh0119/shareAI-Llama3-DPO-zh-en-emoji 已经是这种格式,可以直接用。
Github地址:https://github.com/CrazyBoyM/llama3-Chinese-chat
huggingface地址:https://huggingface.co/datasets/shareAI/DPO-zh-en-emoji
Modelscope:https://modelscope.cn/datasets/hjh0119/shareAI-Llama3-DPO-zh-en-emoji
运行方法
vim train_dpo_qwen2.5.sh
chmod +x train_dpo_qwen2.5.sh
./train_dpo_qwen2.5.sh
训练完成后,模型会保存在:
output/dpo-qwen2.5/
分组偏好优化 GRPO (Group Relative Policy Optimization),多卡案例
原理详解
GRPO是针对PPO的一种改进方法,主要解决PPO在处理多样性和探索性方面的不足。它通过引入群组相对比较机制来优化策略。
核心思想
GRPO的核心思想是在一个batch内的样本之间进行相对比较,而不是绝对的奖励优化。这种方法可以更好地处理奖励的分布偏差问题。
训练脚本
#!/bin/bash
# Qwen2.5-7B-Instruct GRPO 训练脚本
# 使用 ModelScope Swift 框架 + vLLM rollout server
# 使用 6 张 GPU (训练用),剩余 GPU 可做 rollout
export CUDA_VISIBLE_DEVICES=0,1,2,3,4,5
export NPROC_PER_NODE=6 # 与训练卡数对应
swift rlhf \
--rlhf_type grpo \ # RLHF 算法:GRPO
--model Qwen/Qwen2.5-7B-Instruct \ # 基座模型
--reward_funcs accuracy \ # 奖励函数 (示例:accuracy,可换成别的 reward_fn)
--use_vllm true \ # 使用 vLLM 进行 rollout
--vllm_mode server \ # rollout 模式:server 模式(需要预先启动 vLLM 服务)
--vllm_server_host 127.0.0.1 \ # vLLM 服务器地址
--vllm_server_port 8000 \ # vLLM 服务器端口
--train_type full \ # 全参数训练 (也可改成 lora)
--torch_dtype bfloat16 \ # 使用 bfloat16 节省显存
--dataset AI-MO/NuminaMath-TIR#1000 \ # 数据集 (数学 reasoning 示例)
--split_dataset_ratio 0 \ # 不划分验证集
--max_completion_length 2048 \ # 模型生成的最大长度
--num_train_epochs 3 \ # 训练 3 个 epoch
--per_device_train_batch_size 2 \ # 每卡 batch size
--learning_rate 1e-6 \ # 学习率
--gradient_accumulation_steps 2 \ # 梯度累积
--save_total_limit 2 \ # 最多保留 2 个 checkpoint
--logging_steps 1 \ # 每步打印日志
--warmup_ratio 0.05 \ # 预热
--dataloader_num_workers 4 \ # 数据加载线程数
--dataset_num_proc 4 \ # 数据预处理线程数
--num_generations 8 \ # 每个 prompt rollout 生成 8 个样本
--temperature 1.0 \ # rollout 采样温度
--top_p 0.9 \ # nucleus sampling
--top_k 50 \ # top-k 采样
--deepspeed zero2 \ # DeepSpeed ZeRO-2 分布式优化
--log_completions true \ # 记录 rollout 的完整输出
--num_iterations 1 \ # 迭代次数 (可增加)
--report_to tensorboard wandb \ # 日志上报 (支持 TensorBoard / WandB)
--beta 0.04 # KL 惩罚系数 (防止过度偏离参考模型)
数据要求
[
{
"prompt": "计算:7 + 5 等于多少?",
"response": "12",
"ground_truth": "12"
},
{
"prompt": "计算:9 - 4 等于多少?",
"response": "5",
"ground_truth": "5"
},
{
"prompt": "解方程:2x = 10,求 x。",
"response": "5",
"ground_truth": "5"
},
{
"prompt": "如果一个三角形三边分别是 3, 4, 5,它的面积是多少?",
"response": "6",
"ground_truth": "6"
},
{
"prompt": "化简:(x^2 - 1) / (x - 1)",
"response": "x + 1",
"ground_truth": "x + 1"
},
{
"prompt": "计算:3 × 8 等于多少?",
"response": "24",
"ground_truth": "24"
},
{
"prompt": "小红有 10 支铅笔,送给同学 3 支,还剩多少?",
"response": "7",
"ground_truth": "7"
},
{
"prompt": "计算平方根:√81",
"response": "9",
"ground_truth": "9"
},
{
"prompt": "解方程:x + 15 = 20,求 x。",
"response": "5",
"ground_truth": "5"
},
{
"prompt": "计算积分:∫ 2x dx",
"response": "x^2 + C",
"ground_truth": "x^2 + C"
}
]
字段解释
prompt:提示,模型要解决的问题(数学题/逻辑推理任务)
response:模型生成的输出(训练时会 rollout 多个 response)
ground_truth :标准答案,用于 reward 函数(例如 accuracy)计算分数
运行方法
1、启动 vLLM rollout server(在另外两张 GPU 上跑):
CUDA_VISIBLE_DEVICES=6,7 \
swift rollout \
--model Qwen/Qwen2.5-7B-Instruct \
--data_parallel_size 2
这会在 127.0.0.1:8000 上提供 rollout 服务。
2、运行 GRPO 训练(6 卡训练,自动调用 rollout server):
chmod +x train_grpo_qwen2.5.sh
./train_grpo_qwen2.5.sh
训练完成后,模型和日志会保存在:
output/grpo-qwen2.5/