LLaVA 与视觉指令微调 本节摘要:LLaVA(2023 年 4 月)是地球上被复制最多的多模态架构。它用两层 MLP 取代 BLIP-2 的 Q-Former,用朴素的 token 拼接取代 Flamingo 的门控交叉注意力,并在 GPT-4 从纯文本 caption 生成的 15.8 万条视觉指令轮次上训练。2023 到 2026 年间,任何动手搭 VLM 的从业者,搭的都是 LLaVA 的某个变体。LLaVA-1.5 加了 AnyRes,LLaVA-NeXT 拔高分辨率,LLaVA-OneVision 把单图、多图、视频统一进一套配方。本节读透这套配方,实现投影器,并解释「为什么更简单的赢了」。
本节摘要:LLaVA(2023 年 4 月)是地球上被复制最多的多模态架构。它用两层 MLP 取代 BLIP-2 的 Q-Former,用朴素的 token 拼接取代 Flamingo 的门控交叉注意力,并在 GPT-4 从纯文本 caption 生成的 15.8 万条视觉指令轮次上训练。2023 到 2026 年间,任何动手搭 VLM 的从业者,搭的都是 LLaVA 的某个变体。LLaVA-1.5 加了 AnyRes,LLaVA-NeXT 拔高分辨率,LLaVA-OneVision 把单图、多图、视频统一进一套配方。本节读透这套配方,实现投影器,并解释「为什么更简单的赢了」。
阅读完本节,你应当能够:
BLIP-2 的 Q-Former(第 03 节)把图像压成 32 个 token,干净、高效、跑分好看。但它有两个问题。
第一,Q-Former 可训练,但它的损失不是最终任务。阶段 1 训 ITC+ITM+ITG,阶段 2 训 LM 损失。query 学到的是某种中间表示,LLM 还得去解码它。信息在瓶颈里流失。
第二,Q-Former 有 1.88 亿参数,在 LLaVA 2023 年的规模下,你得把它和目标 LLM 协同设计。换 LLM,重训 Q-Former;换视觉编码器,重训。每种组合都是一个独立的研发项目。
LLaVA 的答案简单到令人尴尬:拿 ViT 的 576 个 patch token,每个过两层 MLP(1024 → 4096 → 4096),全部 576 个一股脑塞进 LLM 输入序列。没有瓶颈,没有阶段 1 的奇怪目标,直接在 LM 损失上训 MLP。
数据从哪来?LLaVA 的第二个洞见:用 GPT-4(纯文本)生成指令数据。把一张图的 COCO caption 与边界框喂给 GPT-4,让它产出对话、详细描述、复杂推理问题。15.8 万条指令-响应轮次,免费,无需人工标注。
结果:一个在 8 张 A100 上跑一天就成的 VLM,在 MMMU 上击败 Flamingo,还发布了社区可扩展的开源 checkpoint。到 2023 年底已衍生 50+ 个分叉。
LLaVA-1.5 的 13B 版:
1024 → 4096 → 4096。图像 + 文本 prompt 的前向:
img -> ViT -> 576 个维度 1024 的 patch patches -> MLP -> 576 个维度 4096 的 token prompt: system + "<image>" 占位符 + 用户问题 把 <image> 替换成 576 个投影后的 token 把完整序列喂给 LLM 解码响应
图像占 LLM 上下文 576 个 token。2048 上下文时给文本留 1472 个;32k 上下文时只是舍入误差。
冻结 ViT、冻结 LLM,只训两层 MLP。数据集:55.8 万图文对(LAION-CC-SBU)。损失:在投影后图像 token 条件下,对 caption 做 LM。batch 128、单 epoch,几小时搞定。投影器学会把 ViT 空间映射到 LLM 空间,没有任务专属监督。
投影器解冻(仍可训),LLM 解冻(通常全量,有时用 LoRA)。在 15.8 万条视觉指令轮次上训练。
指令数据是关键。Liu 等人这样生成:
这些都不直接碰图像,只碰文本描述。GPT-4 会幻觉出看似合理的图像内容,有噪声,但管用:15.8 万轮次足以解锁对话能力。
**LLaVA-1.5(2023 年 10 月)**新增:
**LLaVA-NeXT(2024 年 1 月)**新增:
第 08 节深入讲 OneVision。简版:同样的投影器,但用一套课程训练,让单图、多图、视频在一个模型里共享视觉 token 预算。
| Q-Former(BLIP-2) | MLP(LLaVA) | |
|---|---|---|
| 每图视觉 token | 32 | 576(基线)或 2880(AnyRes) |
| 可训练参数 | 1.88 亿 + LM | 4000 万 + LM |
| 阶段 1 损失 | ITC+ITM+ITG | 纯 LM |
| LLM 即插即用 | 需重训 | 换 LLM 几乎免重训 |
| 多图 | 别扭 | 自然(拼接) |
| 视频 | 别扭 | 自然(逐帧拼接) |
| token 预算 | 小 | 大 |
MLP 在简洁性与 token 灵活性上胜,Q-Former 在 token 预算上胜。到 2023 年底,token 预算不再是约束(LLM 上下文涨到 32k~128k+),简洁性主导。
A chat between a curious human and an artificial intelligence assistant. The assistant gives helpful, detailed, and polite answers to the human's questions. USER: <image> Describe this image in detail. ASSISTANT: The image shows ...
<image> 是占位符 token。分词前,它被替换成 576 个视觉 token(AnyRes 则 2880 个)。分词器看到的序列比它训练时略长,但 LLM 能处理这个新输入,因为阶段 1 教过它了。
LLaVA-1.5-7B 拆解:
阶段 2 训练成本:8×A100 约 20 小时。这是关键数字——一天、一节点、可复现。LLaVA 之所以扩散,就在于此。
code/main.py 实现:
16 → 32 → 32),纯 Python。<image> 替换成 N 个投影 token + user 轮次 + assistant 生成占位符。# 输入: ViT patch 嵌入 (576, 1024) W1, b1 = ..., ... # (1024, 4096), (4096,) W2, b2 = ..., ... # (4096, 4096), (4096,) h = gelu(patches @ W1 + b1) # (576, 4096) visual_tokens = h @ W2 + b2 # (576, 4096) —— 这就是喂给 LLM 的视觉 token
💡 关键点:投影器是 LLaVA 唯一在阶段 1 训练的组件,参数量仅约 2200 万。它把 ViT 空间「翻译」到 LLM 空间——这就是模态融合的全部秘密:一个学出来的线性映射。
def build_llava_prompt(image_tokens, system, user_question): # 图像 token 拼成字符串占位 img_str = "".join(["<img_tok>" for _ in range(len(image_tokens))]) prompt = (f"{system}\nUSER: <image> {user_question}\nASSISTANT:") # 分词后把 <image> 这个特殊 token 展开成视觉 token 的嵌入 return replace_image_placeholder(prompt, image_tokens)
def stage1(projector, vit, llm, caption_pairs): freeze(vit); freeze(llm) # 只训投影器 for img, caption in caption_pairs: patches = vit(img) # (576, 1024) v_tokens = projector(patches) # (576, 4096) loss = llm.lm_loss(concat(v_tokens, embed(caption))) backward(loss); step(projector) def stage2(projector, vit, llm, instruct_data): unfreeze(projector); unfreeze(llm) # 全量可训 for img, instruction, response in instruct_data: v_tokens = projector(vit(img)) loss = llm.lm_loss(concat(v_tokens, embed(instruction+response))) backward(loss); step(projector, llm)
llava/model/projector/builder.py 一行 build_mlp_projector,两阶段训练脚本 scripts/finetune*.sh,定义了 LLaVA 系的事实标准。LlavaNextProcessor + LlavaNextForConditionalGeneration,AnyRes 切图内置,接 HF 流水线;切到不同 LLM 只改 language_model 字段。工程取舍:快速复现用 transformers;做投影器消融用 Prismatic;追新论文用各官方仓库。换 LLM 时只重训投影器是 LLaVA 的核心工程优势。
本节产出 outputs/skill-llava-vibes-eval.md。给定一个 LLaVA 系 checkpoint,它跑一套 10 条 prompt 的「感觉评估」套件(3 条 caption、3 条 VQA、2 条推理、2 条拒答),产出人类可读的成绩单。不是基准,是个烟雾测试,确认投影器与 LLM 连接良好。
算投影器参数:算两层 MLP 投影器在 1024 → 4096 → 4096 下的可训练参数量(含 GELU 与偏置)。它占 LLaVA-13B 的多少比例?
拒答 prompt:为「图像含普通私人」的拒答场景构造一个 LLaVA prompt,写出期望的助手响应。为什么 LLaVA 应该零样本拒答?需要什么训练数据来强化拒答?
AnyRes token:读 LLaVA-NeXT 博客的 AnyRes 章节,算一张 1344×672 图在 AnyRes 下的视觉 token 数,对比基线 336×336 的 576 token。
跳过阶段 1:LLaVA 阶段 1 投影器用 caption 上的 LM 损失训练。如果跳过阶段 1 直接进阶段 2(视觉指令微调)会怎样?引用 Prismatic VLMs 的消融(arXiv:2402.07865)给答案。
新领域数据:LLaVA-Instruct-150k 用 GPT-4 配 COCO caption 生成指令。为新领域(医学 X 光、卫星图)描述生成领域指令的四步流水线,每步可能出什么问题?
1024 → 4096 → 4096 带 GELU,约 2200 万参数,阶段 1 唯一训练对象。下一节,我们将进入任意分辨率——Patch-n'-Pack 与 NaFlex 如何让 VLM 处理任意宽高比与高分辨率,而不必把图硬塞进固定网格,这是 2026 年视觉塔的标配。