Qwen-VL 多模态大模型在自定义数据上的微调与部署指南
Qwen-VL 是阿里云研发的多模态视觉语言模型,支持图像、文本及检测框输入输出。在自定义数据集上对 Qwen-VL 进行微调与部署的全流程。内容包括硬件配置要求、软件环境搭建、模型下载方式、数据格式准备、LoRA 及 Q-LoRA 微调方法、模型合并以及微调后的推理使用。通过可掌握基于 PEFT 技术的高效微调方案,适用于下游任务接入。

Qwen-VL 是阿里云研发的多模态视觉语言模型,支持图像、文本及检测框输入输出。在自定义数据集上对 Qwen-VL 进行微调与部署的全流程。内容包括硬件配置要求、软件环境搭建、模型下载方式、数据格式准备、LoRA 及 Q-LoRA 微调方法、模型合并以及微调后的推理使用。通过可掌握基于 PEFT 技术的高效微调方案,适用于下游任务接入。

Qwen-VL 是阿里云研发的大规模视觉语言模型(Large Vision Language Model, LVLM)。Qwen-VL 可以以图像、文本、检测框作为输入,并以文本和检测框作为输出。

Qwen-VL-Chat = 大语言模型 (Qwen-7B) + 视觉图片特征编码器 (Openclip ViT-bigG) + 位置感知视觉语言适配器 (可训练 Adapter) + 1.5B 的图文数据 + 多轮训练 + 对齐机制 (Chat)

微调训练的显存占用及速度如下 (BS=1),可根据显存大小调整 Sequence Length 参数。
| Method | Speed (512 Sequence Length) | Memory (512 Sequence Length) |
|---|---|---|
| LoRA (Base) | 2.4s/it | 37.3GB |
| LoRA (Chat) | 2.3s/it | 23.6GB |
| Q-LoRA | 4.5s/it | 17.2GB |
推理阶段的显存占用及速度如下。
| Quantization | Speed (2048 tokens) | Memory (2048 tokens) |
|---|---|---|
| BF16 | 28.87 | 22.60GB |
| Int4 | 37.79 | 11.82GB |
$ curl -O https://repo.anaconda.com/archive/Anaconda3-2019.03-Linux-x86_64.sh # 从官网下载安装脚本
$ bash Anaconda3-2019.03-Linux-x86_64.sh # 阅读协议确认安装,安装完成后再输入 yes 以便不需要手动将 Anaconda 添加到 PATH
$ conda create -n qwen_vl python=3.10 # 安装虚拟环境,python 3.10 及以上版本
$ conda activate qwen_vl # 激活虚拟环境
$ conda install pytorch==2.1.2 torchvision==0.16.2 torchaudio==2.1.2 pytorch-cuda=11.8 -c pytorch -c nvidia # pytorch 2.0 及以上版本,建议使用 CUDA 11.4 及以上
利用 ModelScope 和 Transformers 快速使用 Qwen-VL 和 Qwen-VL-Chat。
pip3 install -r requirements.txt
pip3 install -r requirements_openai_api.txt
pip3 install -r requirements_web_demo.txt
pip3 install deepspeed
pip3 install peft
pip3 install optimum
pip3 install auto-gptq
pip3 install modelscope -U
建议先从 ModelScope 下载模型及代码至本地,再从本地加载模型:
from modelscope import snapshot_download
from transformers import AutoModelForCausalLM, AutoTokenizer
# 其中版本 v1.1.0 支持 INT4、INT8 的在线量化,其余版本不支持
model_id = 'qwen/Qwen-VL-Chat'
revision = 'v1.0.0'
# 下载模型到指定目录
local_dir = "/root/autodl-tmp/Qwen-VL-Chat"
snapshot_download(repo_id=model_id, revision=revision, local_dir=local_dir)
也可手动下载,下载地址如下:
# 启动命令,局域网访问
python web_demo_mm.py --server-name 0.0.0.0
from transformers import AutoModelForCausalLM, AutoTokenizer
from transformers.generation import GenerationConfig
import torch
torch.manual_seed(1234)
# 请注意:根据显存选择配置,分词器默认行为已更改为默认关闭特殊 token 攻击防护。
tokenizer = AutoTokenizer.from_pretrained("Qwen/Qwen-VL-Chat", trust_remote_code=True)
model = AutoModelForCausalLM.from_pretrained("Qwen/Qwen-VL-Chat", device_map="auto", trust_remote_code=True, bf16=True, fp16=False).eval()
# 第一轮对话
query = tokenizer.from_list_format([
{'image': 'https://qianwen-res.oss-cn-beijing.aliyuncs.com/Qwen-VL/assets/demo.jpeg'}, # Either a local path or an url
{'text': '这是什么?'},
])
response, history = model.chat(tokenizer, query=query, history=None)
print(response)
# 图中是一名女子在沙滩上和狗玩耍,旁边是一只拉布拉多犬,它们处于沙滩上。
# 第二轮对话
response, history = model.chat(tokenizer, '框出图中击掌的位置', history=history)
print(response)
# <ref>击掌</ref><box>(536,509),(588,602)</box>

提供了 finetune.py 这个脚本供用户实现在自己的数据上进行微调的功能,以接入下游任务。此外还提供了 shell 脚本减少用户的工作量。这个脚本支持 DeepSpeed 和 FSDP。
需要将所有样本数据放到一个列表中并存入 JSON 文件中。每个样本对应一个字典,包含 id 和 conversation,其中后者为一个列表。示例如下所示:
[
{
"id": "identity_0",
"conversations": [
{
"from": "user",
"value": "你好"
},
{
"from": "assistant",
"value": "我是 Qwen-VL,一个支持视觉输入的大模型。"
}
]
},
{
"id": "identity_1",
"conversations": [
{
"from": "user",
"value": "Picture 1: <img>https://qianwen-res.oss-cn-beijing.aliyuncs.com/Qwen-VL/assets/demo.jpeg</img>\n图中的狗是什么品种?"
},
{
"from": "assistant",
"value"
对数据格式的解释:
<img> </img> <ref> </ref> <box> </box>。Picture id: <img>img_path</img>\n{your prompt},其中 id 表示对话中的第几张图片。"img_path"可以是本地的图片或网络地址。<box>(x1,y1),(x2,y2)</box>,其中 (x1, y1) 和(x2, y2)分别对应左上角和右下角的坐标,并且被归一化到 [0, 1000) 的范围内。检测框对应的文本描述也可以通过 <ref>text_caption</ref> 表示。微调脚本能够帮你实现:全参数微调,不支持单卡训练,且需确认机器是否支持 bf16 sh finetune/finetune_ds.sh;LoRA;Q-LoRA。
使用官方项目里提供的微调脚本进行 LoRA 微调测试,模型采用 HuggingFace 下载的那个全精度模型,数据采用上面的示例数据,建议模型路径使用绝对路径,如果你想节省显存占用,可以考虑使用 chat 模型进行 LoRA 微调,显存占用将大幅度降低。
# 单卡训练
sh finetune/finetune_lora_single_gpu.sh
# 分布式训练
sh finetune/finetune_lora_ds.sh
#!/bin/bash
export CUDA_DEVICE_MAX_CONNECTIONS=1
DIR=`pwd`
MODEL="/root/autodl-tmp/Qwen-VL-Chat"
DATA="/root/autodl-tmp/data.json"
export CUDA_VISIBLE_DEVICES=0
python3 finetune.py \
--model_name_or_path $MODEL \
--data_path $DATA \
--bf16 True \
--fix_vit True \
--output_dir output_qwen \
--num_train_epochs 5 \
--per_device_train_batch_size 1 \
--per_device_eval_batch_size 1 \
--gradient_accumulation_steps 8 \
--evaluation_strategy "no" \
--save_strategy "steps" \
--save_steps 1000 \
--save_total_limit 10 \
--learning_rate 1e-5 \
--weight_decay 0.1 \
--adam_beta2 0.95 \
--warmup_ratio 0.01 \
--lr_scheduler_type "cosine" \
--logging_steps 1 \
--report_to "none" \
--model_max_length 600 \
--lazy_preprocess True \
--gradient_checkpointing \
--use_lora
注意事项:


如果你依然遇到显存不足的问题,可以考虑使用 Q-LoRA (论文)。该方法使用 4 比特量化模型以及 paged attention 等技术实现更小的显存开销。运行 Q-LoRA 你只需运行如下脚本:
# 单卡训练
sh finetune/finetune_qlora_single_gpu.sh
# 分布式训练
sh finetune/finetune_qlora_ds.sh
与全参数微调不同,LoRA 和 Q-LoRA 的训练只需存储 adapter 部分的参数。因此需要先合并并存储模型(LoRA 支持合并,Q-LoRA 不支持),再用常规方式读取你的新模型:
from peft import AutoPeftModelForCausalLM
model = AutoPeftModelForCausalLM.from_pretrained(
path_to_adapter, # path to the output directory
device_map="auto",
trust_remote_code=True
).eval()
merged_model = model.merge_and_unload()
# max_shard_size and safe serialization are not necessary.
# They respectively work for sharding checkpoint and save the model to safetensors
merged_model.save_pretrained(new_model_directory, max_shard_size="2048MB", safe_serialization=True)
完成模型合并后,可以使用以下代码加载微调后的模型进行推理,逻辑与原始模型类似,但会体现微调后的知识或风格。
from transformers import AutoModelForCausalLM, AutoTokenizer
import torch
tokenizer = AutoTokenizer.from_pretrained("new_model_directory", trust_remote_code=True)
model = AutoModelForCausalLM.from_pretrained("new_model_directory", device_map="auto", trust_remote_code=True, bf16=True).eval()
# 测试推理
query = tokenizer.from_list_format([
{'image': 'test_image.jpg'},
{'text': '请描述这张图片'}
])
response, history = model.chat(tokenizer, query=query, history=None)
print(response)
batch_size 或启用 gradient_checkpointing。
微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online
基于 Mermaid.js 实时预览流程图、时序图等图表,支持源码编辑与即时渲染。 在线工具,Mermaid 预览与可视化编辑在线工具,online
解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online