☰
XTuner 多模态数据集(VLM)训练全流程指南:从 LLaVA 数据准备到对话与评测
2026/10/13 1:51:27 网站建设 项目流程
  • 大模型
  • 模型微调

【免费下载链接】xtuner

A Next-Generation Training Engine Built for Ultra-Large MoE Models

项目地址:https://gitcode.com/GitHub_Trending/xt/xtuner
点击查看免费下载

导读

本文基于 XTuner 仓库中的多模态训练文档,系统讲解如何利用 XTuner 完成 LLaVA 图文模型的微调:从开源 LLaVA 数据集与自定义多模态数据集的准备,到「预训练 + 指令跟随微调」两步训练、PTH 模型转换与 LoRA 合并,再到xtuner chat图文对话与 MMBench 评测。以仓库内置的xtuner/llava-internlm2-7b配置为例,读完本文你将掌握一套完整可复现的 VLM 训练、转换、对话与评测链路,并理解底层数据管线(LLaVADataset、llava_map_fn、图像 token 编码)与模型结构(LLaVAModel投影层与 LoRA)的实现原理。

一、多模态训练整体路线

XTuner 支持 LLaVA 格式数据集的多模态图文预训练与微调。多模态图文训练一般分为两步:

  1. 预训练(pretrain):冻结 LLM 与视觉编码器(CLIP-ViT),仅训练连接视觉与语言特征的投影层(MLP Projector),让模型学会将图像特征对齐到文本语义空间;
  2. 指令跟随微调(finetune):载入预训练得到的.pth权重作为初始化,使用图文对话数据微调,使模型具备多轮图文问答能力。

对应到仓库中的配置(xtuner/configs/llava/README_zh-CN.md):

  • ./${LLM}_${ViT}/下是与 LLaVA-InternLM 训练设置对齐的配置(即使用 LoRA / QLoRA);
  • ./official/下是与 LLaVA-v1.5 官方训练设置对齐的配置。

以llava-internlm2-7b为例,预训练配置与指令跟随微调配置分别位于:

  • 预训练:xtuner/configs/llava/internlm2_chat_7b_clip_vit_large_p14_336/pretrain/llava_internlm2_chat_7b_clip_vit_large_p14_336_e1_gpu8_pretrain.py
  • 指令跟随微调(QLoRA):xtuner/configs/llava/internlm2_chat_7b_clip_vit_large_p14_336/finetune/llava_internlm2_chat_7b_qlora_clip_vit_large_p14_336_lora_e1_gpu8_finetune.py

关于各模型在各评测集上的结果,仓库内置的 xtuner/configs/llava/README_zh-CN.md 提供了 MMBench、MME、SEEDBench_IMG、MMVet、MMMU、MathVista、HallusionBench 等多项评测数据,可直接参考。

二、数据准备:LLaVA 开源数据集

多模态训练的第一步是准备数据。本节从「LLaVA 开源数据集准备」和「自定义数据集准备」两部分展开。

2.1 数据文件结构

下载并整理后的数据应具备如下目录结构(这也是所有内置配置文件默认假设的路径,data_root = './data/llava_data/'):

./data/llava_data ├── LLaVA-Pretrain │ ├── blip_laion_cc_sbu_558k.json │ ├── blip_laion_cc_sbu_558k_meta.json │ └── images ├── LLaVA-Instruct-150K │ └── llava_v1_5_mix665k.json └── llava_images ├── coco │ └── train2017 ├── gqa │ └── images ├── ocr_vqa │ └── images ├── textvqa │ └── train_images └── vg ├── VG_100K └── VG_100K_2

其中LLaVA-Pretrain用于第一阶段预训练(558K 图文对,训练投影层),LLaVA-Instruct-150K的llava_v1_5_mix665k.json与llava_images目录下的多来源图片用于第二阶段指令跟随微调。该结构在 docs/zh_cn/user_guides/dataset_prepare.md 中有完整对应说明。

2.2 预训练数据下载(LLaVA-Pretrain)

# Make sure you have git-lfs installed (https://git-lfs.com) git lfs install git clone https://huggingface.co/datasets/liuhaotian/LLaVA-Pretrain --depth=1

2.3 指令微调数据下载

文本数据:LLaVA-Instruct-150K

# Make sure you have git-lfs installed (https://git-lfs.com) git lfs install git clone https://huggingface.co/datasets/liuhaotian/LLaVA-Instruct-150K --depth=1

图像数据(对应llava_images下的五个子目录):

数据集用途目录下载
COCOcoco/train2017下载train2017.zip并解压
GQAgqa/images下载 GQAimages.zip
TextVQAtextvqa/train_images下载train_val_images.zip
VisualGenomevg/VG_100K、vg/VG_100K_2下载 part1、part2 两个压缩包
OCR-VQAocr_vqa/images使用官方 download script 下载

⚠️ 特别注意 OCR-VQA 图片命名:OCR-VQA 所下载的图片命名需要利用如下脚本进行处理,以确保所有图片后缀为.jpg:

#!/bin/bash ocr_vqa_path="<your-directory-path>" find "$target_dir" -type f | while read file; do extension="${file##*.}" if [ "$extension" != "jpg" ] then cp -- "$file" "${file%.*}.jpg" fi done

2.4 自定义数据集准备

如果用户期望使用自定义数据集进行图文训练,可以参照 LLaVA 开源数据集格式进行准备,JSON 格式如下:

[ { "image": "xxx/xxx", "conversations": [ { "from": "human", "value": "<image>\nHello! What's this?" }, { "from": "gpt", "value": "This is a dog!" }, { "from": "human", "value": "Is it cute?" }, { "from": "gpt", "value": "Yes." } ] }, ... ]

针对自定义数据目前有一些约束:

  1. image字段表示图片路径,且仅能有一张图片;
  2. conversations字段第 0 条的value需要包括<image>,以确保图片被正确嵌入到首轮输入中。

源码层面的印证:<image>是仓库定义的图片占位 tokenDEFAULT_IMAGE_TOKEN,其 token 索引为IMAGE_TOKEN_INDEX = -200(见 xtuner/utils/constants.py)。在数据管线中:

  • xtuner/dataset/map_fns/dataset_map_fns/llava_map_fn.py 的llava_map_fn会将 human 轮次中的<image>从消息中间提到开头并规范化为<image>\n...的格式,再切分为{'input', 'output'}单轮对话结构;同时跳过数据集开头可能出现的from == 'gpt'轮次;
  • xtuner/dataset/utils.py 的encode_fn在编码含<image>的输入时,按DEFAULT_IMAGE_TOKEN切分文本,并在切分位置插入IMAGE_TOKEN_INDEX,随后对输入部分打上IGNORE_INDEX = -100标签(不计算损失),仅对output部分计算 loss——这正是「只学回答、不学提问」的多模态 SFT 标签策略;
  • 同样的约束也体现在仅含图片 token 的llava_image_only_map_fn(用于图文预训练阶段,输入仅含<image>)。

扩展到 InternVL 系列数据集:除 LLaVA 外,XTuner 还内置了InternVL_V1_5_Dataset(xtuner/dataset/internvl_dataset.py),用于 InternVL 系列 VLM 的多模态训练。其配置支持data_paths与image_folders以列表形式传入多份数据(图片目录可为None,表示该数据源无图片),例如 xtuner/configs/internvl/v1_5/internvl_v1_5_internlm2_26b_finetune.py:

llava_dataset = dict( type=InternVL_V1_5_Dataset, model_path=path, data_paths=data_path, # 可为 ['a.json','b.jsonl','c.json'] image_folders=image_folder, # 可为 ['a', None, 'c'] template=prompt_template, max_length=max_length)

InternVL_V1_5_Dataset支持根据min_dynamic_patch/max_dynamic_patch对图像做动态切分(dynamic preprocess),并按downsample_ratio计算 patch token 数,max_length默认放宽到 4096。

三、训练:预训练与指令跟随微调

多模态图文训练一般分为两步:预训练(pretrain)、指令跟随微调(finetune)。下面以llava-internlm2-7b为例给出完整命令,用户可以对其中的模型路径、数据路径进行自定义修改。

3.1 预训练(Pretrain)

$ NPROC_PER_NODE=8 xtuner train llava_internlm2_chat_7b_clip_vit_large_p14_336_e1_gpu8_pretrain --deepspeed deepspeed_zero2

训练得到的模型将默认保存在./work_dirs/,用户可以通过命令xtuner train --work-dir ${SAVE_PATH}指定保存路径。

预训练配置要点(预训练配置文件):

  • 模型:llm_name_or_path = 'internlm/internlm2-chat-7b',visual_encoder_name_or_path = 'openai/clip-vit-large-patch14-336';
  • 冻结策略:freeze_llm=True、freeze_visual_encoder=True,即 LLM 与 CLIP-ViT 全程冻结,只有投影层(projector)参与训练;
  • LLM 采用 4bit QLoRA 量化加载(BitsAndBytesConfig:load_in_4bit=True、bnb_4bit_quant_type='nf4'、bnb_4bit_use_double_quant=True),显著降低显存占用;
  • 数据:data_path = './data/llava_data/LLaVA-Pretrain/blip_laion_cc_sbu_558k.json',image_folder = './data/llava_data/LLaVA-Pretrain/images';
  • 序列长度:max_length = int(2048 - (336 / 14)**2) = 1472(CLIP 336×336 输入在 14×14 patch 下产生 24×24=576 个视觉 token,从 2048 中扣除后即为文本侧可用长度);
  • 优化:AdamW,lr = 1e-3,betas = (0.9, 0.999),weight_decay = 0,max_norm = 1(梯度裁剪),warmup_ratio = 0.03(LinearLR 预热后接 CosineAnnealingLR);
  • 训练:batch_size = 32(per_device)、max_epochs = 1、dataloader_num_workers = 4;
  • 保存与评测:save_steps = 500、save_total_limit = 2;custom_hooks中的EvaluateChatHook每 500 步用evaluation_images(一张示例图片)与evaluation_inputs(中英文提示词)自动进行一轮对话生成并打印日志。

3.2 指令跟随微调(Finetune)

指令跟随微调时,需要载入预训练阶段所得到的.pth模型,以提供良好的初始化。这一通过在配置文件中的pretrained_pth指定(默认指向./work_dirs/llava_internlm2_chat_7b_clip_vit_large_p14_336_e1_gpu8_pretrain/iter_2181.pth),用户可以自行修改。

$ NPROC_PER_NODE=8 xtuner train llava_internlm2_chat_7b_qlora_clip_vit_large_p14_336_lora_e1_gpu8_finetune --deepspeed deepspeed_zero2

QLoRA 微调配置要点(微调配置文件):

  • 数据:data_path = './data/llava_data/LLaVA-Instruct-150K/llava_v1_5_mix665k.json',image_folder = './data/llava_data/llava_images';
  • LoRA 注入:LLM 侧llm_lora(r=512、lora_alpha=256、lora_dropout=0.05),视觉编码器侧visual_encoder_lora(r=64、lora_alpha=16),target_modules未指定时由find_all_linear_names自动识别(见 xtuner/model/llava.py);
  • 冻结策略:freeze_llm=True、freeze_visual_encoder=True,冻结基座权重、仅训练 LoRA 适配器;
  • 优化:lr = 2e-4,batch_size = 16,其余优化器设置与预训练一致;
  • 图像预处理:pad_image_to_square=True,即调用 xtuner/dataset/utils.py 的expand2square将图片按 RGB 均值色填充为正方形后再送入 CLIPImageProcessor;
  • 采样器:使用LengthGroupedSampler,length_property='modality_length',按「模态长度」分桶采样。该属性由LLaVADataset.modality_length提供——有图的样本记正长度、无图的样本记负长度,从而实现图文样本按长度分组、减少 padding 浪费。

此外仓库还提供了全参数微调配置 llava_internlm2_chat_7b_clip_vit_large_p14_336_e1_gpu8_finetune.py(freeze_llm=False、LLM 以 fp32 加载、lr=2e-5、batch_size=8、accumulative_counts=2),以及llava_internlm2_chat_7b_clip_vit_large_p14_336_e1_gpu8_finetune.py之外的多种 LLM + ViT 组合(vicuna、internlm、internlm2-20b 等,见 xtuner/configs/llava)。

3.3 数据管线源码解读:LLaVADataset

理解LLaVADataset(xtuner/dataset/llava.py)有助于把握上述配置参数的底层影响:

  • 文本与图像分离处理:构造时先读取data_path(支持.json与.jsonl),经process_hf_dataset完成 tokenize、dataset_map_fn(llava_map_fn)与template_map_fn(template_map_fn_factory,按PROMPT_TEMPLATE.internlm2_chat套上<|im_start|>对话模板,见 xtuner/dataset/map_fns/template_map_fn.py)处理,得到text_data;真正的图片在__getitem__时才按image_folder + image_file在线读取并预处理为pixel_values;
  • modality_length属性:返回每个样本的文本长度,无图样本取负值,供LengthGroupedSampler使用;
  • 无图样本的兜底:若某样本没有image字段,则填充一张与image_processor.crop_size等尺寸的全零pixel_values,保证 batch 结构一致;
  • 离线处理文本数据:当offline_processed_text_folder被指定时(与data_path同时存在时优先加载离线数据),直接从本地加载已 tokenize 好的 HF Dataset,跳过在线处理,这是大数据量场景下提速的关键(详见下文 4.4 节)。

四、模型转换与合并

4.1 PTH 转 HuggingFace(pth_to_hf)

模型训练后会自动保存成 PTH 模型(例如iter_5198.pth),但 PTH 并不是通用的 HuggingFace 格式,需要利用xtuner convert pth_to_hf将其转换为 HuggingFace 模型,以便后续对话、评测与部署使用。具体命令为:

$ xtuner convert pth_to_hf $FINETUNE_CFG $PTH_PATH $SAVE_PATH $ # 例如:xtuner convert pth_to_hf llava_internlm2_chat_7b_qlora_clip_vit_large_p14_336_lora_e1_gpu8_finetune ./iter_5198.pth ./iter_5198_hf

转换器源码位于 xtuner/tools/model_converters/pth_to_hf.py,其要点包括:

  • 通过--cfg-options支持命令行覆盖配置;默认输出 LLM 为 fp16(可加--fp32保存为 fp32),并支持--max-shard-size(默认 2GB)分片与--safe-serialization;
  • 对LLaVAModel会清空pretrained_pth后按配置重建模型,再逐参数装载权重并调用model.to_hf(...)落盘;
  • LLaVAModel.to_hf(xtuner/model/llava.py)根据训练范式输出不同目录结构:
    • 默认save_format='xtuner':若使用 LoRA,则输出llm_adapter/、visual_encoder_adapter/与projector/;若为全参数微调,则输出完整 LLM 权重、visual_encoder/与projector/,同时保存 tokenizer 与 image_processor;
    • 也可选择save_format='huggingface'或'official',将状态字典按映射关系重组为LlavaForConditionalGeneration/ 官方 LLaVA 结构(含图像 token 的 embedding 扩容处理)。

使用默认的微调范式时,转换后的文件结构与仓库文档描述的xtuner/llava-internlm2-7b发布结构一致(LLM/LLM-adapter + visual_encoder/visual_encoder-adapter + projector)。

4.2 LoRA / QLoRA 模型合并(可选)

如果您使用了 LoRA / QLoRA 微调,则模型转换后将得到 adapter 参数,而并不包含原 LLM 参数。如果您期望获得合并后的模型权重,那么可以利用xtuner convert merge:

$ xtuner convert merge $LLM $LLM_ADAPTER $SAVE_PATH $ xtuner convert merge $CLIP $CLIP_ADAPTER $SAVE_PATH --is-clip

其中第一条合并 LLM 与其 LoRA adapter,第二条用--is-clip标记合并 CLIP-ViT 与其 LoRA adapter。合并工具(xtuner/tools/model_converters/merge.py)内部通过PeftModel.from_pretrained加载 adapter 并调用merge_and_unload()完成权重合并,之后save_pretrained落盘,同时保存 tokenizer / image_processor;默认设备为cuda,可用--device cpu/auto调整。

4.3 离线处理数据集的加速技巧(可选)

当训练数据量非常大时,每次训练都先在线处理数据会极为耗时。XTuner 提供了离线处理 LLaVA 数据的流程(详见 docs/zh_cn/user_guides/llava_offline.md):

  1. 用xtuner list-cfg -p llava查看 LLaVA 相关配置,用xtuner copy-cfg ${CONFIG_NAME} .导出配置;
  2. 运行python xtuner/tools/process_untokenized_llava_data.py ${CONFIG_PATH} --save-folder /folder/to/save/processed/dataset离线处理文本数据;
  3. 修改导出的配置,把llava_dataset中的data_path/tokenizer替换为offline_processed_text_folder=/folder/to/save/processed/dataset;
  4. 直接使用修改后的配置训练。

LLaVADataset会优先加载offline_processed_text_folder,多次训练无需重复 tokenize。

五、对话测试

用户可以利用xtuner chat实现与微调后的多模态图文模型对话。假设模型转换阶段获得的模型路径为./iter_5198_hf,则可以利用下列命令实现对话:

$ xtuner chat internlm/internlm2-chat-7b \ $ --visual-encoder openai/clip-vit-large-patch14-336 \ $ --llava ./iter_5198_hf \ $ --prompt-template internlm2_chat \ $ --image $IMAGE_PATH

参数与运行机制(见 xtuner/tools/chat.py):

  • 第一个参数为 LLM 路径或 HuggingFace Hub ID。如果训练阶段 LLM 使用的是 LoRA / QLoRA 微调,则此参数请传入基础 LLM,如internlm/internlm2-chat-7b;如果使用的是全参数微调,则此参数请传入转换(xtuner convert pth_to_hf)所得到的模型权重,如./iter_5198_hf;
  • --visual-encoder:指定 CLIP 视觉编码器;若--llava目录内已包含visual_encoder/子目录,则无需再传(工具会自动检测目录结构);
  • --llava:模型转换阶段获得的权重目录,工具会按需加载其中的projector/、llm_adapter/、visual_encoder_adapter/;
  • --prompt-template internlm2_chat:与训练时的PROMPT_TEMPLATE保持一致,工具会据此套用对话模板并自动注入停止词;
  • --image:指定本地图片路径或 URL,工具内部经expand2square+CLIPImageProcessor预处理后,由 visual_encoder 提取特征、projector 投影,最终通过prepare_inputs_labels_for_multimodal将视觉 token 拼入input_ids后执行生成;
  • 其它可选参数:--torch-dtype(默认 fp16)、--bits(4/8 位量化加载 LLM)、--max-new-tokens(默认 2048)、--temperature(默认 0.1)、--top-k(默认 40)、--top-p(默认 0.75)等。

六、评测

6.1 VLMEvalKit

XTuner 的 LLaVA 模型可以利用 VLMEvalKit 进行评测,可参考其 Quickstart 快速上手(按该工具链的标准流程准备数据集与配置文件即可)。

6.2 XTuner 内置 MMBench 评测

为了方便使用,XTuner 内也集成了 MMBench 评测。您可以通过下列命令下载 MMBench 评测数据集:

$ wget https://opencompass.openxlab.space/utils/VLMEval/MMBench_DEV_EN.tsv $ wget https://opencompass.openxlab.space/utils/VLMEval/MMBench_TEST_EN.tsv $ wget https://opencompass.openxlab.space/utils/VLMEval/MMBench_DEV_CN.tsv $ wget https://opencompass.openxlab.space/utils/VLMEval/MMBench_TEST_CN.tsv $ wget https://opencompass.openxlab.space/utils/VLMEval/CCBench.tsv

之后,您可以利用下列命令实现评测:

$ xtuner mmbench internlm/internlm2-chat-7b \ $ --visual-encoder openai/clip-vit-large-patch14-336 \ $ --llava ./iter_5198_hf \ $ --prompt-template internlm2_chat \ $ --data-path $DATA_PATH \ $ --work-dir $RESULT_PATH

要点说明(见 xtuner/tools/mmbench.py):

  • 第一个参数为 LLM 路径或 HuggingFace Hub ID,规则与xtuner chat相同(LoRA/QLoRA 传基础 LLM,全参微调传转换后的权重);
  • $DATA_PATH指上一步骤所下载的某一个 tsv 文件,如MMBench_DEV_EN.tsv;
  • 工具内部用MMBenchDataset解析 tsv:若首行含answer列则判定为dev集,否则为test集;推理时对每个样本拼接「题目 + 选项」并提示模型"直接回答选项字母",生成采用do_sample=False;
  • 评测结果保存到--work-dir下的mmbench_result.xlsx与mmbench_result.json;
  • 评测完成后,若为开发集则会直接打印结果(按 Average 及 CP / FP-S / FP-C / LR / RR / AR 等能力维度分类给出准确率表格);若为测试集,则需将mmbench_result.xlsx提交至 MMBench 官方完成评测以取得精度结果。

七、FAQ

7.1 如何更换 LLM?

修改 LLM 的方式与训练单模态的大语言模型类似:

  1. 修改配置文件中的llm_name_or_path参数至您期望使用的 LLM,例如internlm/internlm2-chat-20b等;
  2. 修改配置文件中的prompt_template参数,与您所选择的 LLM 保持对齐,具体选择可参考对话模板文档。

更换 LLM 后,需注意其 tokenizer 与对话模板与数据管线的兼容性(模板注入由 xtuner/dataset/map_fns/template_map_fn.py 完成)。

7.2 ValueError:bos_token_idhas to be defined when noinput_idsare provided.

这是由于老版本transformers的 LLMgenerate接口在接受inputs_embeds输入时,必须传入有效的bos_token_id(对应 transformers 的修复 PR #29772)。

更新transformers即可解决:

$ pip install -U transformers

八、关键文件索引

  • 多模态训练文档:docs/zh_cn/training/multi_modal_dataset.rst
  • LLaVA 数据准备:docs/zh_cn/user_guides/dataset_prepare.md、离线处理:docs/zh_cn/user_guides/llava_offline.md
  • 配置示例:xtuner/configs/llava/internlm2_chat_7b_clip_vit_large_p14_336/pretrain 与 xtuner/configs/llava/internlm2_chat_7b_clip_vit_large_p14_336/finetune
  • 数据集实现:xtuner/dataset/llava.py、xtuner/dataset/map_fns/dataset_map_fns/llava_map_fn.py、xtuner/dataset/internvl_dataset.py
  • 模型实现:xtuner/model/llava.py
  • 工具链:xtuner/tools/chat.py、xtuner/tools/mmbench.py、xtuner/tools/model_converters/pth_to_hf.py、xtuner/tools/model_converters/merge.py
  • LLaVA 全流程说明与评测结果:xtuner/configs/llava/README_zh-CN.md
  • 大模型
  • 模型微调

【免费下载链接】xtuner

A Next-Generation Training Engine Built for Ultra-Large MoE Models

项目地址:https://gitcode.com/GitHub_Trending/xt/xtuner
点击查看免费下载

相关推荐

上一篇:beets 查询语言完全指南:从关键词匹配到日期区间与正则的高级库检索
下一篇:从安装失败到完美签名:xManager JKS密钥管理实战指南

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询