书生浦语大模型实战营第四期:InternVL 多模态模型部署微调实践
- 教程链接:https://github.com/InternLM/Tutorial/tree/camp4/docs/L2/InternVL
- 视频链接:https://www.bilibili.com/video/BV1nESCYWEnN/
- 任务链接:https://github.com/InternLM/Tutorial/blob/camp4/docs/L2/InternVL/task.md
- 提交链接:https://aicarrier.feishu.cn/share/base/form/shrcnUqshYPt7MdtYRTRpkiOFJd
任务说明
基础任务(完成此任务即完成闯关)
- 理解多模态大模型的常见设计模式,可以大概讲出多模态大模型的工作原理。
- 了解InternVL2的设计模式,可以大概描述InternVL2的模型架构和训练流程。
- 了解LMDeploy部署多模态大模型的核心代码,并运行提供的gradio代码,在UI界面体验与InternVL2的对话。
- 了解XTuner,并利用给定数据集微调InternVL2-2B后,再次启动UI界面,体验模型美食鉴赏能力的变化。
- 将训练好的模型上传到 Hugging Face 或 ModelScope 上,模型名称包含 InternVL 关键词(优秀学员必做)
基础1:多模态大模型常见设计模式&工作原理
视频内容
举例:
简单总结
多模态大语言模型MLLM是指能够处理和融合多种不同类型数据(如文本、图像、音频、视频等)的大型人工智能模型,这些模型通常基于
深度学习技术,能够理解和生成多种模态的数据,从而在各种复杂的应用场景中表现出强大的能力。
多模态大模型研究的重点是不同模态特征空间的对齐,常见设计模式主要有:
- 以Blip2,Mini-GPT4为代表的Q-Former路线
- 以LLaVA, LLaVA-NEXT为代表的Linear Projector/MLP路线
Q-Former由两个transformer子模块组成,一个是query encoder(可学习的查询编码器),另一个是text encoder & decoder(文本编码器和解码器)。这两个子模块通过cross attention(交叉注意力)机制进行交互,以实现视觉和文本信息的对齐和融合。Q-Former旨在通过一组可学习的query tokens来压缩和提取视觉特征,这些特征能够被大语言模型所解释和利用。它使用了一个轻量级的transformer结构,包含一个可学习的query向量集,用于从冻结的视觉模型中提取视觉特征。Q-Former由两个transformer子模块组成,一个是query encoder(可学习的查询编码器),另一个是text encoder & decoder(文本编码器和解码器)。这两个子模块通过cross attention(交叉注意力)机制进行交互,以实现视觉和文本信息的对齐和融合。由于参数量大、收敛速度慢以及信息损失等问题,Q-Former在某些任务上可能受到限制。此外,Q-Former的训练过程也相对复杂,需要较高的计算资源。
LLaVA的架构包括视觉编码器、语言模型和线性投影三个核心组件。视觉编码器用于处理输入图像以提取特征,语言模型用于理解和生成语言响应,线性投影则作为视觉特征和语言模型嵌入空间之间的桥梁。LaVA 的对齐方式相对来说比较简单,只有简单的线性层。Linear Projector 没有视觉信息损失、训练收敛快、表现也好。
基础2:InternVL2设计模式,模型架构&训练流程
InternVL2的设计基本上都在这个图里了,包括InternViT、Pixel Shuffle、动态处理高分辨率图片、基于InternLM2的Tokenizer
下面是各个部件的细节说明:
训练是分阶段的,先训MLP Projector部分,第二阶段是联合训练,主要是视觉文本指令
大概有这些知识点,先动手操作一下,后面慢慢看~
LMDeploy部署多模态大模型
回顾了一下LMDeploy的优点
LMdeploy的环境配置之前基础岛都搞过了,可以回去翻翻,这里直接部署:
改下教程提供的demo.py
中的模型路径即可。
PS:本人也遇到了教程中所说的这个问题:
这个直接按照教程搞下就ok了,可能异步并发的时候也会有bug,遇到再说~
import os
import random
import numpy as np
import torch
import torch.backends.cudnn as cudnn
import gradio as gr
from utils import load_json, init_logger
from demo import ConversationalAgent, CustomTheme
FOOD_EXAMPLES = "demo/food_for_demo.json"
# MODEL_PATH = "/root/share/new_models/OpenGVLab/InternVL2-2B"
MODEL_PATH = '../InternVL2-2B'
# MODEL_PATH = "/root/xtuner/work_dirs/internvl_v2_internlm2_2b_lora_finetune_food/lr35_ep10"
OUTPUT_PATH = "./outputs"
def setup_seeds():
seed = 42
random.seed(seed)
np.random.seed(seed)
torch.manual_seed(seed)
cudnn.benchmark = False
cudnn.deterministic = True
def main():
setup_seeds()
# logging
init_logger(OUTPUT_PATH)
# food examples
food_examples = load_json(FOOD_EXAMPLES)
agent = ConversationalAgent(model_path=MODEL_PATH,
outputs_dir=OUTPUT_PATH)
theme = CustomTheme()
titles = [
"""<center><B><font face="Comic Sans MS" size=10>书生大模型实战营</font></B></center>""" ## Kalam:wght@700
"""<center><B><font face="Courier" size=5>「进阶岛」InternVL 多模态模型部署微调实践</font></B></center>"""
]
language = """Language: 中文 and English"""
with gr.Blocks(theme) as demo_chatbot:
for title in titles:
gr.Markdown(title)
# gr.Markdown(article)
gr.Markdown(language)
with gr.Row():
with gr.Column(scale=3):
start_btn = gr.Button("Start Chat", variant="primary", interactive=True)
clear_btn = gr.Button("Clear Context", interactive=False)
image = gr.Image(type="pil", interactive=False)
upload_btn = gr.Button("🖼️ Upload Image", interactive=False)
with gr.Accordion("Generation Settings"):
top_p = gr.Slider(minimum=0, maximum=1, step=0.1,
value=0.8,
interactive=True,
label='top-p value',
visible=True)
temperature = gr.Slider(minimum=0, maximum=1.5, step=0.1,
value=0.8,
interactive=True,
label='temperature',
visible=True)
with gr