Ascend-SACT/Qwen2.5-3B-Instruct-2k-mindspeedllm
模型介绍文件和版本Pull Requests讨论分析
下载使用量0

Qwen2.5-3B-Instruct-2k-MindspeedLLM训练指导

一、 模型概述及场景

Qwen2.5是通义千问大模型系列2024年9月发布,参数量从0.5B到72B不等的多个基础模型和指令微调模型。相比Qwen2,Qwen2.5主要带来以下提升:

  • 通过领域专家模型增强,显著扩充知识储备,大幅提升代码与数学能力
  • 在指令遵循、长文本生成(超8K tokens)、结构化数据理解(如表格)及结构化输出(尤其是JSON格式)方面表现更优
  • 对系统提示词的多样性更具适应性,强化了聊天机器人的角色扮演和条件设定功能
  • 支持128K tokens长上下文,可生成8K tokens内容
  • 支持中英法西葡德意俄日韩越泰阿拉伯等29种语言

本案例包含指令精调的3B参数Qwen2.5模型,具有以下技术特征:

• 类型:因果语言模型

• 训练阶段:预训练+后训练

• 架构:采用RoPE位置编码、SwiGLU激活函数、RMSNorm层标准化、带注意力QKV偏置及词嵌入绑定的Transformer结构

• 参数量:3.09B(非嵌入参数量2.77B)

• 层数:36

• 注意力头配置(分组查询注意力):查询头16个,键值头2个

• 上下文长度:完整支持32,768 tokens,生成长度8,192 tokens

模型huggingface链接:Qwen2.5-3B-Instruct

本案例使用昇腾A3机器上,基于MindspeedLLM 框架完成Qwen2.5-3B-Instruct模型基于业务数据集的SFT训练实践。

二、 环境准备

Qwen2.5-3B-Instruct在业务数据集上的全参微调训练与评测使用到的软件以及硬件环境如下:

2.1. 硬件环境

硬件名称配置信息备注
机器型号A3 超节点
测试集群8卡Pod单机

2.2. 软件环境

软件版本部署方式
DriverAscendHDK 25.2.0宿主机
FirmwareAscendHDK 25.2.0宿主机
Python3.10.18容器
CANN8.2.RC1容器
Torch2.6.0容器
Torch_npu2.6.0容器
MindSpeed2.1.0_core_r0.8.0容器
MindSpeed-LLM2.1.0容器
Megatron-LMcore_r0.8.0容器
Docker镜像OSUbuntu 20.04.6/

2.3. 镜像准备

MindspeedLLM 镜像已发布,使用方法请参考:昇腾训练镜像构建指导 中 MindSpeed-LLM镜像章节。

三、 数据预处理

3.1. 脚本

业务数据集是ShareGPT风格数据,因此采用ShareGPT风格数据集处理方法进行预处理。

业务当前提供数据集预处理脚本如下:

# 业务数据集预处理
source /usr/local/Ascend/ascend-toolkit/set_env.sh
cd /usr/local/Ascend/llm-train/MindSpeed-LLM
datapath=***
mkdir ${datapath}/train_data_10k

python ./preprocess_data.py \
    --input ${datapath}/train_data_10k.jsonl \
    --tokenizer-name-or-path /data/***/Qwen2.5-3B-Instruct \
    --output-prefix ${datapath}/train_data_10k/train_data_10k \
    --workers 4 \
    --log-interval 1000 \
    --tokenizer-type PretrainedFromHF \
    --handler-name SharegptStyleInstructionHandler \
    --prompt-type qwen \
    --map-keys '{"messages":"messages", "tags":{"role_tag": "role","content_tag": "content","user_tag": "user","assistant_tag": "assistant","system_tag": "system"}}'

关键参数说明:

  1. --input(必须):

    描述: 输入数据文件的路径,通常是一个jsonl(每行一个JSON对象)文件。

    示例: --input /path/to/data.jsonl

  2. --tokenizer-name-or-path(必须):

    描述: 用于分词器的预训练模型的名称或路径。可以是Hugging Face模型仓库的ID,也可以是本地包含tokenizer文件的目录。

    示例: --tokenizer-name-or-path Qwen/Qwen1.5-7B或者 --tokenizer-name-or-path /path/to/tokenizer

  3. --output-prefix(必须):

    描述: 输出文件的前缀。预处理后的数据会被保存为多个文件(例如,后缀为.bin和.idx),这个参数指定这些文件的前缀路径。

    示例: --output-prefix /path/to/output/preprocessed_data

  4. --workers(可选,默认值可能为1):

    描述: 指定数据预处理时使用的进程数(多进程)。更多的进程数可以加快处理速度。

    示例: --workers 4

  5. --log-interval(可选,默认值可能为100):

    描述: 控制日志打印的频率,例如每处理1000条数据打印一次进度日志。

    示例: --log-interval 1000

  6. --tokenizer-type(必须):

    描述: 指定tokenizer的类型。这里使用PretrainedFromHF,表示使用Hugging Face的预训练tokenizer。

    示例: --tokenizer-type PretrainedFromHF

  7. --handler-name(必须):

    描述: 指定数据处理器(handler)的类名。这里使用SharegptStyleInstructionHandler,这是专门为类似ShareGPT格式(对话格式)的指令数据设计的处理器。该处理器会按照指令模板格式化数据。

    示例: --handler-name SharegptStyleInstructionHandler

  8. --prompt-type(必须):

    描述: 指定提示模板类型。不同的提示模板对应不同的格式化方式。这里指定为qwen,表示使用Qwen模型所要求的提示格式。

    示例: --prompt-type qwen

  9. --map-keys(必须):

    描述: 一个JSON字符串,用于将输入数据中的字段映射到处理器所需的字段。这个参数允许我们自定义输入JSON中的键名,使得处理器能够正确获取角色、内容等信息。

    格式: 一个JSON字典,其中至少包括:

    • "messages": 输入数据中对话列表的键名(通常是一个列表,包含多个对话回合)

    • "tags": 一个嵌套字典,用于指定在对话回合中每个字段的键名,例如角色(role)、内容(content)等,以及用户、助手和系统角色的标签。

      示例:

      --map-keys '{"messages":"messages", "tags":{"role_tag":"role", "content_tag":"content", "user_tag":"user", "assistant_tag":"assistant", "system_tag":"system"}}'

      说明:在这个例子中,输入数据中对话列表的键名为"messages"。在每一个对话回合中,角色字段的键名为"role",内容字段的键名为"content",而用户、助手和系统消息则分别用"user"、"assistant"和"system"来标识(这些标签用于区分消息发送者)。

注意:由于--map-keys参数是一个JSON字符串,所以需要用单引号括起来(在shell中),并且确保内部双引号被正确转义或保留(这里使用的是JSON字符串,所以内部用双引号)。

3.2. 处理结果

数据预处理脚本会将数据按照相应的数据风格进行解析,并且根据prompt-type所对应的模板构建成为prompt,再转化为token后保存到.bin .idx 文件中。下图是解析后的文件示例。

image-20250806164146977

四、 权重准备

4.1. 模型权重下载

从HuggingFace下载模型权重Qen2.5-3B-Instruct,下载方式参考HF镜像站,其他模型下载可参考Dense模型、MOE模型和SSM模型文档中对应模型的下载链接。下载完成效果如下:

image-20251218162207909

4.2. 权重转换

随着大规模预训练模型的广泛应用,不同的训练框架和硬件平台之间的适配性问题逐渐显现。专有训练框架如MindSpeed-LLM通常采用定制的并行化策略(例如Tensor Parallelism、Pipeline Parallelism)以应对大规模模型训练中的内存和计算瓶颈。随着训练需求和硬件的变化,模型参数的切分策略也需进行相应的调整。然而,跨框架的权重转换往往面临格式不兼容和切分策略不同等挑战。权重转换旨在促进大规模预训练模型在不同训练框架之间的无缝迁移与评估,解决框架间权重格式不兼容及切分策略差异等问题,从而增强模型迁移的灵活性和可扩展性,支持更广泛的应用场景和业务需求。

权重转换实现了 HuggingFace 权重到 Megatron-LM 格式的转换,支持多种并行策略(如张量并行、流水并行等),确保转换后可以在 MindSpeed-LLM 框架下继续训练和推理。

4.2.1. 全参微调

当前采用TP=2,PP=1进行权重切分。权重切分具体代码如下:

# 切换MindspeedLLM路径
cd /src/train25.1.0/MindSpeed-LLM
source /usr/local/Ascend/ascend-toolkit/set_env.sh

echo "============== start convert_ckpt ================"
# 设置需要的权重转换参数
python convert_ckpt.py \
       --use-mcore-models \
       --model-type GPT \
       --load-model-type hf \
       --save-model-type mg \
       --target-tensor-parallel-size 2 \
       --target-pipeline-parallel-size 1 \
       --add-qkv-bias \
       --load-dir /data/***/Qwen2.5-3B-Instruct/ \
       --save-dir /data/private/models_mg/Qwen2.5-3B-Instruct_tp2_pp1/ \
       --tokenizer-model  /data/***/Qwen2.5-3B-Instruct/tokenizer.json \
       --model-type-hf llama2 \
       --params-dtype bf16
参数说明可选/必选
--target-tensor-parallel-sizeTP 切分数量,默认为 1必选
--target-pipeline-parallel-sizePP 切分数量,默认为 1必选
--num-layer-list动态PP划分,通过列表指定每个PP Stage的层数,默认为None可选
--num-layers-per-virtual-pipeline-stageVPP划分,指定VPP的每个Stage层数,默认为None可选
--target-expert-model-parallel-size专家并行,指定专家并行卡数,默认为1可选
--noop-layers自定义空层操作,指定在模型某层增加空层,转换后层数为原huggingface模型层数+空层数,默认为None可选
--use-mcore-models转换为Megatron-Mcore权重,若不指定,则默认转换为Megatron-Legacy权重可选
--model-type-hfhuggingface模型类别,默认为llama2,参考注意 2可选
--tokenizer-model需要指明到具体的分词器模型文件,如 tokenizer.model、tokenizer.json、qwen.tiktoken、None等,具体取决于huggingface中词表文件的格式形式必选
--params-dtype指定权重转换后的权重精度模式,默认为fp16,如果源格式文件为bf16,则需要对应设置为bf16,影响推理或评估结果必选

注意:

  1. VPP和动态PP划分只能二选一

  2. 目前支持的模型见 model_cfg.json中“model_mappings”下包含的模型。

关键参数说明:

qwen2.5模型这里的--model-type-hf需要设置为:llama2。参考目前支持的模型 model_cfg.json中“model_mappings”下包含的模型参数映射关系。

执行结果如下:

image-20251218162655149

五、 模型训练

5.1. 全参微调

全参官方参考链接: 大模型指令微调

5.1.1. 训练脚本

#!/bin/bash
# 脚本名:/data/private/scripts/llm/qwen25-3b-instruct/tune_qwen25_3b_4k_full_ptd.sh
cd /src/train25.1.0/MindSpeed-LLM
source /usr/local/Ascend/ascend-toolkit/set_env.sh

export HCCL_CONNECT_TIMEOUT=1200
export CUDA_DEVICE_MAX_CONNECTIONS=1
export ASCEND_RT_VISIBLE_DEVICES=0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15

NPUS_PER_NODE=16
MASTER_ADDR=localhost
MASTER_PORT=2901
NNODES=1
NODE_RANK=0
WORLD_SIZE=$(($NPUS_PER_NODE*$NNODES))

mkdir -p /data/private/outputs/llm/qwen2.5-3b-instruct/logs
echo "============== start train ================"

# please fill these path configurations
CKPT_LOAD_DIR="/data/private/models_mg/Qwen2.5-3B-Instruct_tp2_pp1/"
CKPT_SAVE_DIR="/data/private/models_mg/ckpt/Qwen2.5-3B-Instruct_tp2_pp1/"
DATA_PATH=""
TOKENIZER_PATH="/data/***/Qwen2.5-3B-Instruct"
tensorboard_dir="/data/private/outputs/llm/qwen2.5-3b-instruct/logs/tensorboard_dir/full"
train_log_path="/data/private/outputs/llm/qwen2.5-3b-instruct/logs/tune_mcore_qwen25_3b_full_tp2_pp1_train.log"

TP=2
PP=1
MBS=8
GBS=128
SEQ_LEN=2048
TRAIN_ITERS=400

DISTRIBUTED_ARGS="
    --nproc_per_node $NPUS_PER_NODE \
    --nnodes $NNODES \
    --node_rank $NODE_RANK \
    --master_addr $MASTER_ADDR \
    --master_port $MASTER_PORT
"
    
GPT_ARGS="
    --finetune \
    --stage sft \
    --is-instruction-dataset \
    --tokenizer-not-use-fast \
    --prompt-type qwen \
    --variable-seq-lengths \
    --use-mcore-models \
    --tensor-model-parallel-size ${TP} \
    --pipeline-model-parallel-size ${PP} \
    --num-layers 36 \
    --hidden-size 2048 \
    --ffn-hidden-size 11008 \
    --num-attention-heads 16 \
    --group-query-attention \
    --num-query-groups 2 \
    --tokenizer-type PretrainedFromHF \
    --tokenizer-name-or-path ${TOKENIZER_PATH} \
    --seq-length ${SEQ_LEN} \
    --max-position-embeddings ${SEQ_LEN} \
    --micro-batch-size ${MBS} \
    --global-batch-size ${GBS} \
    --make-vocab-size-divisible-by 1 \
    --padded-vocab-size 151936 \
    --rotary-base 1000000 \
    --train-iters ${TRAIN_ITERS} \
    --lr 1.0e-5 \
    --weight-decay 0.0 \
    --lr-decay-style cosine \
    --clip-grad 1.0 \
    --adam-beta1 0.9 \
    --adam-beta2 0.999 \
    --add-qkv-bias \
    --disable-bias-linear \
    --attention-dropout 0.0 \
    --init-method-std 0.02 \
    --hidden-dropout 0.0 \
    --position-embedding-type rope \
    --normalization RMSNorm \
    --norm-epsilon 1e-06 \
    --swiglu \
    --use-flash-attn \
    --use-rotary-position-embeddings \
    --no-masked-softmax-fusion \
    --attention-softmax-in-fp32 \
    --initial-loss-scale 4096 \
    --no-gradient-accumulation-fusion \
    --no-load-optim \
    --no-load-rng \
    --seed 42 \
    --bf16\
    --tensorboard-dir $tensorboard_dir \
"

DATA_ARGS="
    --data-path $DATA_PATH \
    --split 100,0,0
"

OUTPUT_ARGS="
    --log-interval 1 \
    --save-interval 2000 \
    --eval-interval 2000 \
    --eval-iters 0 \
"

torchrun $DISTRIBUTED_ARGS posttrain_gpt.py \
    $GPT_ARGS \
    $DATA_ARGS \
    $OUTPUT_ARGS \
    --distributed-backend nccl \
    --load ${CKPT_LOAD_DIR} \
    --save ${CKPT_SAVE_DIR} \
    2>&1 | tee $train_log_path

5.1.2. 启动脚本

cd ***/MindSpeed-LLM
bash /data/private/scripts/llm/qwen25-3b-instruct/tune_qwen25_3b_4k_full_ptd.sh

5.1.3. 训练Loss曲线

如下图所示,loss曲线正常下降。

image-20251218163636354

5.1.4. 精度测试

NPU设备上业务数据集评分结果如下图所示,精度满足客户需求。

image-20251218163015366