English | 中文
Hy-MT 提供了模型训练相关流程,您可以在此章节对训练数据格式进行处理以供模型训练使用。
训练数据按照以下形式处理为 messages 格式,训练和推理的默认 system prompt 为空,可以根据自己的需求进行设定。
以下是翻译任务的训练数据示例:
# 翻译任务示例
{"messages": [{"role": "user", "content": "将以下中文翻译为英文,只输出翻译结果,不要额外解释:\n\n实验结果证明了假设的正确性。"}, {"role": "assistant", "content": "The experimental results demonstrate the correctness of the hypothesis."}]}
您可以参照快速开始文档中的内容进行快速上手。
以下为各模型在 max_seq_length = 8192 时的最低硬件需求:
| 训练方式 | DeepSpeed 策略 | 最低 GPU 需求 |
|---|---|---|
| LoRA 微调 | ZeRO-2(无 offload) | 1 卡(24GB+) |
| 全量微调 | ZeRO-2(无 offload) | 1 卡(24GB+) |
| 训练方式 | DeepSpeed 策略 | 最低 GPU 需求 |
|---|---|---|
| LoRA 微调 | ZeRO-2(无 offload) | 1 卡(80GB+) |
| 全量微调 | ZeRO-3(无 offload) | 2 卡(80GB+ 每卡) |
| 训练方式 | DeepSpeed 策略 | 最低 GPU 需求 |
|---|---|---|
| LoRA 微调 | ZeRO-2(无 offload) | 单机 8 卡(80GB+ 每卡) |
| 全量微调 | ZeRO-3 + offload | 单机 8 卡(80GB+ 每卡) |
如果只使用单机训练,可跳过本节。
以下操作以两个机器为例,两台机器的 ip 分别以${ip1}和${ip2}标识,以下操作均在 docker container 内执行。
首先,配置多机container免密,在每台机器上执行。
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 内,执行:
cat ~/.ssh/id_rsa.pub
将输出的 ssh 公钥复制并粘贴到~/.ssh/authorized_keys文件中,每行一个公钥,每台机器上都要做这个操作。最终每台机器上的~/.ssh/authorized_keys文件内容应当是一致的,并且包含了所有机器的公钥。
需要注意,多节点训练时,每个节点上执行的代码都得一致,建议挂载一个共享的网络盘,如果无法挂载共享网盘,则需要手动将数据集、脚本、代码复制在多台机器的相同目录下。
本项目提供两种训练方式,您可以根据需求选择:
train/deepspeed_support 目录下train/llama_factory_support 目录下参考:HuggingFace Transformers 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 目录下,安装依赖后直接执行对应的脚本命令即可:
pip install -r requirements.txt
# 示例:Dense 1.8B 全量微调
bash train_dense.sh 1.8B
如果要用多台机器启动训练,请先完成 配置机器间免密 ssh 登录 中的配置,并保证多台机器在一个集群内。
确认依赖已经安装完成(如未安装,请执行pip install -r requirements.txt安装),然后在对应的训练脚本中设置 IP_LIST 环境变量:
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/目录下,执行对应的训练脚本即可。注意第一次启动时可能会看见以下的输出:
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 进行训练加速注意:
--resume_from_checkpoint为之前训练保存的 ckpt 路径,不要指定--model_name_or_path,这样只会加载权重,而不会加载训练状态--model_name_or_path 有效时,所有模型相关的参数都会被忽略可以尝试修改 ds config,去掉这几个参数的 auto 属性,改小试试看:
stage3_param_persistence_thresholdstage3_prefetch_bucket_sizestage3_max_reuse_distance保存下来的 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 进行微调。脚本、代码以及配置文件都归档在 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.jsonLoRA 参数(仅 LoRA 微调时生效):
lora_rank: LoRA 秩, 默认 64lora_alpha: LoRA alpha 系数, 默认 128lora_dropout: LoRA dropout 比率, 默认 0.05lora_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_v3cutoff_len: 最大序列长度, 超出部分会被截断; 全量微调可设为 262144(262K), LoRA 微调建议设为 8192 以节省显存max_samples: 每个数据集最多使用的样本数overwrite_cache: 是否覆盖已缓存的预处理数据集输出:
output_dir: 输出目录, 日志、TensorBoard 和权重都会存储在此路径下logging_steps: 每多少步记录一次日志save_steps: 每多少步保存一次 checkpointplot_loss: 是否绘制训练 loss 曲线overwrite_output_dir: 是否覆盖已有的输出目录save_only_model: 是否只保存模型权重(不保存优化器状态等)report_to: 日志上报工具, 可选 none, wandb, tensorboard, swanlab, mlflow训练超参数:
per_device_train_batch_size: 每张卡上的 batch sizegradient_accumulation_steps: 梯度累积步数, per_device_train_batch_size * gradient_accumulation_steps * dp_size 为 global batch sizelearning_rate: 最大学习率, 全量微调推荐 1.0e-5, LoRA 微调推荐 2.0e-4num_train_epochs: 训练轮数lr_scheduler_type: 学习率调度器类型, 推荐使用 cosine_with_min_lrlr_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 登录 中的配置(单机训练可跳过此步骤)。
修改对应启动脚本中开头的以下配置:
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/目录下执行对应的启动脚本即可。例如:
# 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