使用 BLIP-2 进行零样本图像到文本生成
本指南介绍 Salesforce Research 的 BLIP-2,它实现了一套最先进的视觉-语言模型,现已在 🤗 Transformers 中可用。我们将向您展示如何将其用于图像描述、带提示的图像描述、视觉问答和基于聊天的提示。
目录
引言
近年来,计算机视觉和自然语言处理领域取得了快速发展。然而,许多现实世界问题本质上是多模态的——它们涉及多种不同形式的数据,例如图像和文本。视觉-语言模型面临着结合模态的挑战,以便它们能够为广泛的应用打开大门。视觉语言模型可以解决的一些图像到文本任务包括图像描述、图像-文本检索和视觉问答。图像描述可以帮助视障人士,创建有用的产品描述,识别文本之外的不当内容等。图像-文本检索可以应用于多模态搜索,以及自动驾驶等应用。视觉问答可以帮助教育,实现多模态聊天机器人,并协助各种领域特定的信息检索应用。
现代计算机视觉和自然语言模型的能力更强;然而,与它们的先辈相比,它们的规模也显著增加。虽然预训练单一模态模型耗费资源且成本高昂,但端到端视觉和语言预训练的成本变得越来越高。 BLIP-2 通过引入一种新的视觉-语言预训练范式来解决这一挑战,该范式可以潜在地利用预训练视觉编码器和 LLM 的任何组合,而无需端到端预训练整个架构。这使得在多个视觉-语言任务上获得最先进的结果,同时显著减少了可训练参数的数量和预训练成本。此外,这种方法为多模态 ChatGPT 类模型铺平了道路。
BLIP-2 内部机制解析
BLIP-2 通过在现成的冻结预训练图像编码器和冻结大型语言模型之间添加一个轻量级查询 Transformer(Q-Former),弥合了视觉和语言模型之间的模态差距。Q-Former 是 BLIP-2 中唯一可训练的部分;图像编码器和语言模型都保持冻结。
Q-Former 是一个 Transformer 模型,由两个共享相同自注意力层的子模块组成
- 一个图像 Transformer,与冻结的图像编码器交互以进行视觉特征提取
- 一个文本 Transformer,可以兼作文本编码器和文本解码器
图像 Transformer 从图像编码器中提取固定数量的输出特征,与输入图像分辨率无关,并接收可学习的查询嵌入作为输入。查询还可以通过相同的自注意力层与文本交互。
Q-Former 分两个阶段进行预训练。在第一阶段,图像编码器被冻结,Q-Former 通过三个损失进行训练
- 图像-文本对比损失:计算每个查询输出和文本输出的 CLS 标记之间的成对相似度,并选择最高的一个。查询嵌入和文本彼此“不可见”。
- 图像-基础文本生成:查询可以相互关注,但不能关注文本标记,并且文本具有因果掩码,可以关注所有查询。
- 图像-文本匹配损失:查询和文本可以相互可见,并获得一个逻辑值以指示文本是否与图像匹配。为了获得负样本,使用了硬负采样。
在第二个预训练阶段,查询嵌入现在具有与文本相关的视觉信息,因为它已通过信息瓶颈。这些嵌入现在用作 LLM 输入的视觉前缀。此预训练阶段有效地涉及使用因果 LM 损失的图像-基础文本生成任务。
作为视觉编码器,BLIP-2 使用 ViT,而对于 LLM,论文作者使用了 OPT 和 Flan T5 模型。您可以在 Hugging Face Hub 上找到 OPT 和 Flan T5 的预训练检查点。然而,如前所述,所引入的预训练方法允许将任何视觉骨干与任何 LLM 结合使用。
使用 Hugging Face Transformers 运行 BLIP-2
使用 Hugging Face Transformers,您可以轻松下载并在您的图像上运行预训练的 BLIP-2 模型。如果您想跟随本博客文章中的示例,请确保使用具有高 RAM 的 GPU 环境。
让我们从安装 Transformers 开始。由于该模型最近才添加到 Transformers 中,我们需要从源代码安装 Transformers
pip install git+https://github.com/huggingface/transformers.git
接下来,我们需要一张输入图像。每周《纽约客》都会在其读者中举办一次漫画配文比赛,所以让我们拿其中一张漫画来测试 BLIP-2。
import requests
from PIL import Image
url = 'https://media.newyorker.com/cartoons/63dc6847be24a6a76d90eb99/master/w_1160,c_limit/230213_a26611_838.jpg'
image = Image.open(requests.get(url, stream=True).raw).convert('RGB')
display(image.resize((596, 437)))
我们有一张输入图像。现在我们需要一个预训练的 BLIP-2 模型和相应的预处理器来准备输入。您可以在 Hugging Face Hub 上找到所有可用预训练检查点的列表。在这里,我们将加载一个利用 Meta AI 的预训练 OPT 模型(具有 27 亿参数)的 BLIP-2 检查点。
from transformers import AutoProcessor, Blip2ForConditionalGeneration
import torch
processor = AutoProcessor.from_pretrained("Salesforce/blip2-opt-2.7b")
model = Blip2ForConditionalGeneration.from_pretrained("Salesforce/blip2-opt-2.7b", torch_dtype=torch.float16)
请注意,BLIP-2 是一种罕见的情况,您不能使用 Auto API(例如 AutoModelForXXX)加载模型,需要显式使用 Blip2ForConditionalGeneration
。但是,您可以使用 AutoProcessor
来获取适当的处理器类——在这种情况下是 Blip2Processor
。
让我们使用 GPU 来加快文本生成速度
device = "cuda" if torch.cuda.is_available() else "cpu"
model.to(device)
图像描述
让我们看看 BLIP-2 是否能以零样本方式描述一幅《纽约客》漫画。要描述图像,我们不必向模型提供任何文本提示,只需提供预处理的输入图像。在没有任何文本提示的情况下,模型将从 BOS(序列开始)标记开始生成文本,从而创建描述。
inputs = processor(image, return_tensors="pt").to(device, torch.float16)
generated_ids = model.generate(**inputs, max_new_tokens=20)
generated_text = processor.batch_decode(generated_ids, skip_special_tokens=True)[0].strip()
print(generated_text)
"two cartoon monsters sitting around a campfire"
对于一个未在《纽约客》风格漫画上训练过的模型来说,这是一个令人印象深刻的准确描述!
带提示的图像描述
我们可以通过提供文本提示来扩展图像描述,模型将根据图像继续生成。
prompt = "this is a cartoon of"
inputs = processor(image, text=prompt, return_tensors="pt").to(device, torch.float16)
generated_ids = model.generate(**inputs, max_new_tokens=20)
generated_text = processor.batch_decode(generated_ids, skip_special_tokens=True)[0].strip()
print(generated_text)
"two monsters sitting around a campfire"
prompt = "they look like they are"
inputs = processor(image, text=prompt, return_tensors="pt").to(device, torch.float16)
generated_ids = model.generate(**inputs, max_new_tokens=20)
generated_text = processor.batch_decode(generated_ids, skip_special_tokens=True)[0].strip()
print(generated_text)
"having a good time"
视觉问答
对于视觉问答,提示必须遵循特定格式:“Question: {} Answer:”
prompt = "Question: What is a dinosaur holding? Answer:"
inputs = processor(image, text=prompt, return_tensors="pt").to(device, torch.float16)
generated_ids = model.generate(**inputs, max_new_tokens=10)
generated_text = processor.batch_decode(generated_ids, skip_special_tokens=True)[0].strip()
print(generated_text)
"A torch"
基于聊天的提示
最后,我们可以通过将每个生成的响应连接到对话中来创建类似 ChatGPT 的界面。我们用一些文本(例如“恐龙拿着什么?”)提示模型,模型会生成一个答案(“火把”),我们可以将其连接到对话中。然后我们再次这样做,建立上下文。但是,请确保上下文不超过 512 个标记,因为这是 BLIP-2(OPT 和 T5)使用的语言模型的上下文长度。
context = [
("What is a dinosaur holding?", "a torch"),
("Where are they?", "In the woods.")
]
question = "What for?"
template = "Question: {} Answer: {}."
prompt = " ".join([template.format(context[i][0], context[i][1]) for i in range(len(context))]) + " Question: " + question + " Answer:"
print(prompt)
Question: What is a dinosaur holding? Answer: a torch. Question: Where are they? Answer: In the woods.. Question: What for? Answer:
inputs = processor(image, text=prompt, return_tensors="pt").to(device, torch.float16)
generated_ids = model.generate(**inputs, max_new_tokens=10)
generated_text = processor.batch_decode(generated_ids, skip_special_tokens=True)[0].strip()
print(generated_text)
To light a fire.
结论
BLIP-2 是一种零样本视觉-语言模型,可用于多种图像到文本任务,支持图像和图像与文本提示。这是一种有效且高效的方法,可应用于多种场景下的图像理解,尤其是在示例稀缺时。
该模型通过在预训练模型之间添加一个 Transformer,弥合了视觉和自然语言模态之间的鸿沟。这种新的预训练范式使该模型能够跟上两种独立模态的进步。
如果您想了解如何为各种视觉-语言任务微调 BLIP-2 模型,请查看Salesforce 的 LAVIS 库,它为模型训练提供了全面的支持。
要查看 BLIP-2 的实际应用,请在Hugging Face Spaces 上试用其演示。
致谢
非常感谢 Salesforce Research 团队在 BLIP-2 上的工作,Niels Rogge 将 BLIP-2 添加到 🤗 Transformers 中,以及 Omar Sanseviero 审阅了这篇博客文章。