已合并
[Feature] add qwen3vl 8b #1676
yangx_sy创建于 2025年10月31日
[Feature] add qwen3vl 8b #1676
已合并
共 7 个文件变更+232-24
| @@ -127,11 +127,11 @@ mm-convert Qwen3VLConverter hf_to_dcp \ | |||
| 127 | ``` | 127 | ``` |
| 128 | 128 | ||
| 129 | --- | 129 | --- |
| 130 | -当前支持读取多个以`,`(注意不要加空格)分隔的数据集,配置方式为`data.json`中 | 130 | +当前支持读取多个以`,`(注意不要加空格)分隔的数据集,配置方式为`data_xxB.json`中 |
| 131 | dataset_param->basic_parameters->dataset | 131 | dataset_param->basic_parameters->dataset |
| 132 | 从"./data/mllm_format_llava_instruct_data.json"修改为"./data/mllm_format_llava_instruct_data.json,./data/mllm_format_llava_instruct_data2.json" | 132 | 从"./data/mllm_format_llava_instruct_data.json"修改为"./data/mllm_format_llava_instruct_data.json,./data/mllm_format_llava_instruct_data2.json" |
| 133 | 133 | ||
| 134 | -同时注意`data.json`中`dataset_param->basic_parameters->max_samples`的配置,会限制数据只读`max_samples`条,这样可以快速验证功能。如果正式训练时,可以把该参数去掉则读取全部的数据。 | 134 | +同时注意`data_xxB.json`中`dataset_param->basic_parameters->max_samples`的配置,会限制数据只读`max_samples`条,这样可以快速验证功能。如果正式训练时,可以把该参数去掉则读取全部的数据。 |
| 135 | 135 | ||
| 136 | <a id="jump3.2"></a> | 136 | <a id="jump3.2"></a> |
| 137 | #### 2.纯文本或有图无图混合训练数据(以LLaVA-Instruct-150K为例) | 137 | #### 2.纯文本或有图无图混合训练数据(以LLaVA-Instruct-150K为例) |
| @@ -176,14 +176,14 @@ dataset_param->basic_parameters->dataset | |||
| 176 | 176 | ||
| 177 | 【数据目录配置】 | 177 | 【数据目录配置】 |
| 178 | 178 | ||
| 179 | -根据实际情况修改`data.json`中的数据集路径,包括`model_name_or_path`、`dataset_dir`、`dataset`等字段。 | 179 | +根据实际情况修改`data_xxB.json`中的数据集路径,包括`model_name_or_path`、`dataset_dir`、`dataset`等字段。 |
| 180 | 180 | ||
| 181 | 示例:如果数据及其对应的json都在/home/user/data/目录下,其中json目录为/home/user/data/video_data_path.json,此时配置如下: | 181 | 示例:如果数据及其对应的json都在/home/user/data/目录下,其中json目录为/home/user/data/video_data_path.json,此时配置如下: |
| 182 | `dataset_dir`配置为/home/user/data/; | 182 | `dataset_dir`配置为/home/user/data/; |
| 183 | `dataset`配置为./data/video_data_path.json | 183 | `dataset`配置为./data/video_data_path.json |
| 184 | 注意此时`dataset`需要配置为相对路径 | 184 | 注意此时`dataset`需要配置为相对路径 |
| 185 | 185 | ||
| 186 | -以Qwen3VL-xxB为例,`data.json`进行以下修改,注意`model_name_or_path`的权重路径为转换前的权重路径。 | 186 | +以Qwen3VL-xxB为例,`data_xxB.json`进行以下修改,注意`model_name_or_path`的权重路径为转换前的权重路径,即原始hf权重路径。 |
| 187 | 187 | ||
| 188 | **注意`cache_dir`在多机上不要配置同一个挂载目录避免写入同一个文件导致冲突**。 | 188 | **注意`cache_dir`在多机上不要配置同一个挂载目录避免写入同一个文件导致冲突**。 |
| 189 | 189 | ||
| @@ -208,7 +208,7 @@ dataset_param->basic_parameters->dataset | |||
| 208 | } | 208 | } |
| 209 | ``` | 209 | ``` |
| 210 | 210 | ||
| 211 | -如果需要加载大批量数据,可使用流式加载,修改`data.json`中的`sampler_type`字段,增加`streaming`字段。(注意:使用流式加载后当前仅支持`num_workers=0`,单进程处理数据,会有性能波动,并且不支持断点续训功能。) | 211 | +如果需要加载大批量数据,可使用流式加载,修改`data_xxB.json`中的`sampler_type`字段,增加`streaming`字段。(注意:使用流式加载后当前仅支持`num_workers=0`,单进程处理数据,会有性能波动,并且不支持断点续训功能。) |
| 212 | 212 | ||
| 213 | 213 | ||
| 214 | ```json | 214 | ```json |
| @@ -233,7 +233,7 @@ dataset_param->basic_parameters->dataset | |||
| 233 | 233 | ||
| 234 | 【模型保存加载及日志信息配置】 | 234 | 【模型保存加载及日志信息配置】 |
| 235 | 235 | ||
| 236 | -根据实际情况配置`examples/qwen3vl/finetune_qwen3vl.sh`的参数,包括加载、保存路径以及保存间隔`--save-interval`(注意:分布式优化器保存文件较大耗时较长,请谨慎设置保存间隔) | 236 | +根据实际情况配置`examples/qwen3vl/finetune_qwen3vl_xxB.sh`的参数,包括加载、保存路径以及保存间隔`--save-interval`(注意:分布式优化器保存文件较大耗时较长,请谨慎设置保存间隔) |
| 237 | 237 | ||
| 238 | ```shell | 238 | ```shell |
| 239 | ... | 239 | ... |
| @@ -254,16 +254,17 @@ GPT_ARGS=" | |||
| 254 | OUTPUT_ARGS=" | 254 | OUTPUT_ARGS=" |
| 255 | --log-interval 1 \ # 日志间隔 | 255 | --log-interval 1 \ # 日志间隔 |
| 256 | --save-interval 5000 \ # 保存间隔 | 256 | --save-interval 5000 \ # 保存间隔 |
| 257 | - ... | 257 | + --save $SAVE_PATH \ # 保存路径 |
| 258 | " | 258 | " |
| 259 | ``` | 259 | ``` |
| 260 | 260 | ||
| 261 | -根据实际情况配置`examples/qwen3vl/model.json`中的`init_from_hf_path`参数,该参数表示初始权重的加载路径。 | 261 | +根据实际情况配置`examples/qwen3vl/model_xxB.json`中的`init_from_hf_path`参数,该参数表示初始权重的加载路径。 |
| 262 | -根据实际情况配置`examples/qwen3vl/model.json`中的`image_encoder.vision_encoder.freeze`、`image_encoder.vision_projector.freeze`、`text_decoder.freeze`参数,该参数分别代表是否冻结vision model模块、projector模块、及language model模块。 | 262 | +根据实际情况配置`examples/qwen3vl/model_xxB.json`中的`image_encoder.vision_encoder.freeze`、`image_encoder.vision_projector.freeze`、`text_decoder.freeze`参数,该参数分别代表是否冻结vision model模块、projector模块、及language model模块。 |
| 263 | +注:当前`examples/qwen3vl/model_xxB.json`中点各网络层数均为未过校验的无效配置,如需减层请修改原始hf路径下相关配置文件。 | ||
| 263 | 264 | ||
| 264 | 【单机运行配置】 | 265 | 【单机运行配置】 |
| 265 | 266 | ||
| 266 | -配置`examples/qwen3vl/finetune_qwen3vl.sh`参数如下 | 267 | +配置`examples/qwen3vl/finetune_qwen3vl_xxB.sh`参数如下 |
| 267 | 268 | ||
| 268 | ```shell | 269 | ```shell |
| 269 | # 根据实际情况修改 ascend-toolkit 路径 | 270 | # 根据实际情况修改 ascend-toolkit 路径 |
| @@ -282,7 +283,7 @@ WORLD_SIZE=$(($NPUS_PER_NODE * $NNODES)) | |||
| 282 | 以Qwen3VL-xxB为例,启动微调训练任务。 | 283 | 以Qwen3VL-xxB为例,启动微调训练任务。 |
| 283 | 284 | ||
| 284 | ```shell | 285 | ```shell |
| 285 | -bash examples/qwen3vl/finetune_qwen3vl.sh | 286 | +bash examples/qwen3vl/finetune_qwen3vl_xxB.sh |
| 286 | ``` | 287 | ``` |
| 287 | --- | 288 | --- |
| 288 | 289 | ||
| @@ -2,7 +2,7 @@ | |||
| 2 | "dataset_param": { | 2 | "dataset_param": { |
| 3 | "dataset_type": "huggingface", | 3 | "dataset_type": "huggingface", |
| 4 | "preprocess_parameters": { | 4 | "preprocess_parameters": { |
| 5 | - "model_name_or_path": "./ckpt/hf_path/Qwen3-VL-xxB-Instruct", | 5 | + "model_name_or_path": "./ckpt/hf_path/Qwen3-VL-30B-Instruct", |
| 6 | "use_fast_tokenizer": true, | 6 | "use_fast_tokenizer": true, |
| 7 | "split_special_tokens": false, | 7 | "split_special_tokens": false, |
| 8 | "image_max_pixels": 262144, | 8 | "image_max_pixels": 262144, |
| @@ -0,0 +1,54 @@ | |||
| 1 | +{ | ||
| 2 | + "dataset_param": { | ||
| 3 | + "dataset_type": "huggingface", | ||
| 4 | + "preprocess_parameters": { | ||
| 5 | + "model_name_or_path": "./ckpt/hf_path/Qwen3-VL-8B-Instruct", | ||
| 6 | + "use_fast_tokenizer": true, | ||
| 7 | + "split_special_tokens": false, | ||
| 8 | + "image_max_pixels": 262144, | ||
| 9 | + "image_min_pixels": 1024, | ||
| 10 | + "video_max_pixels": 16384, | ||
| 11 | + "video_min_pixels": 0, | ||
| 12 | + "video_fps": 2.0, | ||
| 13 | + "video_maxlen": 64 | ||
| 14 | + }, | ||
| 15 | + "basic_parameters": { | ||
| 16 | + "template": "qwen3_vl_nothink", | ||
| 17 | + "dataset_dir": "./data", | ||
| 18 | + "dataset": "./data/mllm_format_llava_instruct_data.json", | ||
| 19 | + "cache_dir": "./data/cache_dir", | ||
| 20 | + "enable_thinking": false, | ||
| 21 | + "overwrite_cache": false, | ||
| 22 | + "train_on_prompt": false, | ||
| 23 | + "mask_history": false, | ||
| 24 | + "preprocessing_batch_size": 1000, | ||
| 25 | + "preprocessing_num_workers": 16, | ||
| 26 | + "max_samples": null, | ||
| 27 | + "tool_format": null | ||
| 28 | + }, | ||
| 29 | + "attr": { | ||
| 30 | + "system": null, | ||
| 31 | + "images": "images", | ||
| 32 | + "videos": null, | ||
| 33 | + "messages": "messages", | ||
| 34 | + "role_tag": "role", | ||
| 35 | + "content_tag": "content", | ||
| 36 | + "user_tag": "user", | ||
| 37 | + "assistant_tag": "assistant", | ||
| 38 | + "observation_tag": null, | ||
| 39 | + "function_tag": null, | ||
| 40 | + "system_tag": null | ||
| 41 | + } | ||
| 42 | + }, | ||
| 43 | + "dataloader_param": { | ||
| 44 | + "dataloader_mode": "sampler", | ||
| 45 | + "drop_last": true, | ||
| 46 | + "sampler_type": "BaseRandomBatchSampler", | ||
| 47 | + "collate_param": { | ||
| 48 | + "model_name": "qwen3vl", | ||
| 49 | + "ignore_pad_token_for_loss": true | ||
| 50 | + }, | ||
| 51 | + "pin_memory": true, | ||
| 52 | + "shuffle": true | ||
| 53 | + } | ||
| 54 | +} | ||
| @@ -0,0 +1,122 @@ | |||
| 1 | +#!/bin/bash | ||
| 2 | + | ||
| 3 | +source /usr/local/Ascend/ascend-toolkit/set_env.sh | ||
| 4 | +# 该变量只用于规避megatron对其校验,对npu无效 | ||
| 5 | +export CUDA_DEVICE_MAX_CONNECTIONS=2 # 开启FSDP2时,不能置为1 | ||
| 6 | +export ASCEND_SLOG_PRINT_TO_STDOUT=0 | ||
| 7 | +export ASCEND_GLOBAL_LOG_LEVEL=3 | ||
| 8 | +export TASK_QUEUE_ENABLE=2 | ||
| 9 | +export COMBINED_ENABLE=1 | ||
| 10 | +export CPU_AFFINITY_CONF=1 | ||
| 11 | +export HCCL_CONNECT_TIMEOUT=1200 | ||
| 12 | +export NPU_ASD_ENABLE=0 | ||
| 13 | +export ASCEND_LAUNCH_BLOCKING=0 | ||
| 14 | +export ACLNN_CACHE_LIMIT=100000 | ||
| 15 | +export TOKENIZERS_PARALLELISM=false | ||
| 16 | +export PYTORCH_NPU_ALLOC_CONF=expandable_segments:True | ||
| 17 | + | ||
| 18 | +# export HCCL_SOCKET_IFNAME= | ||
| 19 | +# export GLOO_SOCKET_IFNAME= | ||
| 20 | +# export ASCEND_RT_VISIBLE_DEVICES= | ||
| 21 | + | ||
| 22 | +NPUS_PER_NODE=16 | ||
| 23 | +MASTER_ADDR=localhost | ||
| 24 | +MASTER_PORT=6000 | ||
| 25 | +NNODES=1 | ||
| 26 | +NODE_RANK=0 | ||
| 27 | +WORLD_SIZE=$(($NPUS_PER_NODE*$NNODES)) | ||
| 28 | + | ||
| 29 | + | ||
| 30 | +MM_DATA="./examples/qwen3vl/data_30B.json" | ||
| 31 | +MM_MODEL="./examples/qwen3vl/model_30B.json" | ||
| 32 | +MM_TOOL="./mindspeed_mm/tools/tools.json" | ||
| 33 | +LOAD_PATH="ckpt/mm_path/Qwen3-VL-30B-Instruct" | ||
| 34 | +SAVE_PATH="save_dir" | ||
| 35 | +FSDP2_PATH="./examples/qwen3vl/fsdp2_config.yaml" | ||
| 36 | + | ||
| 37 | +TP=1 | ||
| 38 | +PP=1 | ||
| 39 | +CP=1 | ||
| 40 | +MBS=1 | ||
| 41 | +GRAD_ACC_STEP=1 | ||
| 42 | +SEQ_LEN=1024 | ||
| 43 | +DP=$(($WORLD_SIZE/$TP/$PP/$CP)) | ||
| 44 | +GBS=$(($MBS*$GRAD_ACC_STEP*$DP)) | ||
| 45 | + | ||
| 46 | + | ||
| 47 | +DISTRIBUTED_ARGS=" | ||
| 48 | + --nproc_per_node $NPUS_PER_NODE \ | ||
| 49 | + --nnodes $NNODES \ | ||
| 50 | + --node_rank $NODE_RANK \ | ||
| 51 | + --master_addr $MASTER_ADDR \ | ||
| 52 | + --master_port $MASTER_PORT | ||
| 53 | +" | ||
| 54 | + | ||
| 55 | +# GPT_ARGS中模型相关参数具体配置在example/qwen2vl/model_xb.json中,训练相关参数配置在这里 | ||
| 56 | +GPT_ARGS=" | ||
| 57 | + --use-mcore-models \ | ||
| 58 | + --tensor-model-parallel-size ${TP} \ | ||
| 59 | + --pipeline-model-parallel-size ${PP} \ | ||
| 60 | + --context-parallel-size ${CP} \ | ||
| 61 | + --context-parallel-algo ulysses_cp_algo \ | ||
| 62 | + --micro-batch-size ${MBS} \ | ||
| 63 | + --global-batch-size ${GBS} \ | ||
| 64 | + --tokenizer-type NullTokenizer \ | ||
| 65 | + --vocab-size 152064 \ | ||
| 66 | + --seq-length ${SEQ_LEN} \ | ||
| 67 | + --make-vocab-size-divisible-by 1 \ | ||
| 68 | + --normalization RMSNorm \ | ||
| 69 | + --use-fused-rmsnorm \ | ||
| 70 | + --swiglu \ | ||
| 71 | + --use-fused-swiglu \ | ||
| 72 | + --no-masked-softmax-fusion \ | ||
| 73 | + --lr 1.0e-5 \ | ||
| 74 | + --lr-decay-style cosine \ | ||
| 75 | + --weight-decay 0 \ | ||
| 76 | + --train-iters 10000 \ | ||
| 77 | + --lr-warmup-fraction 0.1 \ | ||
| 78 | + --clip-grad 0.0 \ | ||
| 79 | + --adam-beta1 0.9 \ | ||
| 80 | + --adam-beta2 0.999 \ | ||
| 81 | + --no-gradient-accumulation-fusion \ | ||
| 82 | + --seed 42 \ | ||
| 83 | + --load $LOAD_PATH \ | ||
| 84 | + --use-flash-attn \ | ||
| 85 | + --no-load-optim \ | ||
| 86 | + --no-load-rng \ | ||
| 87 | + --no-save-optim \ | ||
| 88 | + --no-save-rng \ | ||
| 89 | + --num-workers 8 \ | ||
| 90 | + --use-torch-fsdp2 \ | ||
| 91 | + --untie-embeddings-and-output-weights \ | ||
| 92 | + --ckpt-format torch_dcp \ | ||
| 93 | + --fsdp2-config-path $FSDP2_PATH \ | ||
| 94 | + --optimizer-selection fused_torch_adamw \ | ||
| 95 | + --use-cpu-initialization \ | ||
| 96 | + --calculate-per-token-loss \ | ||
| 97 | +" | ||
| 98 | + | ||
| 99 | +MM_ARGS=" | ||
| 100 | + --mm-data $MM_DATA \ | ||
| 101 | + --mm-model $MM_MODEL \ | ||
| 102 | + --mm-tool $MM_TOOL | ||
| 103 | +" | ||
| 104 | + | ||
| 105 | +OUTPUT_ARGS=" | ||
| 106 | + --log-interval 1 \ | ||
| 107 | + --save-interval 10000 \ | ||
| 108 | + --eval-interval 10000 \ | ||
| 109 | + --eval-iters 5000 \ | ||
| 110 | + --save $SAVE_PATH \ | ||
| 111 | +" | ||
| 112 | +logfile=$(date +%Y%m%d)_$(date +%H%M%S) | ||
| 113 | +mkdir -p logs | ||
| 114 | +torchrun $DISTRIBUTED_ARGS pretrain_transformers.py \ | ||
| 115 | + $GPT_ARGS \ | ||
| 116 | + $MM_ARGS \ | ||
| 117 | + $OUTPUT_ARGS \ | ||
| 118 | + --distributed-backend nccl \ | ||
| 119 | + 2>&1 | tee logs/train_${logfile}.log | ||
| 120 | +chmod 440 logs/train_${logfile}.log | ||
| 121 | +find $SAVE_PATH -type d -exec chmod 750 {} \; | ||
| 122 | +find $SAVE_PATH -type f -exec chmod 640 {} \; | ||
| @@ -27,10 +27,10 @@ NODE_RANK=0 | |||
| 27 | WORLD_SIZE=$(($NPUS_PER_NODE*$NNODES)) | 27 | WORLD_SIZE=$(($NPUS_PER_NODE*$NNODES)) |
| 28 | 28 | ||
| 29 | 29 | ||
| 30 | -MM_DATA="./examples/qwen3vl/data.json" | 30 | +MM_DATA="./examples/qwen3vl/data_8B.json" |
| 31 | -MM_MODEL="./examples/qwen3vl/model.json" | 31 | +MM_MODEL="./examples/qwen3vl/model_8B.json" |
| 32 | MM_TOOL="./mindspeed_mm/tools/tools.json" | 32 | MM_TOOL="./mindspeed_mm/tools/tools.json" |
| 33 | -LOAD_PATH="ckpt/mm_path/Qwen3-VL-xxB-Instruct" | 33 | +LOAD_PATH="ckpt/mm_path/Qwen3-VL-8B-Instruct" |
| 34 | SAVE_PATH="save_dir" | 34 | SAVE_PATH="save_dir" |
| 35 | FSDP2_PATH="./examples/qwen3vl/fsdp2_config.yaml" | 35 | FSDP2_PATH="./examples/qwen3vl/fsdp2_config.yaml" |
| 36 | 36 | ||
| @@ -107,6 +107,7 @@ OUTPUT_ARGS=" | |||
| 107 | --save-interval 10000 \ | 107 | --save-interval 10000 \ |
| 108 | --eval-interval 10000 \ | 108 | --eval-interval 10000 \ |
| 109 | --eval-iters 5000 \ | 109 | --eval-iters 5000 \ |
| 110 | + --save $SAVE_PATH \ | ||
| 110 | " | 111 | " |
| 111 | logfile=$(date +%Y%m%d)_$(date +%H%M%S) | 112 | logfile=$(date +%Y%m%d)_$(date +%H%M%S) |
| 112 | mkdir -p logs | 113 | mkdir -p logs |
| @@ -1,26 +1,26 @@ | |||
| 1 | { | 1 | { |
| 2 | "model_id": "qwen3_vl_moe", | 2 | "model_id": "qwen3_vl_moe", |
| 3 | - "init_from_hf_path": "./ckpt/hf_path/Qwen3-VL-xxB-Instruct", | 3 | + "init_from_hf_path": "./ckpt/hf_path/Qwen3-VL-30B-Instruct", |
| 4 | "image_encoder": { | 4 | "image_encoder": { |
| 5 | "vision_encoder": { | 5 | "vision_encoder": { |
| 6 | "model_id": "qwen3vit", | 6 | "model_id": "qwen3vit", |
| 7 | - "num_layers": 27, | 7 | + "num_layers": 999999, |
| 8 | - "hidden_size": 1152, | 8 | + "hidden_size": 999999, |
| 9 | - "num_attention_heads": 16, | 9 | + "num_attention_heads": 999999, |
| 10 | "freeze": true | 10 | "freeze": true |
| 11 | }, | 11 | }, |
| 12 | "vision_projector": { | 12 | "vision_projector": { |
| 13 | "model_id": "lnmlp", | 13 | "model_id": "lnmlp", |
| 14 | - "num_layers": 1, | 14 | + "num_layers": 999999, |
| 15 | "freeze": true | 15 | "freeze": true |
| 16 | } | 16 | } |
| 17 | }, | 17 | }, |
| 18 | "text_decoder": { | 18 | "text_decoder": { |
| 19 | "model_id": "qwen3lm", | 19 | "model_id": "qwen3lm", |
| 20 | - "num_layers": 94, | 20 | + "num_layers": 999999, |
| 21 | - "hidden_size": 4096, | 21 | + "hidden_size": 999999, |
| 22 | - "num_attention_heads": 64, | 22 | + "num_attention_heads": 999999, |
| 23 | - "max_position_embeddings": 262144, | 23 | + "max_position_embeddings": 999999, |
| 24 | "freeze": false | 24 | "freeze": false |
| 25 | }, | 25 | }, |
| 26 | "patch": { | 26 | "patch": { |
| @@ -0,0 +1,30 @@ | |||
| 1 | +{ | ||
| 2 | + "model_id": "qwen3_vl", | ||
| 3 | + "init_from_hf_path": "./ckpt/hf_path/Qwen3-VL-8B-Instruct", | ||
| 4 | + "image_encoder": { | ||
| 5 | + "vision_encoder": { | ||
| 6 | + "model_id": "qwen3vit", | ||
| 7 | + "num_layers": 999999, | ||
| 8 | + "hidden_size": 999999, | ||
| 9 | + "num_attention_heads": 999999, | ||
| 10 | + "freeze": true | ||
| 11 | + }, | ||
| 12 | + "vision_projector": { | ||
| 13 | + "model_id": "lnmlp", | ||
| 14 | + "num_layers": 999999, | ||
| 15 | + "freeze": true | ||
| 16 | + } | ||
| 17 | + }, | ||
| 18 | + "text_decoder": { | ||
| 19 | + "model_id": "qwen3lm", | ||
| 20 | + "num_layers": 999999, | ||
| 21 | + "hidden_size": 999999, | ||
| 22 | + "num_attention_heads": 999999, | ||
| 23 | + "max_position_embeddings": 999999, | ||
| 24 | + "freeze": false | ||
| 25 | + }, | ||
| 26 | + "patch": { | ||
| 27 | + "clip_grad_async": true, | ||
| 28 | + "scale_grad": true | ||
| 29 | + } | ||
| 30 | +} | ||