Skip to content

Latest commit

 

History

History
327 lines (246 loc) · 9.65 KB

L2 G4000.md

File metadata and controls

327 lines (246 loc) · 9.65 KB

InternVL 的部署与微调

1. 多模态模型 基础

1.1 多模态大模型的常见设计模式

我所理解的多模态大模型的常见设计模式:

image

多模态大模型的工作原理:

  1. 以大语言模型为基础架构,作为统一的推理和生成骨干网络
  2. 多模态输入处理:通过各自的编码器(encoder)+适配器(adapter)的方式处理图片、音频等多模态输入,将不同模态对齐到语言模型的语义空间
    • 通过专门的编码器(encoder)处理各类输入:
      • 图像编码器(如CLIP, ViT)
      • 音频编码器(如Wav2Vec)
      • 视频编码器等
    • 对齐策略的多样性:
      • 适配器(adapter)对齐
      • 投影层对齐
      • 交叉注意力对齐
  3. 特征融合和生成
    • 多模态特征的交互和融合:
      • 通过交叉注意力机制实现模态间信息交换
      • 多层次的特征融合
    • 解码过程:
      • 基于融合特征的序列生成
      • 上下文感知的多模态理解

image

1.2 InternVL的设计

简要阅读了InternVL1.5的论文

InternVL 1.5 模型架构:

image

InternVL 1.5 的训练过程:

  1. 基础模型准备:

    • 视觉基础模型: InternViT-6B
    • 语言基础模型: InternLM2-20B(Chat版本)
  2. 视觉编码器的持续学习(Continuous Learning)优化:

    A. InternViT-6B-448px-V1.2 的优化:

    • 移除最后 3 层(从48层减少到45层)
    • 分辨率从 224 提升到 448
    • 使用图像描述和OCR数据集训练
    • 此时是与 Nous-Hermes-2-Yi-34B 配合

    B. InternViT-6B-448px-V1.5 的进一步优化:

    • 基于 V1.2 版本继续训练
    • 扩展到动态 448×448 分辨率(1-12块)
    • 增强数据规模、质量和多样性
    • 提升 OCR 能力和高分辨率处理能力
  3. 两阶段训练流程:

    A. 预训练阶段:

    • 训练目标: 优化视觉编码器和 MLP 投影层
    • 预训练数据:
      • 图像描述 (53.9%)
      • OCR 数据 (40.9%)
      • 检测数据 (5.2%)

    B. 微调阶段:

    • 训练目标: 整个模型端到端训练
    • 微调数据类型: 多样化的下游任务数据,提高多模态理解能力
      • 图像描述
      • 通用问答
      • 科学理解
      • 图表理解
      • 数学推理
      • 知识问答
      • OCR 任务
      • 文档理解
      • 视觉定位
      • 多轮对话

一个重要发现是:

论文特别提到:"值得注意的是,尽管 InternVL 1.5 中的 LLM 从 Nous-Hermes-2-Yi-34B 换成了 InternLM2-20B,但 InternViT 仍然保持了与新 LLM 的出色兼容性和可移植性。这表明 InternViT-6B 在 MLLM 预训练阶段学习到的视觉特征具有广泛的适用性,并不与特定的 LLM 紧密绑定。"

这说明:

  1. 视觉编码器的训练是相对独立的
  2. 训练好的视觉编码器可以和不同的LLM配合使用
  3. 这种设计增加了模型的灵活性和可复用性

2. 配环境

xtuner 的环境:复用此前 L1 G5000 课程配好的xtuner环境,额外执行下面一行即可:

pip install -U 'xtuner[deepspeed]' timm==1.0.9

lmdeploy 的环境:

pip install lmdeploy gradio==4.44.1 timm==1.0.9

3. 部署

3.1 LMDeploy部署多模态大模型

lmdeploy推理的核心代码可以总结为:

  1. 🔧 初始化配置(创建管线)
  2. ⚙️ 设置参数(控制生成)
  3. 🗣️ 开始对话(首次对话)
  4. 💬 持续对话(后续对话)
"""
LMDeploy 多模态对话系统示例
该示例展示了如何使用 LMDeploy 构建一个支持图文多轮对话的系统
"""

## 1. 导入必要的包
# lmdeploy 核心功能
from lmdeploy import pipeline, TurbomindEngineConfig, GenerationConfig
# 图像加载工具
from lmdeploy.vl import load_image

## 2. 初始化模型和配置
# 设置模型路径
model_path = "your_model_path"
# 创建推理管线
# TurbomindEngineConfig: 推理引擎配置
pipe = pipeline(model_path,
               backend_config=TurbomindEngineConfig(session_len=8192))

## 3. 准备输入数据
# 加载图片 (支持多种格式如 jpg, png)
# 也可以使用 PIL.Image.open() 加载
image = load_image('your_image_path')

## 4. 设置生成参数
# GenerationConfig: 控制文本生成的行为
gen_config = GenerationConfig(
    top_p=0.8,          # 采样时的累积概率阈值
    temperature=0.8     # 温度参数,调节输出的随机性
)

## 5. 开始首轮对话
# pipe.chat(): 启动对话
# - 输入: ('提示词', 图片对象)
# - gen_config: 上面设置的生成参数
# 返回: session 对象,包含对话状态
sess = pipe.chat(
    ('describe this image', image),  # 元组形式传入提示词和图片
    gen_config=gen_config
)
# 打印模型回复
print("模型回复:", sess.response.text)

## 6. 继续多轮对话
# 传入:
# - 新的问题
# - session: 上一轮返回的会话状态,保持对话连贯性
# - gen_config: 生成参数
sess = pipe.chat(
    'What is the woman doing?',  # 新的问题
    session=sess,                # 传入上一轮对话的 session
    gen_config=gen_config       # 保持相同的生成参数
)
# 打印新的回复
print("模型新回复:", sess.response.text)

3.2 WebUI

运行提供的gradio代码,在UI界面体验与InternVL2的对话:

在微调之前,模型的表现有点难绷。

image

image

4. 微调

了解XTuner,并利用给定数据集微调InternVL2-2B后,再次启动UI界面,体验模型美食鉴赏能力的变化。

4.1 微调配置

  1. 训练策略:

    • 只在语言模型部分加入 LoRA 进行训练
    • 视觉编码器完全冻结,且没有使用 LoRA
    • LoRA 配置:
      • 在语言模型部分使用了 LoRA
      • rank(r) = 128
      • lora_alpha = 256
      • dropout = 0.05
      • 注释掉了视觉编码器的 LoRA 配置
  2. 训练超参数:

    • 批次大小:4
    • 梯度累积:2 次
    • 最大训练轮次:10 epochs
    • 学习率:3e-5
    • 优化器:AdamW (β1=0.9, β2=0.999)
    • 权重衰减:0.05
    • 使用了混合精度训练 (AmpOptimWrapper)
  3. 学习率调度:

    • 使用了两阶段学习率调度:
      1. warmup阶段:LinearLR,热身比例为 3% 的总轮次
      2. 主要训练阶段:CosineAnnealingLR,从热身结束到训练结束
  4. 数据处理:

    • 最大序列长度:8192 tokens
    • 使用 LengthGroupedSampler 进行采样
    • 设置了 4 个数据加载工作进程

4.2 了解数据集

是一个中餐美食相关的问答多模态数据集。

阅读数据的sivqa_llava.json 文件,可以看出:

  • 每个样本包含:
    • 一张食物图片
    • 一轮问答对话(human 提问,gpt 回答)
[
    {
        "image": "图片相对路径",
        "conversations": [
            {
                "from": "human/gpt",  # 对话角色
                "value": "对话内容"    # 包含问题或答案
            },
            ...
        ]
    },
    ...
]

具体处理流程:

  1. 图像处理:
    • 图片会被视觉编码器单独处理,转换成视觉特征(visual features)
    • InternVL 使用的是类 CLIP 的视觉编码器,会将图片编码成固定维度的特征向量
# 伪代码表示
image = load_image("images/14456664_217_IMG_3854.jpeg")
# 预处理:调整大小、裁剪、标准化等
processed_image = preprocess(image)
# 通过视觉编码器获取特征
image_features = vision_encoder(processed_image)
  1. 文本处理:
# 使用模板格式化对话
formatted_text = PROMPT_TEMPLATE.internlm2_chat(
    human="图片中的食物通常属于哪个菜系?\n<image>",
    assistant="新疆菜,图中的菜是烤羊肉串"
)

# 转换为token ids
input_ids = tokenizer(formatted_text)

# 创建标签(-100表示不计算loss的位置)
labels = input_ids.clone()
labels[:human_text_end] = -100  # 人类问题部分不计算loss
  1. 最终批处理:
batch = {
    "image_features": torch.stack([sample1_img, sample2_img, ...]),  # [B, num_patches, hidden_size]
    "input_ids": torch.stack([sample1_ids, sample2_ids, ...]),      # [B, seq_len]
    "attention_mask": torch.stack([sample1_mask, sample2_mask, ...]),
    "labels": torch.stack([sample1_labels, sample2_labels, ...])
}

最终,模型会:

  1. 使用视觉编码器处理 image_features
  2. 使用语言模型处理 input_ids
  3. 将两种模态的特征融合
  4. 生成回答并计算与 labels 的损失

这也解释了为什么配置文件中只训练语言模型的 LoRA:主要的适配工作是在多模态融合后的语言生成部分。

4.3 启动微调

XTuner使用流程:

  1. 准备好微调的数据
  2. 写好微调配置文件
  3. 开跑!

使用课程提供的配置文件,显存占用在32G左右:

image

训练结束,共用时1h33min:

image

lora文件288MB: image

4.3 检验微调效果

xtuner 的环境下进行模型转换。

然后运行WebUI:

image

image