🧠 多模态大模型 · Visual Instruction Tuning

LLaVA

Large Language-and-Vision Assistant
一个开源的端到端多模态大模型,让大语言模型"看懂"图像

向下滚动 ↓

LLaVA 是什么?

LLaVA(Large Language-and-Vision Assistant)是 2023 年由 威斯康星大学麦迪逊分校、微软研究院和哥伦比亚大学的研究者共同提出的 开源多模态大语言模型。它是首批将 GPT-4 级别的视觉指令微调 (Visual Instruction Tuning)思路落地到开源模型上的工作之一。

它的核心思想非常简洁:把一个视觉编码器(看图)和一个 大语言模型(说话)用一个投影层连接起来, 让模型能够根据图像内容回答问题、执行指令,实现图文对话。

LLaVA 的意义在于:它证明了仅用极简的架构少量公开数据, 就能训出在多模态基准上接近 GPT-4V 表现的开源模型,极大地推动了多模态开源生态的发展。

2 阶段
训练流程
~150K
指令数据
CLIP+LLM
双塔组合
开源
权重 & 数据

三大组件,一条流水线

LLaVA 的架构可以用一句话概括:图像 → 视觉编码器 → 投影层 → 大语言模型 → 文本输出。 它没有设计复杂的交互模块,而是用最直接的方式把视觉特征"翻译"成语言模型能理解的"词"。

🖼️
图像输入
224×224 / 336×336
👁️
CLIP ViT
视觉编码器(冻结)
🔗
投影层
Linear / MLP
🧠
大语言模型
Vicuna / LLaMA
💬
文本输出
回答 / 描述
关键设计:视觉编码器和语言模型通常都是预训练好的,LLaVA 主要训练的是中间的 投影层(把视觉特征空间对齐到语言模型的词嵌入空间),再通过指令微调让整体学会"看图说话"。

图像怎么"塞进"语言模型?—— <image> 占位 token

LLM 只认文本 token,图像要进入它的输入序列,靠的是一个特殊占位 token——在 prompt 模板里写成 <image>。它干两件事:给 LLM 词表扩一个新"词"并初始化 embedding;在序列里占个位置,等视觉特征备好后,把这个占位符替换成一串视觉 token

USER: <image>
这张图里有什么?
ASSISTANT:
<image> × 1 → 替换成 → 视觉 token × 576 → 拼进 → 文本序列

336×336 的图,ViT-L/14(patch 14)切成 24×24 = 576 个 patch,每个经编码 + 投影层映射成 1 个视觉 token,整体替换掉那个 <image>。这就是上面"投影层"说的"建立视觉 token → 语言空间的映射"。

关键认知:<image> 这个 special token 本身不是加速手段,它只是"接口 / 对齐"机制。真正的性能负担,恰恰是替换进去的那 576 个视觉 token——自注意力是 O(n²),序列暴涨算力平方级上升;每个视觉 token 都要在每层存 K/V,KV Cache 显存随长度线性涨。一张图 576 token,往往比文字 prompt 还长,成了延迟和显存的大头。
那"special token 提速"说的到底是什么?用少量可学习的 special token 压缩图像(代表是 BLIP-2 的 Q-Former):不放 576 个,而是放 32 个可学习 query token,通过交叉注意力把 576 个视觉特征蒸馏成 32 个。序列 576 → 32,注意力算力降一个量级、KV Cache 缩到约 1/18。注意 LLaVA 本身没用这招(它走"全量视觉 token + 简单投影"的简单路线),所以后续优化都是在不动框架的前提下砍 token:FlashAttention 缓解访存、token 裁剪 / 合并直接砍数量、SwiftKV 从 KV Cache 层面让 prompt token 跳过部分后层。少即是快——这就是视觉 token 数量与性能的核心关系。

LLaVA 用到了哪些技术?

从视觉编码到训练优化,LLaVA 站在了一系列成熟技术的肩膀上。

视觉编码

CLIP ViT-L/14

OpenAI 的 CLIP 视觉 Transformer,将图像编码为视觉 token 序列。LLaVA 使用其 ViT-L/14 变体(输入 336×336),在训练中通常冻结权重,只取其强大的图像表征能力。

语言模型

Vicuna / LLaMA

语言解码器。早期 LLaVA 使用 Vicuna(基于 LLaMA 在 ShareGPT 对话数据上微调的对话模型),后续版本也接入了 LLaMA-3、Mistral、Qwen 等更强的基础模型作为后端。

模态对齐

投影层 Projection

连接视觉与语言的桥梁。LLaVA-v1 用单层 Linear,LLaVA-1.5 升级为两层 MLP(多层感知机),把视觉特征映射到 LLM 的词嵌入维度,相当于给模型装上"视觉词汇表"。

数据构造

GPT-4 辅助数据生成

用 GPT-4 基于 COCO 图像的描述和边界框,自动生成多模态指令数据(详细描述、对话、复杂推理三类),无需人工逐条标注,高效构建了 15 万条视觉指令数据集。

高效微调

LoRA / QLoRA

参数高效微调技术。通过在注意力层旁路注入低秩矩阵,只训练极少参数(通常 <1%),让普通 GPU 也能微调大模型,显著降低显存和算力门槛。

分布式训练

DeepSpeed

微软的深度学习优化库,LLaVA 用它做分布式训练与显存优化(ZeRO 切分、混合精度、激活检查点),是训练大模型背后的"加速引擎"。详见下文。

训练框架

PyTorch + Transformers

基于 HuggingFace Transformers 和 PyTorch 实现,配合 DeepSpeed 与 Flash Attention 加速,构成了完整的训练与推理栈。

注意力加速

Flash Attention

IO 感知的注意力实现,减少 GPU HBM 读写,在长上下文和长图像 token 序列场景下显著降低显存、提升速度。

如何从 0 训练一个自己的 LLaVA?

"从零"在这里指从零开始组装并训练自己的多模态模型(视觉编码器和 LLM 通常复用预训练权重)。 整个流程分为数据准备 → 阶段一对齐预训练 → 阶段二指令微调 → 评估四步。

第 0 步

📁 准备数据与预训练权重

选好两个预训练模型作为"地基",并准备图文对齐数据。

  • 视觉编码器:下载 CLIP ViT-L/14(openai/clip-vit-large-patch14-336)
  • 语言模型:下载 Vicuna-7B/13B 或 LLaMA-3-8B 等
  • 对齐数据:CC3M / LAION / LCS-558K(图文对)
  • 指令数据:LLaVA-Instruct-150K(GPT-4 生成)或自建数据
阶段 1 · Stage 1

🎯 特征对齐预训练(Pretrain / Projector)

目标是让投影层学会把视觉特征"翻译"成语言模型能理解的表示。

  • 冻结:视觉编码器 + 大语言模型 全部冻结
  • 可训练:仅投影层(Linear / MLP)
  • 数据:大规模图文对(如 595K),用图像描述作为目标文本
  • 目的:建立"视觉 token → 语言空间"的映射,相当于教模型一套"视觉词汇"
  • 算力:相对便宜,8×A100 数小时内可完成
阶段 2 · Stage 2

🗣️ 视觉指令微调(Visual Instruction Tuning)

让模型学会根据图像执行指令、回答问题,具备对话与推理能力。

  • 冻结:仅视觉编码器冻结(或部分冻结)
  • 可训练:大语言模型 + 投影层(全参微调,或用 LoRA)
  • 数据:15 万条视觉指令数据(详细描述 / 多轮对话 / 复杂推理)
  • 目的:把"看图"能力与"对话/推理"能力打通
  • 算力:较重,需要 DeepSpeed ZeRO-2/3 + 多卡分布式训练
第 3 步

📊 评估与迭代

在多模态基准上评测,根据结果迭代数据和训练策略。

  • 学术基准:GQA、ScienceQA、VQAv2、MMBench、MMBench
  • 综合评测:MMMU、MMBench、MM-Vet、SEED-Bench
  • 对比对象:GPT-4V、其他开源多模态模型

典型的训练启动命令(伪代码示意):

# 阶段一:投影层对齐预训练(冻结 ViT + LLM) deepspeed --num_gpus=8 llava/train/train_mem.py \ --model_name_or_path lmsys/vicuna-7b-v1.5 \ --version v1 \ --vision_tower openai/clip-vit-large-patch14-336 \ --tune_mm_mlp_adapter True \ --mm_vision_select_layer -2 \ --mm_projector_type mlp2x_gelu \ --deepspeed ./scripts/zero2.json \ --output_dir ./checkpoints/llava-7b-pretrain # 阶段二:视觉指令微调(解冻 LLM + 投影层) deepspeed --num_gpus=8 llava/train/train_mem.py \ --model_name_or_path ./checkpoints/llava-7b-pretrain \ --vision_tower openai/clip-vit-large-patch14-336 \ --tune_mm_mlp_adapter True \ --tune_mm_vision_tower False \ --bf16 True \ --deepspeed ./scripts/zero3.json \ --output_dir ./checkpoints/llava-7b-finetune
关于"从零"的说明:完全从随机权重训练一个 LLaVA 是不现实的(需要海量算力和数据)。 业界所说的"从零训自己的模型",通常是指复用预训练的 ViT 和 LLM 权重, 自己训练投影层 + 指令微调,得到一个属于自己的多模态模型。如果连 ViT/LLM 都要自己训, 那是另一个量级的工程(百卡、月级)。

从指令微调到偏好对齐

上一节的"阶段二 视觉指令微调"本质上就是 SFT。它让模型"会做",但要让它"做得合人类心意",往往还要接一层 RL 对齐--这是从"能对话"到"对话讨喜、安全、少幻觉"的关键一跃。

SFT:监督微调(Supervised Fine-Tuning)

用"指令 -> 标准回答"的标注数据,以下一 token 预测(next-token)的方式教模型按指令做事。LLaVA 的 Stage 2 就是 SFT:数据是 GPT-4 基于 COCO 图像自动生成的 15 万条视觉指令(详细描述 / 多轮对话 / 复杂推理三类),免去了人工逐条标注。

两个关键机制:
  • Loss masking(损失掩码):只在 assistant 的回答部分算损失,user / 系统提示部分 mask 掉--不教模型"背诵问题",只教它"怎么答"。
  • Special token 结构化:<image>、对话角色标记等设成 special token,目标序列更短、格式更稳(呼应上一节"少即是快"),也减少 <lable> 这类标签笔误。
SFT 的天花板:模型能力被标注数据的质量和覆盖面卡死。它学的是"模仿标准答案",但"哪个回答更好 / 更安全 / 更少幻觉"这种偏好层面的判断,SFT 给不了--这正是 RL 要补的缺口。

RL:强化学习对齐

核心思想:不再告诉模型"标准答案是什么",而是让它生成回答,由一个奖励信号告诉它"哪个更好",据此调整策略。主流路线有两条:

方法 怎么做 需要 reward model 特点
RLHF(PPO) 先用人类偏好对训一个奖励模型,再用 PPO 以其打分为奖励优化 SFT 模型 是(显式训 RM) 经典三阶段 SFT→RM→PPO;效果好但训练不稳、工程复杂
DPO 不训 RM、不做 PPO,直接用偏好对(chosen / rejected)通过一个简化损失微调 更简单稳定、显存友好,已成主流首选
RLAIF / RLHF-V 用 AI 反馈代替人类标注;或多模态场景下针对幻觉做偏好对齐 视方案而定 省人工、专治 VLM 的"看图瞎编"
和 SFT 的关系:几乎总是 SFT 先、RL/DPO 后--SFT 给模型"基本功",RL/DPO 在此之上做"偏好微调"。所以"对齐"通常指的就是这条"SFT → 偏好优化"流水线,而不是二选一。

DPO 的损失(偏好对形式,伪代码示意):

# DPO:让模型对 chosen 的概率相对 rejected 更高(以 SFT 模型为参照)
loss = -log_sigmoid( beta * ( log_ratio(chosen) - log_ratio(rejected) ) )
# log_ratio(x) = log( π_θ(x) / π_ref(x) ),π_ref 即 SFT 参考策略

DeepSpeed 是什么?

DeepSpeed 是微软开源的深度学习训练优化库, 专为训练超大模型设计。它和 PyTorch 配合使用,能在显存、速度、规模三个维度上 "榨干"硬件性能,是大模型训练的事实标准之一。LLaVA 的多卡训练就依赖它。

🧩 ZeRO 显存优化

Zero Redundancy Optimizer,把优化器状态、梯度、参数切分到多卡上,消除数据并行的冗余,让单卡能训更大的模型。

⚡ 混合精度训练

支持 BF16/FP16,在几乎不损失精度的前提下减半显存、近乎翻倍速度。

💾 激活检查点

用时间换空间,丢弃中间激活值、反向时重算,大幅降低显存峰值,能训更长序列。

🌐 多卡 / 多机分布式

无缝扩展到多 GPU、多节点,配合 ZeRO-3 可训练数百亿参数模型。

ZeRO 的三个阶段

ZeRO 通过逐步切分更多内容,用更多通信换更少显存:

阶段 切分内容 显存节省 通信开销
ZeRO-1 优化器状态(Optimizer States) ~4× 与普通数据并行相当
ZeRO-2 优化器状态 + 梯度(Gradients) ~8× 略增
ZeRO-3 优化器状态 + 梯度 + 参数(Parameters) ~N×(N 为卡数) 显著增加
在 LLaVA 中的使用:阶段一(投影层预训练)通常用 ZeRO-2 即可; 阶段二(全参微调 7B/13B)往往需要 ZeRO-3 才能塞进显存。 一个 JSON 配置文件(如 zero3.json)即可切换策略,无需改动训练代码。
别混淆:DeepSeek ≠ DeepSpeed
你问的 "deepseed" 在 LLaVA 训练语境里通常指 DeepSpeed(微软训练库,发音相近)。 另一个常见词 DeepSeek(深度求索)则是完全不同的东西——它是一家中国 AI 公司, 以 MoE(混合专家)架构的大模型(DeepSeek-V3、R1 推理模型)闻名,与 LLaVA 训练库无直接关系。 两者只是名字相似,请勿混淆。

SwiftKV:让长 prompt 推理更快

LLaVA 用 DeepSpeed 完成训练,那训好之后如何让模型推理更高效SwiftKV 正是 DeepSpeed 作者团队(Samyam Rajbhandari、Yuxiong He 等,现于 Snowflake AI Research) 把优化思路从"训练"延伸到"推理"的代表作。它专门解决企业级场景(RAG、长文档摘要、代码生成)中 长 prompt 带来的 prefill 计算瓶颈

背景:为什么是 Prefill? LLM 推理分两阶段--Prefill(处理整段 prompt、算出 KV Cache,计算密集) 和 Decode(逐 token 生成,访存密集)。RAG / 摘要类应用 prompt 远长于输出,prefill 成了延迟和算力的大头, 而传统针对 decode 的 KV 优化帮不上忙。SwiftKV 就是来砍 prefill 的。

三大核心机制

核心创新

① 跨层 KV 预填充

用前面某一层的输出,直接预填充后面若干层的 KV Cache,让 prompt token 跳过这些后层。 prompt 不必每层都跑一遍 Transformer,通过层间复用省掉大量 prefill 计算。

质量保障

② 知识保留蒸馏

跳层会改变模型行为,所以用一套轻量蒸馏把原模型能力迁移过来,让变换后的模型精度几乎不掉。 这是"无痛跳层"的关键--光跳层质量会崩,蒸馏才稳。

可叠加

③ KV Cache 压缩兼容

天然兼容 KV Cache 压缩(低显存场景进一步省内存),可与 token 裁剪、量化等方法叠加, 在显存受限时进一步提升推理表现。

实测效果(论文数据)

指标 提升
Prefill 计算量降低 25% ~ 50%
端到端聚合吞吐最高 2×
单 token 生成时间降低 60%
Llama-3.1-70B 推理速度16K tokens/s(560 TFlops/GPU)
与 DeepSpeed 的渊源:SwiftKV 的作者 Samyam RajbhandariYuxiong He 正是 DeepSpeed / ZeRO 的提出者。他们从微软转到 Snowflake 后,SwiftKV 可看作 DeepSpeed 从"训练优化" 向"推理优化"的延伸。2025 年 7 月,SwiftKV 被整合进 Snowflake 开源的 Arctic Inference(vLLM 插件, 提出 Shift Parallelism 并发策略),已用于 Snowflake Cortex AI 生产环境。
别被同名论文搞混:arXiv 上还有一篇 2026 年 1 月的同名论文 "SwiftKV: An Edge-Oriented Attention Algorithm..."(Junming Zhang 等),那是另一拨人做的 边缘设备注意力加速器,和 Snowflake 这篇 SwiftKV 毫无关系,只是撞名。业界说的 SwiftKV 默认指 Snowflake 这篇。

📄 论文:SwiftKV: Fast Prefill-Optimized Inference with Knowledge-Preserving Model Transformation(arXiv:2410.03960,2024-10) · 🔗 开源:github.com/snowflakedb/arctictraining

一图回顾全貌

LLaVA = CLIP 视觉编码器 + 投影层 + 大语言模型 + 视觉指令微调

它用最简洁的架构证明了:把现成的"眼睛"(CLIP)和"大脑"(LLM)用一个可训练的"桥梁"(投影层) 连起来,再用 GPT-4 生成的指令数据做两阶段微调(先对齐、再对话),就能得到一个强大的开源多模态助手。 而训练这一切的"加速引擎",就是 DeepSpeed——它通过 ZeRO 切分、混合精度、激活检查点, 把显存和算力压榨到极致,让普通人也能在多卡上训出自己的大模型。 而训完之后要让模型推理更快,同一拨人又拿出了 SwiftKV--用跨层 KV 预填充 + 蒸馏, 把长 prompt 的 prefill 计算砍掉 25~50%。从训练推理,一条完整的优化链路。