本指南介绍了Salesforce Research的BLIP-2,它可以在🤗 Transformers中使用一套最先进的视觉语言模型。我们将向您展示如何在图像字幕、提示图像字幕、视觉问答和基于聊天的提示中使用它。
目录
- 介绍
- BLIP-2的内部结构是什么?
- 如何在Hugging Face Transformers中使用BLIP-2
- 图像字幕
- 提示图像字幕
- 视觉问答
- 基于聊天的提示
- 结论
- 致谢
介绍
近年来,计算机视觉和自然语言处理取得了快速发展。然而,许多现实世界的问题本质上是多模态的-它们涉及到多个不同形式的数据,如图像和文本。视觉语言模型面临的挑战是如何结合这些模态,以打开各种应用的大门。视觉语言模型可以处理的一些图像到文本的任务包括图像字幕、图像文本检索和视觉问答。图像字幕可以帮助视觉障碍者、创建有用的产品描述、识别超越文本的不适当内容等。图像文本检索可以应用于多模态搜索,以及自动驾驶等应用中。视觉问答可以在教育中发挥作用,实现多模态的聊天机器人,并在各种领域特定的信息检索应用中提供帮助。
现代计算机视觉和自然语言模型变得更加强大,但与之前的模型相比也显著增大了体积。虽然预训练单模态模型需要消耗大量资源且昂贵,但端到端视觉和语言预训练的成本变得越来越高。BLIP-2通过引入一种新的视觉语言预训练范式来解决这一挑战,该范式可以潜在地利用任何预训练的视觉编码器和LLM的组合,而无需对整个架构进行端到端的预训练。这在显著减少可训练参数和预训练成本的同时,实现了多个视觉语言任务的最先进结果。此外,这种方法为多模态ChatGPT模型铺平了道路。
BLIP-2的内部结构是什么?
BLIP-2通过在现有的冻结预训练图像编码器和冻结大型语言模型之间添加了一个轻量级的查询变换器(Q-Former),来弥合视觉和语言模型之间的模态差距。Q-Former是BLIP-2中唯一可训练的部分,图像编码器和语言模型都保持冻结状态。
Q-Former是一个由两个子模块组成的变换器模型,它们共享相同的自注意力层:
- 一个图像变换器,与冻结的图像编码器进行交互以进行视觉特征提取
- 一个文本变换器,可以作为文本编码器和文本解码器
图像变换器从图像编码器中提取固定数量的输出特征,与输入图像分辨率无关,并接收可学习的查询嵌入作为输入。查询还可以通过相同的自注意力层与文本进行交互。
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模型的BLIP-2检查点,该模型具有27亿个参数。
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是否能以零-shot方式为纽约客的漫画添加字幕。为了给图像添加字幕,我们不需要向模型提供任何文本提示,只需提供预处理后的输入图像。没有任何文本提示,模型将从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)
"两个卡通怪物围坐在篝火旁边"
对于一个没有在纽约客风格的漫画上进行训练的模型来说,这是一个令人印象深刻的准确描述!
提供提示的图像字幕
我们可以通过提供文本提示来扩展图像字幕,模型将在给出图像的情况下继续生成文本。
prompt = "这是一幅卡通图片"
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)
"两个怪物围坐在篝火旁边"
prompt = "它们看起来像是"
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)
"度过美好的时光"
视觉问答
对于视觉问答,提示必须遵循特定的格式:“问题:{} 答案:”
prompt = "问题:恐龙拿着什么?答案:"
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)
"火把"
基于聊天的提示
最后,我们可以通过将每个生成的回答串联到对话中来创建类似于ChatGPT的界面。我们用一些文本(例如“恐龙拿着什么?”)提示模型,模型为其生成一个答案(“火把”),然后我们可以将其连接到对话中。然后我们重复这个过程,逐步建立上下文。然而,确保上下文不超过512个标记,因为这是BLIP-2(OPT和T5使用的语言模型的上下文长度)。
context = [
("恐龙拿着什么?", "火把"),
("它们在哪里?", "在树林里。")
]
question = "为什么?"
template = "问题:{} 答案:{}."
prompt = " ".join([template.format(context[i][0], context[i][1]) for i in range(len(context))]) + " 问题:" + question + " 答案:"
print(prompt)
问题:恐龙拿着什么?答案:火把。问题:它们在哪里?答案:在树林里。问题:为什么?答案:
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)
为了生火。
结论
BLIP-2是一个零-shot视觉语言模型,可以用于多个图像到文本任务,包括图像和图像文本提示。它是一种有效且高效的方法,可应用于各种场景中的图像理解,尤其是当样本稀缺时。
该模型通过在预训练模型之间添加一个transformer来弥合视觉和自然语言的差距。这种新的预训练范式使得该模型能够跟上各个模态的进展。
如果您想了解如何针对各种视觉语言任务对BLIP-2模型进行微调,请查看Salesforce的LAVIS库,该库提供了全面的模型训练支持。
要查看BLIP-2的实际效果,请在Hugging Face Spaces上尝试其演示。
致谢
非常感谢Salesforce研究团队为BLIP-2的工作,感谢Niels Rogge将BLIP-2添加到🤗 Transformers中,以及感谢Omar Sanseviero对本博客文章的审核。