InternVL多模态模型部署微调实践
基础任务(完成此任务即完成闯关)
- 理解多模态大模型的常见设计模式,可以大概讲出多模态大模型的工作原理。
- 了解InternVL2的设计模式,可以大概描述InternVL2的模型架构和训练流程。
- 了解LMDeploy部署多模态大模型的核心代码,并运行提供的gradio代码,在UI界面体验与InternVL2的对话。
- 了解XTuner,并利用给定数据集微调InternVL2-2B后,再次启动UI界面,体验模型美食鉴赏能力的变化。
- 将训练好的模型上传到 Hugging Face 或 ModelScope 上,模型名称包含 InternVL 关键词(优秀学员必做)
环境配置
训练环境配置
新建虚拟环境并进入:
conda create --name xtuner-env python=3.10 -y
conda activate xtuner-env
xtuner-env
为训练环境名,可以根据个人喜好设置,在本教程中后续提到训练环境均指"xtuner-env"环境。
安装与deepspeed集成的xtuner和相关包:
pip install xtuner==0.1.23 timm==1.0.9
pip install 'xtuner[deepspeed]'
pip install torch==2.4.1 torchvision==0.19.1 torchaudio==2.4.1 --index-url https://download.pytorch.org/whl/cu121
pip install transformers==4.39.0 tokenizers==0.15.2 peft==0.13.2 datasets==3.1.0 accelerate==1.2.0 huggingface-hub==0.26.5
训练环境既为安装成功。
推理环境配置
配置推理所需环境:
conda create -n lmdeploy python=3.10 -y
conda activate lmdeploy
pip install lmdeploy==0.6.1 gradio==4.44.1 timm==1.0.9
lmdeploy
为推理使用环境名。
LMDeploy部署多模态大模型并基于UI进行交互
核心部署代码
主要通过pipeline.chat
接口来构造多轮对话管线,核心代码为:
## 1.导入相关依赖包
from lmdeploy import pipeline, TurbomindEngineConfig, GenerationConfig
from lmdeploy.vl import load_image
## 2.使用你的模型初始化推理管线
model_path = "your_model_path"
pipe = pipeline(model_path,
backend_config=TurbomindEngineConfig(session_len=8192))
## 3.读取图片(此处使用PIL读取也行)
image = load_image('your_image_path')
## 4.配置推理参数
gen_config = GenerationConfig(top_p=0.8, temperature=0.8)
## 5.利用 pipeline.chat 接口 进行对话,需传入生成参数
sess = pipe.chat(('describe this image', image), gen_config=gen_config)
print(sess.response.text)
## 6.之后的对话轮次需要传入之前的session,以告知模型历史上下文
sess = pipe.chat('What is the woman doing?', session=sess, gen_config=gen_config)
print(sess.response.text)
网页应用部署体验
拉取教程github仓库:
git clone https://github.com/Control-derek/InternVL2-Tutorial.git
cd InternVL2-Tutorial
demo.py
文件中,MODEL_PATH处传入InternVL2-2B的路径,如果使用的是InternStudio的开发机则无需修改,否则改为模型路径。
启动demo:
conda activate lmdeploy
python demo.py
运行后配置ssh端口转发,vscode下操作会自动配置,在本地打开浏览器访问:
微调InternVL2-2B
准备配置文件
cd /root
git clone https://github.com/InternLM/xtuner.git
conda activate xtuner-env
原始internvl的微调配置文件在路径./xtuner/configs/internvl/v2
下,假设上面克隆的仓库在/root/InternVL2-Tutorial
,复制配置文件到目标目录下:
cp /root/InternVL2-Tutorial/xtuner_config/internvl_v2_internlm2_2b_lora_finetune_food.py /root/xtuner/xtuner/configs/internvl/v2/internvl_v2_internlm2_2b_lora_finetune_food.py
配置文件参数解读
internvl_v2_internlm2_2b_lora_finetune_food.py
:
在第一部分的设置中,有如下参数:
path
: 需要微调的模型路径,在InternStudio环境下,无需修改。data_root
: 数据集所在路径。data_path
: 训练数据文件路径。image_folder
: 训练图像根路径。prompt_temple
: 配置模型训练时使用的聊天模板、系统提示等。使用与模型对应的即可,此处无需修改。max_length
: 训练数据每一条最大token数。batch_size
: 训练批次大小,可以根据显存大小调整。accumulative_counts
: 梯度累积的步数,用于模拟较大的batch_size,在显存有限的情况下,提高训练稳定性。dataloader_num_workers
: 指定数据集加载时子进程的个数。max_epochs
:训练轮次。optim_type
:优化器类型。lr
: 学习率betas
: Adam优化器的beta1, beta2weight_decay
: 权重衰减,防止训练过拟合用max_norm
: 梯度裁剪时的梯度最大值warmup_ratio
: 预热比例,前多少的数据训练时,学习率将会逐步增加。save_steps
: 多少步存一次checkpointsave_total_limit
: 最多保存几个checkpoint,设为-1即无限制
#######################################################################
# PART 1 Settings #
#######################################################################
# Model
path = '/root/share/new_models/OpenGVLab/InternVL2-2B'
# Data
data_root = '/root/share/datasets/FoodieQA/' # your data path
data_path = data_root + 'sivqa_llava.json'
image_folder = data_root # your image folder path
prompt_template = PROMPT_TEMPLATE.internlm2_chat
max_length = 8192
# Scheduler & Optimizer
batch_size = 4 # per_device
accumulative_counts = 2
dataloader_num_workers = 4
max_epochs = 10
optim_type = AdamW
# official 1024 -> 4e-5
# lr = 1e-6
lr = 3e-5
betas = (0.9, 0.999)
weight_decay = 0.05
max_norm = 1 # grad clip
warmup_ratio = 0.03
# Save
save_steps = 64
save_total_limit = -1 # Maximum checkpoints to keep (-1 means unlimited)
第二部分配置文件,LoRA相关参数:
#######################################################################
# PART 2 Model & Tokenizer & Image Processor #
#######################################################################
model = dict(
type=InternVL_V1_5,
model_path=path,
freeze_llm=True,
freeze_visual_encoder=True,
# comment the following lines if you don't want to use Lora in llm
llm_lora=dict(
type=LoraConfig,
r=128,
lora_alpha=256,
lora_dropout=0.05,
target_modules=None,
task_type='CAUSAL_LM'),
# uncomment the following lines if you don't want to use Lora in visual encoder # noqa
# visual_encoder_lora=dict(
# type=LoraConfig, r=64, lora_alpha=16, lora_dropout=0.05,
# target_modules=['attn.qkv', 'attn.proj', 'mlp.fc1', 'mlp.fc2'])
)
r
: 低秩矩阵的秩,决定了低秩矩阵的维度。lora_alpha
缩放因子,用于调整低秩矩阵的权重。lora_dropout
dropout 概率,以防止过拟合。
断点重训,配置如下参数:
# load from which checkpoint
load_from = None
# whether to resume training from the loaded checkpoint
resume = False
把这里的load_from
传入你想要载入的checkpoint,并设置resume=True
即可断点重续。
数据集下载
我们采用的是FoodieQA数据集,这篇文章中了2024EMNLP的主会,其引用信息如下:
@article{li2024foodieqa,
title={FoodieQA: A Multimodal Dataset for Fine-Grained Understanding of Chinese Food Culture},
author={Li, Wenyan and Zhang, Xinyu and Li, Jiaang and Peng, Qiwei and Tang, Raphael and Zhou, Li and Zhang, Weijia and Hu, Guimin and Yuan, Yifei and S{\o}gaard, Anders and others},
journal={arXiv preprint arXiv:2406.11030},
year={2024}
}
FoodieQA 是一个专门为研究中国各地美食文化而设计的数据集。它包含了大量关于食物的图片和问题,帮助多模态大模型更好地理解不同地区的饮食习惯和文化特色。这个数据集的推出,让我们能够更深入地探索和理解食物背后的文化意义。
通过如下两种方式获取数据集,根据获取方式的不同,可能需要修改配置文件中的data_root
变量为你数据集的路径:
#######################################################################
# PART 1 Settings #
#######################################################################
# Model
path = '/root/share/new_models/OpenGVLab/InternVL2-2B'
# Data
data_root = '/root/share/datasets/FoodieQA/' # your data path
data_path = data_root + 'sivqa_llava.json'
image_folder = data_root # your image folder path
prompt_template = PROMPT_TEMPLATE.internlm2_chat
max_length = 8192
方式1:
huggingface下载,https://huggingface.co/datasets/lyan62/FoodieQA。该数据集为了防止网络爬虫污染测评效果,需要向提交申请后下载使用。
在命令行登录huggingface后直接在服务器上下载:
huggingface-cli login
然后在这里输入huggingface的具有read
权限的token即可成功登录。
再使用命令行下载数据集:
huggingface-cli download --repo-type dataset --resume-download lyan62/FoodieQA --local-dir /root/huggingface/FoodieQA --local-dir-use-symlinks False
如果觉得上述过程麻烦,可以用浏览器下载后,再上传服务器即可😊
由于原始数据集格式不符合微调需要格式,需要处理方可使用,在InternVL2-Tutorial
下,运行:
python process_food.py
即可把数据处理为XTuner所需格式。注意查看input_path
和output_path
变量与自己下载路径的区别。
方式2:
开发机已经预置数据集,路径``。
开始微调
运行命令,开始微调:
xtuner train /root/xtuner/xtuner/configs/internvl/v2/internvl_v2_internlm2_2b_lora_finetune_food.py --deepspeed deepspeed_zero2
看到有日志输出,即为启动成功:
把/root/xtuner/xtuner/configs/internvl/v2/internvl_v2_internlm2_2b_lora_finetune_food.py
换成自己配置文件的路径即可。
微调后,把模型checkpoint的格式转化为便于测试的格式:
python xtuner/configs/internvl/v1_5/convert_to_official.py xtuner/configs/internvl/v2/internvl_v2_internlm2_2b_lora_finetune_food.py ./work_dirs/internvl_v2_internlm2_2b_lora_finetune_food/iter_640.pth ./work_dirs/internvl_v2_internlm2_2b_lora_finetune_food/lr35_ep10/
如果修改了超参数,iter_xxx.pth
需要修改为对应的想要转的checkpoint。 ./work_dirs/internvl_v2_internlm2_2b_lora_finetune_food/lr35_ep10/
为转换后的模型checkpoint保存的路径。
问题:
(xtuner-env) root@intern-studio-50014188:~/xtuner/xtuner# xtuner train internvl_v2_internlm2_2b_lora_finetune_food.py
--deepspeed deepspeed_zero2
/root/.conda/envs/xtuner-env/lib/python3.10/site-packages/mmengine/optim/optimizer/zero_optimizer.py:11: DeprecationWarning: `TorchScript` support for functional optimizers is deprecated and will be removed in a future PyTorch release. Consider using the `torch.compile` optimizer instead.
from torch.distributed.optim import \
[2025-01-05 13:47:05,878] [INFO] [real_accelerator.py:191:get_accelerator] Setting ds_accelerator to cuda (auto detect)
/root/.conda/envs/xtuner-env/lib/python3.10/site-packages/deepspeed/runtime/zero/linear.py:49: FutureWarning: `torch.cuda.amp.custom_fwd(args...)` is deprecated. Please use `torch.amp.custom_fwd(args..., device_type='cuda')` instead.
def forward(ctx, input, weight, bias=None):
/root/.conda/envs/xtuner-env/lib/python3.10/site-packages/deepspeed/runtime/zero/linear.py:67: FutureWarning: `torch.cuda.amp.custom_bwd(args...)` is deprecated. Please use `torch.amp.custom_bwd(args..., device_type='cuda')` instead.
def backward(ctx, grad_output):
01/05 13:47:13 - mmengine - WARNING - WARNING: command error: 'cannot import name 'log' from 'torch.distributed.elastic.agent.server.api' (/root/.conda/envs/xtuner-env/lib/python3.10/site-packages/torch/distributed/elastic/agent/server/api.py)'!
01/05 13:47:13 - mmengine - WARNING -
Arguments received: ['xtuner', 'train', 'internvl_v2_internlm2_2b_lora_finetune_food.py', '--deepspeed', 'deepspeed_zero2']. xtuner commands use the following syntax:
xtuner MODE MODE_ARGS ARGS
Where MODE (required) is one of ('list-cfg', 'copy-cfg', 'log-dataset', 'check-custom-dataset', 'train', 'test', 'chat', 'convert', 'preprocess', 'mmbench', 'eval_refcoco')
MODE_ARG (optional) is the argument for specific mode
ARGS (optional) are the arguments for specific command
Some usages for xtuner commands: (See more by using -h for specific command!)
1. List all predefined configs:
xtuner list-cfg
2. Copy a predefined config to a given path:
xtuner copy-cfg $CONFIG $SAVE_FILE
3-1. Fine-tune LLMs by a single GPU:
xtuner train $CONFIG
3-2. Fine-tune LLMs by multiple GPUs:
NPROC_PER_NODE=$NGPUS NNODES=$NNODES NODE_RANK=$NODE_RANK PORT=$PORT ADDR=$ADDR xtuner dist_train $CONFIG $GPUS
4-1. Convert the pth model to HuggingFace's model:
xtuner convert pth_to_hf $CONFIG $PATH_TO_PTH_MODEL $SAVE_PATH_TO_HF_MODEL
4-2. Merge the HuggingFace's adapter to the pretrained base model:
xtuner convert merge $LLM $ADAPTER $SAVE_PATH
xtuner convert merge $CLIP $ADAPTER $SAVE_PATH --is-clip
4-3. Split HuggingFace's LLM to the smallest sharded one:
xtuner convert split $LLM $SAVE_PATH
5-1. Chat with LLMs with HuggingFace's model and adapter:
xtuner chat $LLM --adapter $ADAPTER --prompt-template $PROMPT_TEMPLATE --system-template $SYSTEM_TEMPLATE
5-2. Chat with VLMs with HuggingFace's model and LLaVA:
xtuner chat $LLM --llava $LLAVA --visual-encoder $VISUAL_ENCODER --image $IMAGE --prompt-template $PROMPT_TEMPLATE --system-template $SYSTEM_TEMPLATE
6-1. Preprocess arxiv dataset:
xtuner preprocess arxiv $SRC_FILE $DST_FILE --start-date $START_DATE --categories $CATEGORIES
6-2. Preprocess refcoco dataset:
xtuner preprocess refcoco --ann-path $RefCOCO_ANN_PATH --image-path $COCO_IMAGE_PATH --save-path $SAVE_PATH
7-1. Log processed dataset:
xtuner log-dataset $CONFIG
7-2. Verify the correctness of the config file for the custom dataset:
xtuner check-custom-dataset $CONFIG
8. MMBench evaluation:
xtuner mmbench $LLM --llava $LLAVA --visual-encoder $VISUAL_ENCODER --prompt-template $PROMPT_TEMPLATE --data-path $MMBENCH_DATA_PATH
9. Refcoco evaluation:
xtuner eval_refcoco $LLM --llava $LLAVA --visual-encoder $VISUAL_ENCODER --prompt-template $PROMPT_TEMPLATE --data-path $REFCOCO_DATA_PATH
10. List all dataset formats which are supported in XTuner
Run special commands:
xtuner help
xtuner version
GitHub: https://github.com/InternLM/xtuner
与AI美食家玩耍
修改MODEL_PATH为刚刚转换后保存的模型路径:
(base) root@intern-studio-50014188:~# conda activate lmdeploy
(lmdeploy) root@intern-studio-50014188:~# cd InternVL2-Tutorial/
(lmdeploy) root@intern-studio-50014188:~/InternVL2-Tutorial# ls
__pycache__ demo demo.py outputs process_food.py readme.md utils.py xtuner_config
# 修改demo.py MODEL_PATH为刚刚转换后保存的模型路径:
FOOD_EXAMPLES = "demo/food_for_demo.json"
# MODEL_PATH = "/root/share/new_models/OpenGVLab/InternVL2-2B"
MODEL_PATH = "/root/xtuner/work_dirs/internvl_v2_internlm2_2b_lora_finetune_food/lr35_ep10"
OUTPUT_PATH = "./outputs"
启动网页应用:
python demo.py
查看微调后的效果,是否有食物识别错误的现象。
process_food.py readme.md utils.py xtuner_config
修改demo.py MODEL_PATH为刚刚转换后保存的模型路径:
FOOD_EXAMPLES = “demo/food_for_demo.json”
MODEL_PATH = “/root/share/new_models/OpenGVLab/InternVL2-2B”
MODEL_PATH = “/root/xtuner/work_dirs/internvl_v2_internlm2_2b_lora_finetune_food/lr35_ep10”
OUTPUT_PATH = “./outputs”
启动网页应用:
python demo.py
查看微调后的效果,是否有食物识别错误的现象。