DPO、GRPO强化学习人类偏好对齐:Qwen2.5模型 MS-Swift框架DPO、GRPO训练-实战案例

发布于:2025-09-13 ⋅ 阅读:(17) ⋅ 点赞:(0)

今天分享一个可运行的 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/