Li J, Li D, Savarese S, et al. Blip-2: Bootstrapping language-image pre-training with frozen image encoders and large language models[J]. arXiv preprint arXiv:2301.12597, 2023.
BLIP-2,是 BLIP 系列的第二篇,同样出自 Salesforce 公司,2023 年初挂在了 arXiv 上,不到一年时间已经拥有 600+ 引用量,可见其影响力。现在很多多模态大模型都是基于 BLIP-2 进一步拓展的。
与 ALBEF、BLIP 类似,BLIP-2 的目标是训练一个图文多模态预训练模型。不同点是,BLIP-2 是使用现有的单模态编码器,并且分两阶段冻结图像编码器和文本编码器训练出多模态预训练模型。这使得 BLIP-2 能够在降低训练成本的同时提高性能,给其带来了巨大的优势。
本文不再按照论文解读的方式逐段记录,只专注于介绍 BLIP-2 技术本身。本文参考 多模态学习6—深入理解BLIP-2,更多参考资料如下:
- 全文翻译:BLIP2:下一代多模态模型的雏形;
- 文章总结:[BLIP/BLIP2/InstructBLIP] 图文多模态理解与生成、一文读懂BLIP和BLIP-2多模态预训练;
- 领域现状:多模态大模型 CLIP, BLIP, BLIP2, LLaVA, miniGPT4, InstructBLIP 系列解读;
目录
- 一. 背景
- 二. BLIP-2 原理
- 1. BLIP-2 模型
- 2. 预训练方法
- 三. 实验
- 1. 实验结果
- 2. 对比实验
- 四. 总结
- 五. 复现
一. 背景
现有的视觉语言预训练 (VLP) 方法在训练图文多模态模型时,往往采用端到端的训练模式,主要存在以下两个问题:
- 训练成本大:多模态模型需要大量数据,并且模型结构复杂,因此训练成本较高;
- 模型灾难性遗忘:大语言模型在微调时,会产生遗忘现象。因此如果直接将单模态的预训练模型加入到多模态模型中进行联合训练,可能会产生灾难性的遗忘问题;
为此,作者提出了 BLIP-2 模型:
- 使用现有的预训练过的视觉模型和语言模型(本文使用的是 大语言模型 LLM),避免 从头训练 (train-from-scratch),以减少训练成本;
- 预训练期间 冻结 (froze) 单模态模型的参数,从而避免模型的灾难性遗忘;
- 要想使用预训练过的单模态模型,就必须保证跨模态间能够对齐。为了让两个冻结的单模态模型对齐,引入了 Querying Transformer (Q-Former) 模块来对图文进行对齐,从而让图像和文本产生交互;
LLM 本质上是个语言模型,无法直接接受其他模态的信息,所以需要把各个模态的信息统一到 LLM 能理解的特征空间。为此,作者提出了 Q-Former。为了融合特征,那 Q-Former 采用 transformer 架构最合适不过了。其实这里的 Q-Former 就是在 ALBEF 的基础上改进得到的。
相较于 ALBEF,Q-Former 最大的不同就是引入了 Queries。这些 Queries 通过 Cross-Attention 与图像的特征交互,通过 Self-Attention 与文本的特征交互。
二. BLIP-2 原理
BLIP-2 全称也是 Bootstrapping Language-Image Pre-training,是一种 冻结现有视觉模型和大语言模型的预训练模型。这里的 Bootstrapping 指的是预训练阶段使用先前的学习结果来改进当前的学习结果:第一阶段的预训练使用冻结的视觉模型来学习图像 - 文本表示,第二阶段的预训练使用冻结的大型语言模型来学习图像 - 文本生成。
1. BLIP-2 模型
BLIP-2 由预训练的视觉模型 Image Encoder、预训练的大语言模型 Large Language Model、可学习的 Q-Former 组成:
- Image Encoder:从输入图片中提取视觉特征。文中采用了两种不同的网络结构:CLIP 训练过的 ViT-L/14 和 EVA-CLIP 训练过的 ViT-g/14;
- Large Language Model:大语言模型进行文本生成。文中采用了尝试了两种不同的网络结构:decoder-based LLM 和 encoder-decoder-based LLM;
- Q-Former:弥补视觉和语言两种模态间的差异,实现跨模态间的对齐。Q-Former 使用了一组可学习的 查询向量 Queries 来从冻结的 Image Encoder 中提取视觉特征,然后传入 LLM 供其生成文本;
整个模型的流程是:Image Encoder 接收图像作为输入,输出图像的视觉特征;Q-Former 接收文本和 Image Encoder 输出的图像视觉特征,结合查询向量进行融合,学习与文本相近的视觉特征,输出 LLM 能够理解的视觉表示;最后 LLM 模型接收 Q-Former 输出的视觉标识,生成对应文本。
2. 预训练方法
在介绍 Q-Former 的训练方法之前,需要先明确 Q-Former 的结构:Q-Former 由 Image Transformer 和 Text Transformer 两个子模块构成,它们共享相同的自注意力层:
- Image Transformer:用于与冻结的图像编码器进行交互,从中提取一定数量的输出特征;
- Text Transformer:既可以作为文本编码器,也可以作为文本解码器。它创建一组可学习的 Queries 作为 Image Transformer 的输入,这些 Queries 在 Image Transformer 中通过自注意力层相互作用,并通过交叉注意力层与冻结的图像特征进行交互。根据预训练任务的不同,可以应用不同的自注意力掩码来控制查询文本交互;
Q-Former 使用 BERTbase 的预训练权重初始化,而交叉注意力层则是随机初始化。Q-Former 总共包含 188M 的参数。
预训练 Q-Former 时采用两阶段的训练策略:
-
第一阶段:冻结 Image Encoder 的参数,训练 Queries 和 Q-Former,让 Queries 能够从 Image Encoder 中提取图像特征,转化为和文本特征接近的视觉特征。这一阶段相当于在将图像特征空间拉近到文本特征空间;
-
第二阶段:冻结 LLM 的参数,训练 Queries 和 Q-Former,使得模型能够获取强大的 zero-shot 能力和图像生文本的能力。这一阶段相当于学习如何将视觉信息转换为自然语言文本,以便在后续的任务中生成与图像相关的自然语言描述;
两阶段的具体训练方法详见 多模态学习6—深入理解BLIP-2。
从功能上讲,Q-Former 机制本质上是为了对齐图像和文本。如果没有对齐操作,直接进行第二阶段的 LLM 生成任务学习,那么模型最后的结果会比较差,论文中也有实验证明。但对齐操作并不是一定需要 Q-Former 这种形式么,只要能够将 Image encoder 提取的原始图像特征进行某种程度的映射,理论上就可以进行对齐。但采用 Q-Former 确实有一些明显的优势,包括特征数量的固定、参数共享等。
三. 实验
1. 实验结果
下图的 zero-shot image-to-text generation 示例展现了 BLIP-2 模型超强的能力,包括视觉对话、知识推理、信息检索、语言表达、文本生成等:
2. 对比实验
文中还对比了不同 VLP 模型在 Image Captioning、VQA、Image-Text Retrieval 等任务上的表现:
四. 总结
BLIP-2 是一个典型的图文多模态模型,使用训练好的单模态模型和 Q-Former 机制,通过两阶段训练对不同模态进行对齐,有效地减少了训练成本并解决了模型的遗忘现象。
作者在文末表明,BLIP-2 也存在一些局限性:
- 上下文学习能力的缺失:由于预训练数据集中的每个数据只包含一个图像 - 文本对,因此 LLM 无法学习到一个序列中多个图像 - 文本对的相关性;
- LLM 知识库的不准确性:由于语言任务完全依赖 LLM,因此 LLM 知识库的不准确性和滞后性都会对语言任务的结果带来影响。并且冻结 LLM 参数还会带来一定的风险,包括 LLM 中的攻击性语言、社会偏见等。一种解决办法是进行微调,或者对有害数据集进行过滤;
五. 复现
Salesforce 没有开源预训练的代码,只开源了 训练好的模型 和 API,通过导入 lavis.models
包进行调用,可以直接拿来做下游任务。网页版的 Demo 也可以在线完成 Image Captioning、VQA 等任务(已停用)。
以 blip2_instructed_generation.ipynb 为例,调用 BLIP-2 提供的 API 处理下游任务。一开始使用的是 Google Colab,但加载模型时内存超限;后来换成 AutoDL,但 demo 文件调用封装的 lavis.models
需要从 https://huggingface.co/models 加载,遇到 OSError: Can't load tokenizer for 'bert-base-uncased'.
问题,查阅 huggingface 的讨论区发现是网络问题 1,AutoDL不能访问。下面只展示 demo 里自带的实验结果。
实验结果:
What to do when HuggingFace throws “Can’t load tokenizer” ↩︎