训练常见问题
Q1:复制文档中提供的样例脚本,运行时为什么出现 syntax error near unexpected token `$'{\r''?提示
A:通过复制文档中提供的的样例脚本后创建文件,可能由于Windows系统文件的换行符和Linux有所不同,导致了换行符识别不匹配。可以在Linux系统中执行dos2unix xxx.sh 或者使用vim执行以下两条命令进行格式转换。
:set ff=unix :wq
Q2:所有的模型是否都通用本文档提供的脚本参数?切换模型的时候需要注意什么?
A:使用不同模型的时候,或者进行不同类型的训练时,都需要参考MindSpeed-LLM/docs/quick_start.md · Ascend/MindSpeed-LLM - AtomGit | GitCode 下每种模型具体的example脚本。
但是总体流程都是执行以下脚本,再根据本文档中的说明修改脚本参数后即可开始训练。
- hf到mg格式的权重转换脚本ckpt_convert_XXX_hf2mcore.sh
- 数据处理脚本data_convert_XXX_instruction.sh,如果是预训练则是data_convert_XXX_pretrain.sh
- 训练脚本,微调选择tune,预训练选择pretrain,全量微调选择full,Low-Rank Adaptation则选择LoRA。
- mg到hf格式的权重转换脚本ckpt_convert_XXX_mcore2hf.sh
- 训练任务总脚本run_distributed_task.sh也需要根据上述修改进行调整。
Q3:能否单独执行模型权重转换、数据格式转换、训练任务执行脚本,而不使用训练作业启动总脚本?
A:不推荐。训练任务总脚本run_distributed_task.sh中,除了处理通信之外,也处理了OBS路径以及模型保存等相关操作。环境变量在训练任务总脚本run_distributed_task.sh中进行配置也更为规范和方便。使用总脚本也可以在一台实例上进行训练。
Q4:如果训练任务执行失败,但权重转换和数据格式转换都已成功执行并且保存到存储中,那再次训练时可以不重新转换权重或数据吗?
A:可以,只要保证参数和路径不变的情况下,在训练总脚本run_distributed_task.sh中对权重转换脚本ckpt_convert_XXX_hf2mcore.sh和数据格式转换脚本data_convert_XXX_instruction.sh增加注释,然后将相应的模型、并行参数以及路径填入到run_distributed_task.sh中即可直接进行训练。
Q5:MindSpeed-LLM安装在哪里?想要进行一些修改或者添加打印应该如何找到这个路径?
A:MindSpeed-LLM安装在/home/ma-user/MA_Turbo/src/open_source/MindSpeed-LLM下,其他依赖安装在/home/ma-user/MA_Turbo/src/open_source下。
在MindSpeed-LLM目录下即可看到与官方仓相同的分支内容。自定义使用MindSpeed-LLM的组件和文件时(例如convert_ckpt.py脚本),请注意路径是否正确,或者使用绝对路径/home/ma-user/MA_Turbo/src/open_source/MindSpeed-LLM/convert_ckpt.py。
Q6:训练完成之后得到的是什么格式的权重?为什么数量和一开始的HF模型文件数量不一致?
A:训练刚结束时生成的是 Megatron-Core (mcore) 格式权重(为了极致的分布式训练效率,将权重切分到了不同 GPU 上)。经过 mg2hf 转换脚本处理后,最终得到的是标准的 HuggingFace (HF) 格式权重,这是主流推理引擎(如 vLLM)所通用的格式。
转换后的 .safetensors 文件数量与原始模型不一致是正常的,因为配置的切分策略不同。虽然文件数量变了,但在 model.safetensors.index.json 索引文件的映射下,模型参数是完整的,可以正常加载和使用。
使用前请自行根据mg2hf转化完成的权重生成新的model.safetensors.index.json,避免出现model.safetensors.index.json中仍为旧的未训练的模型权重索引。
convert_ckpt.py的说明文档如下:
v1文档:convert_ckpt.py文档
v2文档:convert_ckpt_v2.py文档
v1版本的examples较多且更稳定,推荐使用v1版本进行权重转化。如果希望使用v2,请保持hf2mg和mg2hf均为v2。可以自行阅读上述文档了解两者差异。
lora训练时权重转化方式区别较大,请自行阅读v1文档中的介绍修改训练脚本和权重转化脚本。
生成新的model.safetensors.index.json示例代码如下
import os import json from safetensors import safe_open # === 修改这里为你的实际路径 === models_dir = "$TRAINED_HF_MODELS" # =========================== def generate_index(dir_path): print(f"正在扫描目录: {dir_path}") files = sorted([f for f in os.listdir(dir_path) if f.endswith(".safetensors")]) if not files: print("错误:目录下没有找到 .safetensors 文件!") return weight_map = {} total_size = 0 print(f"找到 {len(files)} 个权重文件,开始重构索引...") for file_name in files: file_path = os.path.join(dir_path, file_name) try: # 打开文件读取里面的 key with safe_open(file_path, framework="pt") as f: keys = f.keys() # 将该文件里的所有 key 都注册到 map 中 for k in keys: weight_map[k] = file_name # 获取文件大小(可选,用于 metadata) total_size += os.path.getsize(file_path) print(f"已处理: {file_name} (包含 {len(keys)} 个参数)") except Exception as e: print(f"读取文件 {file_name} 失败: {e}") return # 构建最终的 index 字典 index_dict = { "metadata": { "total_size": total_size }, "weight_map": weight_map } # 保存新的 index.json save_path = os.path.join(dir_path, "model.safetensors.index.json") with open(save_path, "w") as f: json.dump(index_dict, f, indent=2) print("-" * 30) print(f"成功!新的索引文件已生成于: {save_path}") if __name__ == "__main__": generate_index(models_dir)