English | 中文

# 模型训练 Hy-MT 提供了模型训练相关流程,您可以在此章节对训练数据格式进行处理以供模型训练使用。 ## 训练数据格式及处理 训练数据按照以下形式处理为 messages 格式,训练和推理的默认 system prompt 为空,可以根据自己的需求进行设定。 以下是翻译任务的训练数据示例: ```python # 翻译任务示例 {"messages": [{"role": "user", "content": "将以下中文翻译为英文,只输出翻译结果,不要额外解释:\n\n实验结果证明了假设的正确性。"}, {"role": "assistant", "content": "The experimental results demonstrate the correctness of the hypothesis."}]} ``` ## 快速开始 您可以参照快速开始文档中的内容进行快速上手。 ## 模型训练 ### 硬件需求 以下为各模型在 max_seq_length = 8192 时的最低硬件需求: #### Hy-MT2-1.8B(Dense) | 训练方式 | DeepSpeed 策略 | 最低 GPU 需求 | |---------|---------------|-------------| | LoRA 微调 | ZeRO-2(无 offload) | 1 卡(24GB+) | | 全量微调 | ZeRO-2(无 offload) | 1 卡(24GB+) | #### Hy-MT2-7B(Dense) | 训练方式 | DeepSpeed 策略 | 最低 GPU 需求 | |---------|---------------|-------------| | LoRA 微调 | ZeRO-2(无 offload) | 1 卡(80GB+) | | 全量微调 | ZeRO-3(无 offload) | 2 卡(80GB+ 每卡) | #### Hy-MT2-30B-A3B(MoE) | 训练方式 | DeepSpeed 策略 | 最低 GPU 需求 | |---------|---------------|-------------| | LoRA 微调 | ZeRO-2(无 offload) | 单机 8 卡(80GB+ 每卡) | | 全量微调 | ZeRO-3 + offload | 单机 8 卡(80GB+ 每卡) | ### 配置机器间免密 ssh 登录(多机训练) > 如果只使用单机训练,可跳过本节。 以下操作以两个机器为例,两台机器的 ip 分别以`${ip1}`和`${ip2}`标识,以下操作均在 docker container 内执行。 首先,配置多机container免密,在每台机器上执行。 ```sh ssh-keygen # 生成id_rsa和id_rsa.pub,用于免密登录 ssh-keygen -t rsa -A # 生成/etc/ssh/ssh_host_rsa_key和ssh_host_ecdsa_key, 用于后面启动ssh listen /usr/sbin/sshd -p 36005 -o ListenAddress=0.0.0.0 # 启动 SSH 监听 echo "Port 36005" > ~/.ssh/config # ssh 连接端口修改为 36005 passwd root # 需要配置root密码,否则监测平台会报警 ``` 注意:这里的`36005`是一个示例端口,可以选用任意端口,但需要保证使用的端口**开放**且**不被其他的进程占用**。 接下来,在每台机器的 container 内,执行: ```sh cat ~/.ssh/id_rsa.pub ``` **将输出的 ssh 公钥复制并粘贴到`~/.ssh/authorized_keys`文件中,每行一个公钥,每台机器上都要做这个操作**。最终每台机器上的`~/.ssh/authorized_keys`文件内容应当是一致的,并且包含了所有机器的公钥。 需要注意,多节点训练时,每个节点上执行的代码都得一致,建议挂载一个共享的网络盘,如果无法挂载共享网盘,则需要手动将数据集、脚本、代码复制在多台机器的相同目录下。 ### 启动方式 本项目提供两种训练方式,您可以根据需求选择: - **DeepSpeed 原生训练**(基于 HuggingFace Transformers Trainer):位于 `train/deepspeed_support` 目录下 - **LLaMA-Factory 训练**:位于 `train/llama_factory_support` 目录下 #### DeepSpeed 原生训练 参考:[HuggingFace Transformers Trainer](https://huggingface.co/docs/transformers/main/en/main_classes/trainer) ##### 训练脚本 在 `train/deepspeed_support` 目录下,各模型对应的训练脚本如下: | 模型 | 全量微调 | LoRA 微调 | |------|---------|----------| | Hy-MT2-1.8B(Dense) | `bash train_dense.sh 1.8B` | `bash train_dense_lora.sh 1.8B` | | Hy-MT2-7B(Dense) | `bash train_dense.sh 7B` | `bash train_dense_lora.sh 7B` | | Hy-MT2-30B-A3B(MoE) | `bash train.sh` | `bash train_lora.sh` | ##### 单机启动训练 在 `train/deepspeed_support` 目录下,安装依赖后直接执行对应的脚本命令即可: ```sh pip install -r requirements.txt # 示例:Dense 1.8B 全量微调 bash train_dense.sh 1.8B ``` ##### 多机启动训练 如果要用多台机器启动训练,请先完成 [配置机器间免密 ssh 登录](#配置机器间免密-ssh-登录多机训练) 中的配置,并保证多台机器在一个集群内。 确认依赖已经安装完成(如未安装,请执行`pip install -r requirements.txt`安装),然后在对应的训练脚本中设置 `IP_LIST` 环境变量: ```shell export HOST_GPU_NUM=8 # IP list, comma separated. e.g. "192.168.1.1,192.168.1.2" or single node "192.168.1.1" IP_LIST=${IP_LIST:-"127.0.0.1"} ``` 注意:如果`IP_LIST`环境变量未设置,则将`IP_LIST`替换为IP列表!格式为: ``` 如果只有一个IP: IP_LIST=${ip_1} 如果有多个IP: IP_LIST=${ip_1},${ip_2} ``` 请将`${ip_1}`和`${ip_2}`替换为真实的IP地址。 然后,在`${ip1}`的机器上,在`train/deepspeed_support/`目录下,执行对应的训练脚本即可。注意第一次启动时可能会看见以下的输出: ```ssh The authenticity of host '[ip]:36005 ([ip]:36005)' can't be established. ECDSA key fingerprint is xxxxxx. ECDSA key fingerprint is MD5:xxxxxx. Are you sure you want to continue connecting (yes/no)? ``` 此时输入`yes`即可继续。 ##### 关键参数 脚本中的关键参数如下: - `--deepspeed`: 此参数应当指向一个 deepspeed 的配置文件,`train/deepspeed_support`文件夹下提供了三种 DeepSpeed 的默认配置文件:`ds_zero2_no_offload.json`, `ds_zero3_no_offload.json`, `ds_zero3_offload.json`,这三个配置文件所需显存依次减少 - `--model_name_or_path`: 要加载的 Hy-MT 的 HF 预训练模型权重,否则无法加载 - `--tokenizer_name_or_path`: tokenizer 文件夹路径, 否则无法加载 - `--train_data_file`: 训练文件路径,应该为一个 jsonl 文件 - `--output_dir`: 输出文件夹,log、tensorboard 和权重都会存储在这个路径下 - `--per_device_train_batch_size`: 每张卡上的 batch size - `--gradient_accumulation_steps`: 梯度累计次数,`per_device_train_batch_size * gradient_accumulation_steps * dp_size`为 global_batch_size - `--max_steps`: 训练的总步数 - `--save_steps`: 每多少个 step 存储一个 checkpoint - `--use_lora`: 是否用 lora 训练,同时接收`--lora_rank`,`--lora_alpha`和`--lora_dropout`参数。lora 默认应用于 "q_proj", "k_proj", "v_proj", "o_proj" 四个参数,如果需要改变的话在代码中修改即可。注意:**使用 lora 训练时,只会保存 lora 的权重,而不会保存 base 模型的权重**,如果需要合并 lora 权重,看下面的“Lora 权重合并”一节 - `--make_moe_param_leaf_module`:当用 zero3 以及 MoE 训练时,将 MoE 模块视作一个 leaf module,即它的参数不进行 zero3 切分,这个选项预计会显著增加显存占用 - `--gradient_checkpointing`:开启梯度重计算 - `--train_attention_params_only`: 是否只训练 attention 参数 - `--learning_rate`: 训练时的最大学习率 - `--min_lr`: 训练时的最小学习率 - `--use_flash_attn`: 开启 flash-attention 进行训练加速 **注意:** - 如果想从一个中途保存的 ckpt 继续训练,而不是加载一个预训练的权重,直接指定`--resume_from_checkpoint`为之前训练保存的 ckpt 路径,不要指定`--model_name_or_path`,这样只会加载权重,而不会加载训练状态 - 从 ckpt 继续训练时,loss 可能会有微小的偏差,这是由一些非确定性算法带来的随机性,是正常现象。参考:[HuggingFace Transformers Trainer Randomness](https://huggingface.co/docs/transformers/main/en/main_classes/trainer#randomness) - 当 `--model_name_or_path` 有效时,所有模型相关的参数都会被忽略 - 一个 batch 内的样本会通过 padding 对齐 batch 内最长的样本,而每条样本的长度最长为 max_seq_length,超出的部分会被裁剪 - 如果报出 bias 权重没有 load 的 warning,忽略即可,Hunyuan-Large 中不会用到 bias ##### 显存不足怎么办? 参考:[DeepSpeed Configuration](https://www.deepspeed.ai/docs/config-json/) 可以尝试修改 ds config,去掉这几个参数的 auto 属性,改小试试看: - `stage3_param_persistence_threshold` - `stage3_prefetch_bucket_size` - `stage3_max_reuse_distance` ##### Lora 模型合并 保存下来的 lora 权重没法在训练运行时合并到 zero3 模型中,因为 zero3 开启时模型权重会切分到各 dp rank 上。因此如果想把 lora 权重合并到 base 模型上,可以通过离线的方式合并后得到权重文件。执行`merge_lora_weight.sh`即可完成 lora 权重和 base 模型权重的合并,其中的参数有: - `--base_model_path`:base 模型的权重目录 - `--adapter_model_path`:lora 权重目录 - `--output_path`:合并后的权重保存目录 - `--save_dtype`: 以什么数据格式存储合并后的权重,可选值:fp16,bf16,fp32 #### LLaMA-Factory 训练 如果对 LLaMA-Factory 较为熟悉,可使用 LLaMA-Factory 进行微调。脚本、代码以及配置文件都归档在 `train/llama_factory_support` 目录下。如果没有特别说明,接下来我们提到的文件都是该目录下的文件。 ##### 安装 可以通过下载源码 https://github.com/hiyouga/LLaMA-Factory/tree/main ,根据网站的指引进行安装。 ##### 训练脚本与配置文件 各模型对应的配置文件和启动脚本如下: | 模型 | 全量微调配置 | LoRA 微调配置 | 启动脚本 | |------|------------|-------------|---------| | Hy-MT2-1.8B(Dense) | `hy_dense_1_8b_full_sft.yaml` | `hy_dense_1_8b_lora_sft.yaml` | `bash train_lf_dense.sh` | | Hy-MT2-7B(Dense) | `hy_dense_7b_full_sft.yaml` | `hy_dense_7b_lora_sft.yaml` | `YAML_FILE=hy_dense_7b_full_sft.yaml bash train_lf_dense.sh` | | Hy-MT2-30B-A3B(MoE) | `hy_v3_full_sft.yaml` | `hy_v3_lora_sft.yaml` | `bash train_lf.sh` | > **提示**:Dense 模型的启动脚本 `train_lf_dense.sh` 默认使用 `hy_dense_1_8b_full_sft.yaml`,可通过 `YAML_FILE` 环境变量指定其他配置文件。 脚本中的关键参数如下: **模型相关:** - `model_name_or_path`: Hy-MT HF 格式预训练模型权重路径 - `trust_remote_code`: 是否信任远程代码, Hy-MT 需要设置为 `true` **训练方法:** - `stage`: 训练阶段, 当前为 `sft`(监督微调) - `finetuning_type`: 微调类型, 可选 `full`(全量微调) 或 `lora`(LoRA 微调) - `deepspeed`: DeepSpeed 配置文件路径, 全量微调推荐 `ds_zero3_offload.json`, LoRA 微调推荐 `ds_zero2_offload_lora.json` **LoRA 参数(仅 LoRA 微调时生效):** - `lora_rank`: LoRA 秩, 默认 `64` - `lora_alpha`: LoRA alpha 系数, 默认 `128` - `lora_dropout`: LoRA dropout 比率, 默认 `0.05` - `lora_target`: LoRA 应用的目标模块, 默认为 `q_proj,k_proj,v_proj,o_proj` **数据集:** - `dataset_dir`: 数据集目录路径 - `dataset`: 数据集名称, 需要在 `dataset_dir` 下的 `dataset_info.json` 中注册 - `template`: 对话模板, Hy-MT2-1.8B 使用 `hy_dense_1_8b`, Hy-MT2-7B 使用 `hy_dense_7b`, Hy-MT2-30B-A3B 使用 `hy_v3` - `cutoff_len`: 最大序列长度, 超出部分会被截断; 全量微调可设为 `262144`(262K), LoRA 微调建议设为 `8192` 以节省显存 - `max_samples`: 每个数据集最多使用的样本数 - `overwrite_cache`: 是否覆盖已缓存的预处理数据集 **输出:** - `output_dir`: 输出目录, 日志、TensorBoard 和权重都会存储在此路径下 - `logging_steps`: 每多少步记录一次日志 - `save_steps`: 每多少步保存一次 checkpoint - `plot_loss`: 是否绘制训练 loss 曲线 - `overwrite_output_dir`: 是否覆盖已有的输出目录 - `save_only_model`: 是否只保存模型权重(不保存优化器状态等) - `report_to`: 日志上报工具, 可选 `none`, `wandb`, `tensorboard`, `swanlab`, `mlflow` **训练超参数:** - `per_device_train_batch_size`: 每张卡上的 batch size - `gradient_accumulation_steps`: 梯度累积步数, `per_device_train_batch_size * gradient_accumulation_steps * dp_size` 为 global batch size - `learning_rate`: 最大学习率, 全量微调推荐 `1.0e-5`, LoRA 微调推荐 `2.0e-4` - `num_train_epochs`: 训练轮数 - `lr_scheduler_type`: 学习率调度器类型, 推荐使用 `cosine_with_min_lr` - `lr_scheduler_kwargs.min_lr_rate`: 最小学习率与最大学习率的比值, 例如 `0.1` 表示最小学习率为最大学习率的 10% - `warmup_ratio`: 预热阶段占总训练步数的比例 - `bf16`: 是否使用 BFloat16 混合精度训练 - `gradient_checkpointing`: 是否开启梯度重计算以节省显存 - `ddp_timeout`: 分布式训练超时时间(毫秒) - `flash_attn`: 注意力实现方式, 推荐 `fa2`(FlashAttention-2), 也可选 `sdpa`; 使用 `fa2` 需要安装 flash-attn 包 - `resume_from_checkpoint`: 从指定 checkpoint 路径恢复训练, 设为 `null` 表示从头开始训练 ##### 启动训练 如需多机训练,请先完成 [配置机器间免密 ssh 登录](#配置机器间免密-ssh-登录多机训练) 中的配置(单机训练可跳过此步骤)。 修改对应启动脚本中开头的以下配置: ```shell export HOST_GPU_NUM=8 # IP list, comma separated. e.g. "192.168.1.1,192.168.1.2" or single node "192.168.1.1" export IP_LIST=${IP_LIST:-"127.0.0.1"} ``` 注意:如果`IP_LIST`环境变量未设置,则将`IP_LIST`替换为IP列表!格式为: ``` 如果只有一个IP: IP_LIST=${ip_1} 如果有多个IP: IP_LIST=${ip_1},${ip_2} ``` 请将`${ip_1}`和`${ip_2}`替换为真实的IP地址。 然后,在每一台机器上,在`train/llama_factory_support/`目录下执行对应的启动脚本即可。例如: ```sh # Dense 1.8B 全量微调 bash train_lf_dense.sh # Dense 7B LoRA 微调 YAML_FILE=hy_dense_7b_lora_sft.yaml bash train_lf_dense.sh # MoE 30B-A3B 全量微调 bash train_lf.sh ```