diff --git a/docs/mindformers/docs/source_zh_cn/usage/direct_preference_opitimization.md b/docs/mindformers/docs/source_zh_cn/usage/direct_preference_opitimization.md new file mode 100644 index 0000000000000000000000000000000000000000..068d04c8f4010fb9409476d18e3cc4428ecd392f --- /dev/null +++ b/docs/mindformers/docs/source_zh_cn/usage/direct_preference_opitimization.md @@ -0,0 +1,209 @@ +# DPO训练 + +## 概述 + +直接偏好优化(Direct Preference Optimization,DPO)是一种在大语言模型训练中用于优化模型偏好的方法。相较传统的强化学习方法,DPO 通过人类偏好数据进行模型优化,从而提高生成内容的质量,使其更符合人类偏好。 + +## DPO训练的基本操作流程 + +结合实际操作,DPO训练的基本流程可以分解为以下步骤: + +1. **选择模型架构:** + 根据任务需求和计算资源,选择合适的模型架构来构建DPO训练模型。 +2. **下载模型权重:** + 针对选择的预训练模型,可以从HuggingFace模型库中下载训练权重。 +3. **数据集准备:** + DPO需要一个偏好标注的数据集,通常包括prompt(用户输入)、preferred response(人类更喜欢的答案)和rejected response(人类不喜欢的答案)。数据来源可以是人工标注、RLHF训练中采样的偏好数据或已有对齐数据集。 +4. **执行DPO训练任务:** + 使用DPO任务的数据集对微调模型进行训练,梯度下降等优化算法来调整模型参数,以最小化对比损失函数。在训练过程中,模型将学习如何根据人类的偏好来调整其生成策略。DPO训练任务完成后,便可以得到新的模型。 + +### 选择DPO训练模型 + +MindSpore Transformers目前已经支持业界主流大模型,该实践流程选择Llama2-7B模型DPO训练为例。 + +### 下载模型权重 + +MindSpore Transformers提供已经转换完成的预训练权重、词表文件用于预训练、微调、DPO和推理,用户也可以下载HuggingFace官方权重使用。 + +词表下载链接:[tokenizer.model](https://ascend-repo-modelzoo.obs.cn-east-2.myhuaweicloud.com/MindFormers/llama2/tokenizer.model) + +| 模型名称 | MindSpore权重 | HuggingFace权重 | +|:----------|:------------------------------------------------------------------------------------------------------------:| :---------------------------------------------------------------------------------------------: | +| Llama2-7B | [Link](https://ascend-repo-modelzoo.obs.cn-east-2.myhuaweicloud.com/MindFormers/llama2/llama2_7b.ckpt) | [Link](https://huggingface.co/meta-llama/Llama-2-7b-hf) | + +> Llama2的所有权重都需要通过向Meta[提交申请](https://ai.meta.com/resources/models-and-libraries/llama-downloads)来获取,如有需要请自行申请。 + + +### 数据集准备 + +MindFormers提供开源的中文大模型价值观比较数据集`CValues-Comparison`作为[DPO](#DPO)数据集。 + +| 数据集名称 | 适用阶段 | 下载链接 | +|:--------------------|:----------:|:------------------------------------------------------------------------------------------:| +| CValues-Comparison | DPO | [Link](https://www.modelscope.cn/datasets/iic/CValues-Comparison/file/view/master?id=4279&status=2&fileName=train.jsonl) | + +**DPO 数据预处理** + +执行MindSpore Transformers中的[dpo_preprocess.py脚本](https://gitee.com/mindspore/mindformers/blob/dev/toolkit/data_preprocess/dpo_preprocess.py),将数据集转换为多轮对话格式。 + +#### 基本用法 + +```bash +python dpo_preprocess.py --src <源数据文件> --dst <输出文件> --vocab_file --tokenizer_type +``` + +#### 完整参数说明 + +| 参数 | 说明 | +| --- | --- | +| `--src` | 源数据文件路径(JSON或JSONL格式) | +| `--dst` | 输出MindRecord文件路径 | +| `--config` | 模型配置文件路径 | +| `--seq_len` | 最大序列长度,默认1024 | +| `--dataset_type` | 数据集类型,可选'dpo'或'cvalues',默认'dpo' | +| `--file_partition` | MindRecord文件分片数量,默认1 | +| `--register_path` | 注册外部模块或API的路径 | +| `--pack` | 是否启用数据打包功能,将多个样本打包成一个序列 | +| `--mp` | 模型并行大小,用于序列对齐,默认1 | +| `--pack_num` | 每个序列打包的样本数量 | +| `--input_sliced_sig` | 是否使用切片输入生成标签 | +| `--vocab_file` | tokenizer词汇表文件路径,默认'./tokenizer.model' | +| `--pad_token` | 填充token,默认'<\|reserved_special_token_0\|>' | +| `--tokenizer_type` | 使用的tokenizer类型,默认'Llama3Tokenizer' | +| `--processor_type` | tokenizer处理器类型,默认'LlamaProcessor' | +| `--auto_register` | 自动注册的MindFormer组件,默认'llama3_1.Llama3Tokenizer' | + +#### 示例 + +##### 处理标准DPO数据集 + +```bash +python dpo_preprocess.py --src ./data/dpo_data.json --dst dpo_mindrecord.mindrecord --vocab_file ./tokenizer.model --seq_len 2048 --dataset_type dpo +``` + +##### 处理具有打包功能的数据集 + +```bash +python dpo_preprocess.py --src ./data/cvalues_data.jsonl --dst cvalues_packed.mindrecord --vocab_file ./tokenizer.model --dataset_type cvalues --pack --mp 2 --pack_num 4 +``` + +### pack数据处理逻辑 + +pack处理的主要步骤如下: + +1. **样本长度计算**:计算所有样本的平均长度,确定每个打包序列可容纳的样本数量。超过这个长度的样本将被截断 +2. **样本分组**:将样本按照长度进行分组,确保打包后的序列长度相近 +3. **序列打包**:将分组后的样本打包成固定大小的序列 +4. **位置信息处理**:为打包的序列添加位置索引信息,便于模型区分不同样本 +5. **注意力掩码处理**:生成对应的注意力掩码,确保模型只关注相关部分 +6. **数据对齐**:确保打包后的序列长度能被模型并行大小(mp)整除,必要时进行调整 + +使用打包功能时,脚本会自动计算的打包数量,也可以通过`--pack_num`参数手动指定。 + + +### 执行DPO训练任务 + +#### 单机训练 + +以Llama2-7B为例,执行msrun启动脚本,进行8卡分布式训练,启动命令如下: + +```bash +bash scripts/msrun_launcher.sh "run_mindformer.py \ +--config configs/model/dpo.yaml \ +--train_dataset_dir /{path}/dpo.mindrecord \ +--load_checkpoint /{path}/model.ckpt \ +--use_parallel True \ +--run_mode finetune" 8 +``` + +参数说明: + +```commandline +config: 模型的配置文件,文件在MindSpore Transformers代码仓中config目录下 +load_checkpoint: checkpoint文件的路径 +train_dataset_dir: 训练数据集路径 +use_parallel: 是否开启并行 +run_mode: 运行模式,train:训练,finetune:微调,predict:推理 +``` + +任务执行完成后,在mindformers/output目录下,会生成checkpoint文件夹,同时模型文件会保存在该文件夹下。 + +#### 多机训练 + +多机多卡DPO任务与启动预训练类似,可参考[多机多卡的预训练命令](https://www.mindspore.cn/mindformers/docs/zh-CN/dev/usage/pre_training.html#%E5%A4%9A%E6%9C%BA%E8%AE%AD%E7%BB%83),并对命令进行如下修改: + +1. 增加启动脚本入参`--load_checkpoint /{path}/llama2_7b.ckpt`加载预训练权重。 +2. 设置启动脚本中的`--train_dataset_dir /{path}/alpaca-fastchat4096.mindrecord`加载微调数据集。 +3. 设置启动脚本中的`--run_mode finetune`,run_mode表示运行模式,train:训练,finetune:微调,predict:推理。 + +任务执行完成后,在mindformers/output目录下,会生成checkpoint文件夹,同时模型文件会保存在该文件夹下。 + +以Llama2-7B为例,执行msrun启动脚本,进行8机分布式训练,启动命令如下: + +```bash +bash scripts/msrun_launcher.sh "run_mindformer.py \ +--config configs/model/dpo.yaml \ +--train_dataset_dir /{path}/dpo.mindrecord \ +--load_checkpoint /{path}/model.ckpt \ +--use_parallel True \ +--run_mode finetune" \ +64 8 {主节点ip} 8118 {node_num} output/msrun_log False 300 +``` + +### 示例配置文件(YAML) + +完整的YAML配置文件可以通过以下链接访问:[Llama2 DPO训练 YAML 文件](https://gitee.com/mindspore/mindformers/blob/dev/configs/llama2/dpo_llama2_7b.yaml)。 + +```yaml +# model config +model: + model_config: + input_sliced_sig: False + rl_config: + rl_type: dpo + # configuration of dpo + dpo_alpha: 1.0 + dpo_beta: 1.0 + +# 参数说明 +input_sliced_sig: 数据集是否处理成模型的seq_length大小,默认为True +rl_type: 模型类别,会根据字符映射到相应强化学习算法 +dpo_alpha: 该参数控制微调模型的关注程度,alpha越小,模型训练越忽略微调模型 +dpo_beta: 该参数控制ref模型的关注程度,beta越小,模型训练越忽略ref模型 +``` + +在`train_dataset`中的相关配置,如下所示: + +```yaml +#使用非packing数据集 +train_dataset: + input_columns: ["chosen_attention_mask", "chosen_input_ids", "chosen_labels","chosen_loss_mask", "rejected_attention_mask", "rejected_input_ids", "rejected_labels", "rejected_loss_mask"] + output_columns: ["chosen_attention_mask", "chosen_input_ids", "chosen_labels","chosen_loss_mask", "rejected_attention_mask", "rejected_input_ids", "rejected_labels", "rejected_loss_mask"] + construct_args_key: ["chosen_attention_mask", "chosen_input_ids", "chosen_labels","chosen_loss_mask", "rejected_attention_mask", "rejected_input_ids", "rejected_labels", "rejected_loss_mask"] + use_data_packing: False + +#使用packing数据集 +train_dataset: + input_columns: ["chosen_attention_mask","chosen_index_packed","chosen_input_ids", "chosen_labels","chosen_lens","chosen_loss_mask", "rejected_attention_mask", "rejected_index_packed", "rejected_input_ids", "rejected_labels", "rejected_lens", "rejected_loss_mask"] + output_columns: ["chosen_attention_mask","chosen_index_packed","chosen_input_ids", "chosen_labels","chosen_lens","chosen_loss_mask", "rejected_attention_mask", "rejected_index_packed", "rejected_input_ids", "rejected_labels", "rejected_lens", "rejected_loss_mask"] + construct_args_key: ["chosen_attention_mask","chosen_index_packed","chosen_input_ids", "chosen_labels","chosen_lens","chosen_loss_mask", "rejected_attention_mask", "rejected_index_packed", "rejected_input_ids", "rejected_labels", "rejected_lens", "rejected_loss_mask"] + use_data_packing: True + packed_num: 8 + +# 参数说明 +input_columns: 输入数据列 +output_columns: 输出数据列 +construct_args_key: 指定key值返回数据列 +use_data_packinga: 是否使用packing数据集,默认为False +packed_num: 每个打包单元中包含的数据样本的数量 +``` + +在`train_dataset_task`中的相关配置,如下所示: + +```yaml +train_dataset_task: + type: DPODataset + +# 参数说明 +type: 数据处理类 +```