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

Qwen2.5-VL-32B-Instruct迁移昇腾MindSpeed-MM微调

目录

  • 简介

  • 环境配置

    • 环境搭建
  • 权重获取及转换

    • 权重下载
    • 权重转换hf2mm
  • 数据集准备及处理

    • 数据集格式
    • 数据集转换
  • 微调

    • 准备工作
    • 配置参数
    • 启动微调
    • LoRA权重合并
  • 环境变量声明

  • 注意事项


简介

🍲 MindSpeed MM是面向大规模分布式训练的昇腾多模态大模型套件,同时支持多模态生成及多模态理解,旨在为华为 昇腾芯片 提供端到端的多模态训练解决方案, 包含预置业界主流模型,数据工程,分布式训练及加速,预训练、微调、在线推理任务等特性。

本篇文档参考官方仓库文档,结合项目实践,介绍基于MindSpeed-MM的多模态大模型微调方法。 使用方法:将tasks目录放到MindSpeed-MM目录下面

环境配置

【模型开发时推荐使用配套的环境版本】

请参考: https://gitee.com/ascend/MindSpeed-MM/blob/master/docs/user-guide/installation.md

环境搭建

裸机

在裸机上,建议使用docker容器进行模型微调

ModelArts

在MA平台上,采用训练作业来进行模型训练,需要熟悉MA平台的使用方法


权重获取及转换

1. 权重获取

从Huggingface库下载对应的模型权重:

  • 模型地址: Qwen2.5-VL-7B;
  • 模型地址: Qwen2.5-VL-32B;
  • 模型地址: Qwen2.5-VL-72B;

将下载的模型权重保存到本地的ckpt/hf_path/Qwen2.5-VL-*B-Instruct目录下。(*表示对应的尺寸)

2. 权重转换(hf2mm)

MindSpeed-MM修改了部分原始网络的结构名称,需要使用mm-convert工具对原始预训练权重进行转换。该工具实现了huggingface权重和MindSpeed-MM权重的互相转换以及PP(Pipeline Parallel)权重的重切分。工具使用请参考权重转换工具

下面提供了一个权重转换的样例和代码

# 这是一个切分pipeline并行8卡的样例
mm-convert  Qwen2_5_VLConverter hf_to_mm \
  --cfg.mm_dir "ckpt/mm_path/Qwen2.5-VL-32B-Instruct" \
  --cfg.hf_config.hf_dir "ckpt/hf_path/Qwen2.5-VL-32B-Instruct" \
  --cfg.parallel_config.llm_pp_layers [[4,9,9,9,9,9,9,6]] \
  --cfg.parallel_config.vit_pp_layers [[32,0,0,0,0,0,0,0]] \
  --cfg.parallel_config.tp_size 2

# 其中:
# mm_dir: 转换后保存目录
# hf_dir: huggingface权重目录
# llm_pp_layers: llm在每个卡上切分的层数,注意要和model.json中配置的pipeline_num_layers一致
# vit_pp_layers: vit在每个卡上切分的层数,注意要和model.json中配置的pipeline_num_layers一致
# tp_size: tp并行数量,注意要和微调启动脚本中的配置一致

如果需要用转换后模型训练,需要同步修改tasks/qwen2.5vl/finetune_qwen2_5_vl.sh中的LOAD_PATH参数,该路径为转换后或者切分后的权重,注意与原始权重 ckpt/hf_path/Qwen2.5-VL-32B-Instruct进行区分。

LOAD_PATH="ckpt/mm_path/Qwen2.5-VL-32B-Instruct"

数据集准备及处理

1. 数据集格式

在数据构造时,对于包含图片的数据,需要保留image这个键值。 这是例子中的原始数据格式

{
  "id": your_id,
  "image": your_image_path,
  "conversations": [
      {"from": "human", "value": your_query},
      {"from": "gpt", "value": your_response},
  ],
}

MindSpeed-MM的格式如下:

new_item = {
    "images": [],
    "messages": [
      {"role": "user", "content": "value"},
      {"role": "assistant", "content": "value"}
    ]
} 

2. 数据集转换

运行数据转换脚本python examples/qwen2vl/llava_instruct_2_mllm_demo_format.py;

注意:这个脚本在MindSpeed-MM代码仓内


配置方式为data.json中 dataset_param->basic_parameters->dataset 配置数据集json路径

同时注意data.json中dataset_param->basic_parameters->max_samples的配置,会限制数据只读max_samples条,这样可以快速验证功能。如果正式训练时,可以把该参数去掉则读取全部的数据。


微调

1. 准备工作

配置脚本前需要完成前置准备工作,包括:环境安装、权重下载及转换、数据集准备及处理,详情可查看对应章节。

2. 配置参数

【数据目录配置】

根据实际情况修改data.json中的数据集路径,包括model_name_or_path、dataset_dir、dataset等字段。

以Qwen2.5VL-32B为例,data.json进行以下修改,注意model_name_or_path的权重路径为转换前的权重路径。

注意cache_dir在多机上不要配置同一个挂载目录避免写入同一个文件导致冲突。

{
    "dataset_param": {
        "dataset_type": "huggingface",
        "preprocess_parameters": {
            "model_name_or_path": "./ckpt/hf_path/Qwen2.5-VL-32B-Instruct",
            ...
        },
        "basic_parameters": {
            ...
            "dataset_dir": "./data",
            "dataset": "./data/your_data.json",
            "cache_dir": "./data/cache_dir",
            ...
        },
        ...
    },
    ...
}

"dataset": 当有多个数据文件时,可以用,隔开,例如"data/your_data1.json,data/your_data2.json"

【LoRA参数配置】

  • --load 若不指定该参数加载权重,模型会随机初始化权重。

  • --lora-r LoRA rank,表示低秩矩阵的维度。较低的 rank 值模型在训练时会使用更少的参数更新,从而减少计算量和内存消耗。然而,过低的 rank 可能限制模型的表达能力。

  • --lora-alpha 控制 LoRA 权重对原始权重的影响比例, 数值越高则影响越大。一般保持 α/r 为 2。

  • --lora-dropout 在 LoRA 模块中dropout的比例,默认为0。

  • --lora-target-modules 选择需要添加 LoRA 的模块。 mcore 模型模块: linear_qkv, linear_proj, linear_fc1, linear_fc2; 多模态场景下需根据模型结构选择上述微调模块。

  • --save 模型权重保存路径,开启 LoRA 微调的情况下,只保存微调模块的权重。

【模型保存加载及日志信息配置】

根据实际情况配置tasks/qwen2.5vl/finetune_qwen2_5_vl.sh的参数,包括加载、保存路径以及保存间隔--save-interval(注意:分布式优化器保存文件较大耗时较长,请谨慎设置保存间隔)

...
# 加载路径
LOAD_PATH="ckpt/mm_path/Qwen2.5-VL-32B-Instruct"
# 保存路径
SAVE_PATH="save_dir"
...
GPT_ARGS="
    ...
    --no-load-optim \  # 不加载优化器状态,若需加载请移除
    --no-load-rng \  # 不加载随机数状态,若需加载请移除
    --no-save-optim \  # 不保存优化器状态,若需保存请移除
    --no-save-rng \  # 不保存随机数状态,若需保存请移除
    ...
"
...
OUTPUT_ARGS="
    --log-interval 1 \  # 日志间隔
    --save-interval 5000 \  # 保存间隔
    ...
    --log-tps \  # 增加此参数可使能在训练中打印每步语言模块的平均序列长度,并在训练结束后计算每秒吞吐tokens量。
"

若需要加载指定迭代次数的权重、优化器等状态,需将加载路径LOAD_PATH设置为保存文件夹路径LOAD_PATH="save_dir",并修改latest_checkpointed_iteration.txt文件内容为指定迭代次数 (此功能coming soon)

$save_dir
   ├── latest_checkpointed_iteration.txt
   ├── ...

【单机运行配置】

配置tasks/qwen2.5vl/finetune_qwen2_5_vl.sh参数如下

# 根据实际情况修改 ascend-toolkit 路径
source /usr/local/Ascend/ascend-toolkit/set_env.sh
NPUS_PER_NODE=8
MASTER_ADDR=localhost
MASTER_PORT=29501
NNODES=1
NODE_RANK=0
WORLD_SIZE=$(($NPUS_PER_NODE * $NNODES))

注意,当开启PP时,model.json中配置的vision_encoder和text_decoder的pipeline_num_layer参数控制了各自的PP切分策略。

3. 启动微调

LoRA 微调

LoRA为框架通用能力,当前功能已支持,可参考LoRA特性文档。

MindSpeed-MM LoRA微调使能方法:

在模型shell脚本中增加 LORA 微调参数。 例如,可在Qwen2.5-VL的微调任务脚本中增加--lora-target-modules参数,使能 LoRA 。

--lora-target-modules linear_qkv linear_proj linear_fc1 linear_fc2

以Qwen2.5VL-32B为例,启动微调训练任务。

bash tasks/qwen2.5vl/finetune_qwen2_5_vl.sh

【MA运行配置】

bash $MA_JOB_DIR/your_code/Mindspeed-MM/tasks/qwen2.5vl/run_exp_MA.sh

LoRA 权重合并

LoRA权重和原始权重合并方法: 例如,可在Qwen2.5-VL的合并脚本merge_lora中设置参数执行合并,其中base_save_dir,lora_save_dir,merge_save_dir分别设置为原始权重目录,LoRA权重目录,合并权重保存目录,use_npu设置是否启用npu加速。 LoRA相关参数lora_target_modules, lora_alpha, lora_r需要和训练时设置保持一致 同理,模型相关参数pp_size, tp_size需要和训练时设置保持一致

脚本路径(MindSpeed-MM代码仓):examples/qwen2vl/merge_lora.py 脚本里主要设置的参数如下

base_save_dir = "your-base-model-path"
lora_save_dir = "your-lora-model-path"
merge_save_dir = "your-merge-model-path"
lora_target_modules = ['linear_qkv', 'linear_proj', 'linear_fc1', 'linear_fc2']

lora_alpha = 16 # 需要和训练时设置保持一致
lora_r = 8
scaling = lora_alpha / lora_r

# PP parameters: 32B
pp_size = 8
tp_size = 2

训练后权重转回huggingface格式

MindSpeed-MM修改了部分原始网络的结构名称,在微调后,如果需要将权重转回huggingface格式,可使用mm-convert权重转换工具对微调后的权重进行转换,将权重名称修改为与原始网络一致。 注意:如果使用了LoRA微调,需要先进行LoRA权重合并至mm模型,再进行转换。

mm-convert  Qwen2_5_VLConverter mm_to_hf \
  --cfg.save_hf_dir "ckpt/mm_to_hf/Qwen2.5-VL-32B-Instruct" \
  --cfg.mm_dir "ckpt/mm_path/Qwen2-VL-32B-Instruct" \
  --cfg.hf_config.hf_dir "ckpt/hf_path/Qwen2.5-VL-32B-Instruct" \
  --cfg.parallel_config.llm_pp_layers [4,9,9,9,9,9,9,6] \
  --cfg.parallel_config.vit_pp_layers [32,0,0,0,0,0,0,0] \
  --cfg.parallel_config.tp_size 2
# 其中:
# save_hf_dir: mm微调后转换回hf模型格式的目录
# mm_dir: 微调后保存的权重目录
# hf_dir: huggingface权重目录
# llm_pp_layers: llm在每个卡上切分的层数,注意要和微调时model.json中配置的pipeline_num_layers一致
# vit_pp_layers: vit在每个卡上切分的层数,注意要和微调时model.json中配置的pipeline_num_layers一致
# tp_size: tp并行数量,注意要和微调启动脚本中的配置一致

参考脚本代码:作战包

tasks/qwen2.5vl/merge_ckpt_MA.sh


环境变量声明

NPUS_PER_NODE: 配置一个计算节点上使用的NPU数量


注意事项

  1. 在 finetune_xx.sh里,与模型结构相关的参数并不生效,以examples/qwen2.5vl/model_xb.json里同名参数配置为准,非模型结构的训练相关参数在 finetune_xx.sh修改。