diff --git a/docs/mindspore/source_zh_cn/mindformers/function/weight_conversion.md b/docs/mindspore/source_zh_cn/mindformers/function/weight_conversion.md index a2c2fe74fc2425b726925c4bbe9c639d8bac69ee..889f901f0ffbc65c60710e94a9d91e6d9db5bbb9 100644 --- a/docs/mindspore/source_zh_cn/mindformers/function/weight_conversion.md +++ b/docs/mindspore/source_zh_cn/mindformers/function/weight_conversion.md @@ -1,3 +1,478 @@ # 权重转换功能 +## 概述 + +在当前的分布式训练和推理环境中,当预训练权重与分布式策略不匹配时,需要进行**预训练权重转换**,以适应对应的分布式策略。 + +## 前期准备 + +### 数据集下载 + +MindFormers提供**Wiki103**作为[预训练](https://gitee.com/mindspore/mindformers/blob/r1.2.0/research/llama3/llama3.md#%E9%A2%84%E8%AE%AD%E7%BB%83)数据集。 + +| 数据集名称 | 适用模型 | 适用阶段 | 下载链接 | +|:-----------|:------------------------:|:--------:|:--------------------------------------------------------------------------------------------------------------------------:| +| Wiki103 | llama3-8b
llama3-70b | Pretrain | [Link](https://gitee.com/link?target=https%3A%2F%2Fdagshub.com%2FDagsHub%2FWIkiText-103%2Fsrc%2Fmain%2Fdataset%2Ftokens) | + +### 模型权重下载 + +MindFormers暂时没有提供权重,用户可以下载HuggingFace官方权重,经过[模型权重转换](https://gitee.com/mindspore/mindformers/blob/r1.2.0/research/llama3/llama3.md#%E6%A8%A1%E5%9E%8B%E6%9D%83%E9%87%8D%E8%BD%AC%E6%8D%A2)后进行使用。 + +词表下载链接:[tokenizer.model](https://gitee.com/link?target=https%3A%2F%2Fhuggingface.co%2Fmeta-llama%2FMeta-Llama-3-8B) + +| 模型名称 | MindSpore权重 | HuggingFace权重 | +|:-----------|:-------------:|:-----------------------------------------------------------------------------------------------:| +| Llama3-8B | \\ | [Link](https://gitee.com/link?target=https%3A%2F%2Fhuggingface.co%2Fmeta-llama%2FMeta-Llama-3-8B) | +| Llama3-70B | \\ | [Link](https://gitee.com/link?target=https%3A%2F%2Fhuggingface.co%2Fmeta-llama%2FMeta-Llama-3-70B) | + +### 模型权重转换 + +下载完成后,运行`mindformers/convert_weight.py`转换脚本,将HuggingFace的权重转换为完整的ckpt权重。 + +```bash +python convert_weight.py --model llama --input_path TORCH_CKPT_DIR --output_path {path}/MS_CKPT_NAME --dtype bf16 +``` + +#### 参数说明 + +- **model**: 模型名称 +- **input_path**: 下载HuggingFace权重的文件夹路径 +- **output_path**: 转换后的MindSpore权重文件保存路径 +- **dtype**: 转换权重的精度 + +## 自动转换 + +### 参数说明 + +**自动权重转换**相关参数说明如下: + +| 参数名称 | 描述 | +| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| load_checkpoint | 预加载权重的绝对路径或文件夹路径。
- 如果是完整权重,则填写绝对路径;
- 如果是分布式权重,则填写文件夹路径,分布式权重须按照`model_dir/rank_x/xxx.ckpt`格式存放,文件夹路径填写为`model_dir`。
**如果rank_x文件夹下存在多个ckpt,将会使用文件名默认排序最后的ckpt文件用于转换。** | +| src_strategy | 预加载权重对应的分布式策略文件路径。
- 如果预加载权重是完整权重,则**不填写**;
- 如果预加载权重是分布式权重,且预加载权重保存时使用了流水线并行,则填写**合并的策略文件路径**或**分布式策略文件夹路径**;
- 如果预加载权重是分布式权重,且预加载权重保存时未使用流水线并行,则填写任一**ckpt_strategy_rank_x.ckpt**路径; | +| auto_trans_ckpt | 权重自动转换开关,为True开启,默认False。 | +| transform_process_num | 权重自动转换使用的进程数,默认为1。
- 如果transform_process_num = 1,使用**单进程转换**,转换时只有rank_0负责权重转换,其它进程等待rank_0转换结束;
- 如果transform_process_num > 1,使用**多进程转换**,比如8卡任务,transform_process_num=2时,转换时rank_0负责rank_0/1/2/3切片权重的转换,rank_4负责rank_4/5/6/7切片权重的转换,其它进程等待rank_0/4转换结束;
**注意**:
① transform_process_num越大,转换时间越短,**转换所占用的host内存越大**;当出现host侧内存不足时,需要减少transform_process_num。
② transform_process_num必须能够整除NPU卡数,且最大不得超过NPU卡数。 | +| transform_by_rank | 是否使用mindspore.transform_checkpoint_by_rank接口做权重转换。
- transform_process_num > 1时,自动设置为`True`;
- transform_process_num = 1时,如果目标权重为分布式权重,则循环调用mindspore.transform_checkpoint_by_rank串行转换每一个rank切片权重。
- transform_process_num = 1时,如果目标权重为完整权重,则自动设置为`False`,使用mindspore.transform_checkpoints接口做权重转换; | + +### 单卡自动转换为多卡 + +**案例描述**:使用前期准备下载的完整权重,转换为8卡分布式权重进行训练。 + +```yaml +# 配置预训练权重路径,填写权重文件路径 +load_checkpoint: "/worker/llama3_8b/llama3_8b.ckpt" + +# 打开权重自动转换开关 +auto_trans_ckpt: True + +# 配置数据集 +train_dataset: &train_dataset + data_loader: + type: MindDataset + dataset_dir: "/worker/dataset/wiki103/" + shuffle: True + +# 配置8卡分布式策略,以dp=2,mp=2,pp=2为例 +parallel_config: + data_parallel: 2 + model_parallel: 2 + pipeline_stage: 2 + micro_batch_num: 2 + +# 修改模型配置 +model: + model_config: + seq_length: 512 + num_layers: 2 +``` + +### 多卡自动转换为多卡 + +**案例描述**:使用单卡自动转换为多卡中保存的8卡分布式权重,转换为4卡分布式权重进行训练。 + +```yaml +# 配置预训练权重路径,填写分布式权重文件夹路径model_dir,权重按照model_dir/rank_x/xxx.ckpt格式存放 +load_checkpoint: "/worker/checkpoint/llama3-8b-2layer-dp2mp2pp2" + +# 配置分布式策略文件路径 +src_strategy_path_or_dir: "/worker/checkpoint/llama3-8b-2layer-dp2mp2pp2/strategy/merged_ckpt_strategy.ckpt" + +# 设置auto_trans_ckpt为True +auto_trans_ckpt: True + +# 设置数据集 +train_dataset: &train_dataset + data_loader: + type: MindDataset + dataset_dir: "/worker/dataset/wiki103/" + shuffle: True + +# 4卡分布式配置参考 +parallel_config: + data_parallel: 1 + model_parallel: 2 + pipeline_stage: 2 + micro_batch_num: 2 + vocab_emb_dp: True + gradient_aggregation_group: 4 +# when model parallel is greater than 1, we can set micro_batch_interleave_num=2, that may accelerate the train process. +micro_batch_interleave_num: 1 +``` + +### 多卡自动转换为单卡 + +**案例描述**:使用多卡自动转换为多卡得到的4卡分布式权重,合并为完整权重,**该场景仅支持单进程转换**。 + +```yaml +# 配置权重路径,填写分布式权重文件夹路径model_dir,权重按照model_dir/rank_x/xxx.ckpt格式存放 +load_checkpoint: "/worker/checkpoint/llam3-8b-2layer-dp1mp2pp2" + +# 配置分布式策略文件路径 +src_strategy_path_or_dir: "/worker/checkpoint/llama3-8b-2layer-dp1mp2pp2/strategy/ + +merged_ckpt_strategy.ckpt" + +# 设置auto_trans_ckpt为True +auto_trans_ckpt: True + +# 设置use_parallel为False +use_parallel: False + +# 设置run_mode为predict +run_mode: 'predict' + +# 配置词表路径(如果配置文件没有vocab_file关键字请自行补上) +processor: + tokenizer: + vocab_file: "/worker/checkpoint/llama3-8b-2layer/tokenizer.model" +``` + +### 注意事项 + +- 若您要开启**多进程转换**(`所有场景均一致`),额外配置`transform_process_num`参数,例如: + + ```yaml + # 设置参与权重转换的进程数量为2 + transform_process_num: 2 + ``` + +- 请注意,多进程转换时需考虑实际内存的使用情况。如果发生内存溢出,建议适当降低进程数量。 +- 开启**自动权重转换**后,系统将首先删除`output`目录下的旧`strategy`和`transformed_checkpoint`文件夹,并保存当前任务的输出结果。因此,建议在转换任务结束后,将`strategy`和`transformed_checkpoint`文件夹**移动到自定义目录**,以避免后续操作中被误删。 +- 分布式策略文件将保存在`output/strategy`文件夹下。如果开启了**流水线并行**,系统会自动合并所有的`ckpt_strategy_rank_x.ckpt`文件,生成`merged_ckpt_strategy.ckpt`。若未开启流水线并行,则不会进行合并操作。 + +## 离线转换 + +### 参数说明 + +**离线权重转换**相关参数说明如下: + +| 参数名称 | 描述 | +| ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| src_checkpoint | 源权重的绝对路径或文件夹路径。
- 如果是​**完整权重**​,则填写​**绝对路径**​;
- 如果是​**分布式权重**​,则填写​**文件夹路径**​,分布式权重须按照`model_dir/rank_x/xxx.ckpt`格式存放,文件夹路径填写为`model_dir`。
**如果rank_x文件夹下存在多个ckpt,将会使用文件名默认排序最后的ckpt文件用于转换。** | +| src_strategy | 源权重对应的分布式策略文件路径。
- 如果是完整权重,则​**不填写**​;
- 如果是分布式权重,且使用了流水线并行,则填写**合并的策略文件路径**或​**分布式策略文件夹路径**​;
- 如果是分布式权重,且未使用流水线并行,则填写任一**ckpt_strategy_rank_x.ckpt**路径; | +| dst_checkpoint | 保存目标权重的文件夹路径。 | +| dst_strategy | 目标权重对应的分布式策略文件路径,分布式权重的策略文件参考[获取分布式策略文件](https://mindformers.readthedocs.io/zh-cn/latest/docs/feature_cards/Transform_Ckpt.html#%E8%8E%B7%E5%8F%96%E5%88%86%E5%B8%83%E5%BC%8F%E7%AD%96%E7%95%A5%E6%96%87%E4%BB%B6)小节获取。
- 如果是完整权重,则​**不填写**​;
- 如果是分布式权重,且使用了流水线并行,则填写**合并的策略文件路径**或​**分布式策略文件夹路径**​;
- 如果是分布式权重,且未使用流水线并行,则填写任一**ckpt_strategy_rank_x.ckpt**路径; | +| prefix | 目标权重保存的前缀名,权重保存为”{prefix}rank_x.ckpt”,默认”checkpoint_”。 | +| world_size | 目标权重的切片总数,一般等于dp \* mp \* pp。 | +| process_num | 离线权重转换使用的进程数,默认为1。
- 如果process_num = 1,使用​**单进程转换**​;
- 如果process_num > 1,使用​**多进程转换**​,比如转换的目标权重为8卡分布式权重,process_num=2时,会启动两个进程分别负责rank_0/1/2/3和rank_4/5/6/7切片权重的转换; | + +### 单进程转换 + +**案例描述:** 使用前期准备下载的完整权重,转换为8卡分布式权重。 + +#### 参数配置 + +```yaml +# 打开策略文件保存开关 +only_save_strategy: True + +# 配置数据集 +train_dataset: &train_dataset + data_loader: + type: MindDataset + dataset_dir: "/worker/dataset/wiki103/" + shuffle: True + +# 配置8卡分布式策略,以dp=2,mp=2,pp=2为例 +parallel_config: + data_parallel: 2 + model_parallel: 2 + pipeline_stage: 2 + micro_batch_num: 2 + +# 修改模型配置 +model: + model_config: + seq_length: 512 + num_layers: 2 +``` + +#### 运行命令 + +开启流水线并行,`dst_strategy`使用文件夹路径。 + +```bash +python transform_checkpoint.py \ + --src_checkpoint=/worker/checkpoint/llama3-8b-2layer/rank_0/llama3_8b.ckpt \ + --dst_checkpoint=/worker/transform_ckpt/llama3_8b_1to8/ \ + --dst_strategy=/worker/mindformers/output/strategy/ +``` + +### 多进程转换 + +```bash +# 使用2个进程转换 +bash transform_checkpoint.sh \ + /worker/checkpoint/llam3-8b-2layer/rank_0/llama3_8b.ckpt \ + None \ + /worker/transform_ckpt/llama3_8b_1to8/ \ + /worker/mindformers/output/strategy/ \ + 8 2 +``` + +## 特殊场景 + +### 物理机多机多卡训练 + +大规模模型通常需要通过多台服务器组成的集群进行训练。在这种多机多卡的训练环境下,涉及到预训练权重的加载和转换问题。本文将根据服务器之间是否存在共享盘,分别描述在不同场景下进行多机多卡训练的流程,以两台服务器、16卡训练为例进行说明。 + +#### 场景一:服务器之间有共享盘 + +在服务器之间有共享盘的场景下,可以使用 MindFormers 的自动权重转换功能进行多机多卡训练。假设 `/data` 为服务器的共享盘,且 MindFormers 的工程代码位于 `/data/mindformers` 路径下。 + +##### 1. 单进程转换 + +在单进程转换模式下,只需在配置文件中配置预训练权重的路径并开启自动权重转换即可。 + +**参数配置:** + +```yaml +# 配置预训练权重路径,填写权重文件的绝对路径 +load_checkpoint: "/worker/checkpoint/llama3-8b/rank_0/llama3_8b.ckpt" + +# 设置 auto_trans_ckpt 为 True 开启自动权重转换 +auto_trans_ckpt: True + +# 配置数据集路径 +train_dataset: &train_dataset + data_loader: + type: MindDataset + dataset_dir: "/worker/dataset/wiki103/" + shuffle: True + +# 配置16卡分布式策略(仅供参考) +parallel_config: + data_parallel: 2 + model_parallel: 4 + pipeline_stage: 2 + micro_batch_num: 2 + vocab_emb_dp: True + gradient_aggregation_group: 4 + micro_batch_interleave_num: 1 +``` + +**启动任务:** + +```bash +# 第一台服务器(主节点) +bash scripts/msrun_launcher.sh "run_mindformer.py \ + --config {CONFIG_PATH} \ + --run_mode train" \ + 16 8 ${ip} ${port} 0 output/msrun_log False 300 +# 第二台服务器(子节点) +bash scripts/msrun_launcher.sh "run_mindformer.py \ + --config {CONFIG_PATH} \ + --run_mode train" \ + 16 8 ${ip} ${port} 1 output/msrun_log False 300 +``` + +##### 2. 多进程转换(可选) + +若需要加速权重转换过程,可以选择多进程转换模式,通过配置 `transform_process_num` 参数实现。 + +**参数配置:** + +```yaml +# 使用2个进程进行转换 +transform_process_num: 2 +``` + +#### 场景二:服务器之间无共享盘 + +在服务器之间无共享盘的情况下,需要使用离线权重转换工具进行多机多卡训练。以下步骤描述了如何进行离线权重转换,并启动多机 + +多卡训练任务。 + +##### 1. 获取分布式策略文件 + +在进行离线权重转换前,首先需要获取各节点的分布式策略文件。 + +**参数配置:** + +```yaml +# 设置 only_save_strategy 为 True 以获取分布式策略文件 +only_save_strategy: True + +# 配置数据集路径 +train_dataset: &train_dataset + data_loader: + type: MindDataset + dataset_dir: "/worker/dataset/wikitext_2048/" + shuffle: True + +# 配置16卡分布式策略(仅供参考) +parallel_config: + data_parallel: 2 + model_parallel: 4 + pipeline_stage: 2 + micro_batch_num: 2 + vocab_emb_dp: True + gradient_aggregation_group: 4 + micro_batch_interleave_num: 1 +``` + +各节点的策略文件将分别保存在各自的`output/strategy`目录中。例如,节点0将保存`ckpt_strategy_rank_0-7.ckpt`文件,节点1将保存`ckpt_strategy_rank_8-15.ckpt`文件。随后,需将所有节点的策略文件集中到同一台服务器上,以便进行后续操作。 + +##### 2. 离线权重转换 + +在保存有所有策略文件的服务器上,进行离线权重转换。 + +**单进程转换:** + +```bash +python mindformers/tools/ckpt_transform/transform_checkpoint.py \ + --src_checkpoint=/worker/checkpoint/llama3-8b/rank_0/llama_7b.ckpt \ + --dst_checkpoint=./output/llama3_8b_dp2mp4pp2 \ + --dst_strategy=./output/strategy +``` + +**多进程转换(可选):** + +```bash +# 使用2个进程进行转换 +bash mindformers/tools/ckpt_transform/transform_checkpoint.sh \ + /worker/checkpoint/llama3-8b/rank_0/llama_7b.ckpt \ + None \ + ./output/llama3_8b_dp2mp4pp2 \ + ./output/strategy \ + 16 2 +``` + +##### 3. 复制权重到其他节点 + +将转换得到的分布式权重分别复制到各自节点。0节点只需要 `rank_0` 到 `rank_7` 的切片权重,1节点只需要 `rank_8` 到 `rank_15` 的切片权重。 + +##### 4. 参数配置 + +```yaml +# 配置预训练权重路径,填写分布式权重文件夹路径 model_dir +load_checkpoint: "/worker/checkpoint/llama3_8b_dp2mp4pp2" + +# 将 only_save_strategy 改为 False +only_save_strategy: False +``` + +### ModelArts 训练 + +在 ModelArts 环境中进行训练与物理机上的多机多卡训练类似,同样支持开启权重自动转换。用户可以通过在训练作业的超参数中配置`auto_trans_ckpt=True`来启用自动权重转换,并通过设置`transform_process_num > 1`来开启多进程转换。 + +​**注意**​:如果 ModelArts 资源池中的服务器节点NPU卡数不是8,则需要额外配置`npu_num_per_node=节点NPU卡数`。例如,如果每个节点配有16个NPU,则应设置`npu_num_per_node=16`。 + +### AutoModel 加载分布式模型 + +`AutoModel` 接口已经适配了权重自动转换功能,支持在分布式训练场景下自动加载并输出分布式模型。以下是使用示例: + +```python +from mindformers import AutoModelForCausalLM, build_context + +# 配置分布式策略 +train_args = TrainingArguments( + use_parallel=True, + data_parallel=1, + model_parallel=2, + pipeline_stage=2, + micro_batch_num=2, + recompute=True, + enable_parallel_optimizer=True, + ... +) + +# 初始化分布式权重 +build_context(train_args) + +# 初始化分布式模型 +model = AutoModelForCausalLM.from_pretrained( + "repo_id", + auto_trans_ckpt=True, + parallel_config=train_args.get_parallel_config() +) +``` + +**注意**:`AutoModel` 的权重自动转换特性仅支持通过 `"repo_id"` 的形式加载模型,即从 OpenMind 或本地仓库加载权重,不支持通过模型名称或其他方式进行加载。 + +## Lora权重合并 + +### 概述 + +LoRA(Low-Rank Adaptation)的基本原理是对原始模型的参数进行低秩重参数化。合并权重的核心过程是将 LoRA 分支的权重计算并叠加到对应的模型权重中。这一操作不会对推理结果产生任何影响,因此合并后的模型在推理时依然能够保持与原始模型一致的性能。 + +有关 LoRA 的详细原理和实现,请参阅以下资源: + +- 论文: [LoRA: Low-Rank Adaptation of Large Language Models](https://arxiv.org/abs/2106.09685) +- GitHub: [https://github.com/microsoft/LoRA](https://github.com/microsoft/LoRA) + +### 使用说明 + +本教程将指导您如何将通过 LoRA(Low-Rank Adaptation)微调后的权重与原始模型的权重进行合并,生成可用于推理的完整模型权重文件。合并后的权重将使您能够在推理过程中直接利用 LoRA 的微调效果。若有其他需求,例如仅有 LoRA 权重或对权重进行进一步操作,您可以基于此方法自行调整脚本。 + +```bash +python mindformers/tools/transform_ckpt_lora.py \ + --src_ckpt_strategy src_strategy_path_or_dir \ + --src_ckpt_path_or_dir src_ckpt_path_or_dir \ + --dst_ckpt_dir dst_ckpt_dir \ + --prefix "checkpoint_" \ + --lora_scaling lora_alpha/lora_rank +``` + +#### 参数说明 + +- **src_ckpt_strategy**:源权重对应的分布式策略文件路径,通常在启动训练任务后默认保存在 `output/strategy/` 目录下。如果源权重为完整权重,则无需填写此参数;如果为分布式权重,需根据以下情况填写: + - **源权重开启了流水线并行**:权重转换基于合并的策略文件,填写分布式策略文件夹路径。脚本会自动将文件夹内的所有 `ckpt_strategy_rank_x.ckpt` 文件合并,并在文件夹下生成 `merged_ckpt_strategy.ckpt`。如果已经存在 `merged_ckpt_strategy.ckpt`,可以直接填写该文件的路径。 + - **源权重未开启流水线并行**:权重转换可基于任一策略文件,填写任意一个 `ckpt_strategy_rank_x.ckpt` 文件的路径即可。 + + **注意**:如果策略文件夹下已存在 `merged_ckpt_strategy.ckpt` 且仍传入文件夹路径,脚本会首先删除旧的 `merged_ckpt_strategy.ckpt`,再合并生成新的 `merged_ckpt_strategy.ckpt` 以用于权重转换。因此,请确保该文件夹具有足够的写入权限,否则操作将报错。 +- **src_ckpt_path_or_dir**:源权重的路径。如果为分布式权重,请填写源权重所在文件夹的路径,源权重应按 `model_dir/rank_x/xxx.ckpt` 格式存放,并将文件夹路径填写为 `model_dir`。若源权重为完整权重,则填写完整权重的绝对路径。 +- **dst_ckpt_dir**:目标权重的保存路径,需为自定义的空文件夹路径。目标权重将按 `model_dir/rank_x/xxx.ckpt` 格式保存。 +- **prefix**:目标权重文件的命名前缀,默认值为 "checkpoint_",即目标权重将按照 `model_dir/rank_x/checkpoint_x.ckpt` 格式保存。 +- **lora_scaling**:LoRA 权重的合并系数,默认为 `lora_alpha/lora_rank`,这两个参数即为 LoRA 模型配置时的参数,需自行计算。 + +### 示例 + +#### 场景 1:完整的带 LoRA 的权重 + +如果您拥有一个完整的带 LoRA 的权重文件,并希望将其转换为完整的原始权重,您可以按照以下方式填写参数(直接输入完整权重的路径): + +```bash +python mindformers/tools/transform_ckpt_lora.py \ + --src_ckpt_path_or_dir .../xxx/xxx.ckpt \ + --dst_ckpt_dir dst_ckpt_dir \ + --prefix "checkpoint_" \ + --lora_scaling lora_alpha/lora_rank +``` + +#### 场景 2:带 LoRA 的分布式权重 + +如果您拥有一个经过分布式切分的带 LoRA 的权重文件,并希望将其转换为完整的原始权重,您可以按照以下方式填写参数(需输入权重文件夹路径和分布式策略文件夹路径): + +```bash +python mindformers + +/tools/transform_ckpt_lora.py \ + --src_ckpt_strategy .../xxx/mindformers/output/strategy/ \ + --src_ckpt_path_or_dir .../xxx/model_dir \ + --dst_ckpt_dir dst_ckpt_dir \ + --prefix "checkpoint_" \ + --lora_scaling lora_alpha/lora_rank +``` + [![查看源文件](https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/website-images/master/resource/_static/logo_source.svg)](https://gitee.com/mindspore/docs/blob/master/docs/mindspore/source_zh_cn/mindformers/function/weight_conversion.md) \ No newline at end of file