更新时间:2026-02-05 GMT+08:00
分享

训练常见问题

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)

相关文档