LLaVA 视觉语言模型
LLaVA(Large Language-and-Vision Assistant)是开源视觉语言模型的代表性工作,通过将视觉编码器与大型语言模型连接,实现了强大的多模态对话能力,其简洁高效的训练范式影响了后续大量 VLM 的设计。
架构设计
LLaVA 的架构极为简洁,由三个核心组件构成:
- 视觉编码器 CLIP-ViT:提取图像特征,输出 patch 级别的视觉 Token
- 投影层(Projection):将视觉 Token 映射到语言模型的嵌入空间
- 语言模型(LLM):基于 Vicuna/Llama 的解码器,处理融合后的多模态序列
python
import torch
import torch.nn as nn
class LlavaProjector(nn.Module):
"""LLaVA 视觉-语言投影层"""
def __init__(self, vision_dim=1024, llm_dim=4096):
super().__init__()
# 两层 MLP 投影
self.projector = nn.Sequential(
nn.Linear(vision_dim, llm_dim),
nn.GELU(),
nn.Linear(llm_dim, llm_dim),
)
def forward(self, vision_features):
# vision_features: [B, num_patches, vision_dim]
return self.projector(vision_features)
class LlavaForConditionalGeneration(nn.Module):
def __init__(self, vision_encoder, projector, language_model):
super().__init__()
self.vision_encoder = vision_encoder
self.projector = projector
self.language_model = language_model
def forward(self, pixel_values, input_ids, labels=None):
# 提取视觉特征
vision_features = self.vision_encoder(pixel_values)
# 投影到语言空间
vision_embeds = self.projector(vision_features)
# 融合视觉和文本嵌入
inputs_embeds = self.merge_vision_text(input_ids, vision_embeds)
# 语言模型生成
return self.language_model(inputs_embeds=inputs_embeds, labels=labels)训练范式
LLaVA 的训练分为两个阶段:
阶段一:特征对齐预训练
- 冻结视觉编码器和语言模型
- 仅训练投影层
- 使用 CC3M 等大规模图文对数据
- 目标:建立视觉特征到语言空间的映射
阶段二:视觉指令微调
- 解冻语言模型(投影层可选冻结)
- 使用 GPT-4 生成的多模态指令数据
- 目标:让模型学会遵循多模态指令
LLaVA 的数据创新
LLaVA 使用 GPT-4 基于 COCO 图像标注生成多模态指令数据,包括对话、详细描述和复杂推理三种类型,这种"AI 生成训练数据"的范式被后续工作广泛采用。
LLaVA 版本演进
| 版本 | 视觉编码器 | 语言模型 | 关键改进 |
|---|---|---|---|
| LLaVA-1.5 | CLIP-ViT-L/336 | Vicuna-7B/13B | 更高分辨率,更多数据 |
| LLaVA-1.6/Next | CLIP-ViT | Mistral/Llama | 动态分辨率,更强推理 |
| LLaVA-NeXT-Video | CLIP-ViT | Llama | 视频理解扩展 |
| LLaVA-OneVision | SigLIP | Qwen2 | 统一图像/视频/单图 |
动态分辨率
LLaVA-1.6 引入了动态分辨率支持,通过将高分辨率图像切分为多个子图分别编码:
- 每个子图独立通过视觉编码器
- 所有子图的视觉 Token 拼接后输入语言模型
- 保留全局缩略图提供整体上下文
Token 开销
动态分辨率会显著增加视觉 Token 数量,高分辨率图像可能产生数千个视觉 Token,需要关注推理延迟和显存消耗。