多模态嵌入:简介

人工智能研究传统上分为不同领域:自然语言处理(NLP)、计算机视觉(CV)、机器人学、人机交互(HCI)等。然而,无数实际任务需要整合这些不同研究领域,比如自动驾驶汽车(计算机视觉+机器人学)、人工智能智能体(自然语言处理+计算机视觉+人机交互)、个性化学习(自然语言处理+人机交互)等。

尽管这些领域旨在解决不同问题,处理不同数据类型,但它们都有一个基本过程,即生成现实世界现象的有用数字表示。

嵌入

嵌入是通过模型训练隐式学习得到的数据的(有用)数字表示。例如,通过学习如何预测文本,BERT学习到了文本的表示,这对许多自然语言处理任务都很有帮助。另一个例子是视觉Transformer(ViT),它在Image Net上进行图像分类训练,之后可用于其他应用。

这里的关键在于,这些学习到的嵌入空间会有一些潜在结构,使相似概念的位置相近,如下方示例所示。

上述模型的一个关键限制是,它们仅限于单一数据模态,如文本或图像,这限制了跨模态应用,如图像字幕生成、内容审核、图像搜索等。但如果我们能合并这两种表示会怎样呢?

多模态嵌入

尽管文本和图像在我们看来可能截然不同,但在神经网络中,它们是通过相同的数学对象——向量来表示的。因此,原则上,文本、图像或任何其他数据模态都可以由单个模型处理。

这就是多模态嵌入的基础,它在同一向量空间中表示多种数据模态,使相似概念位于相近位置(与它们的原始表示无关)。

例如,CLIP(Contrastive Language - Image Pretraining)将文本和图像编码到一个共享的嵌入空间。CLIP的一个关键见解是,通过对齐文本和图像表示,该模型能够对任意一组目标类别进行零样本图像分类,因为任何输入文本都可以被视为一个类别标签(我们稍后会看到一个具体示例)。

然而,这个想法并不局限于文本和图像。实际上,几乎任何数据模态都可以通过这种方式对齐,如文本-音频、音频-图像、文本-脑电图、图像-表格数据以及文本-视频等。这开启了许多应用场景,如视频字幕生成、高级光学字符识别(OCR)、音频转录、视频搜索以及脑电图转文本等。

对比学习

对齐不同嵌入空间的标准方法是对比学习(CL)。对比学习的核心思想是,以相似的方式表示同一信息的不同视图。

这包括学习这样的表示:最大化正样本对之间的相似性,最小化负样本对之间的相似性。在图像-文本模型中,正样本对可能是一张配有恰当字幕的图像,而负样本对则是一张配有不相关字幕的图像(如下图所示)。

对比学习之所以有效,有两个关键因素:

  1. 由于正样本对和负样本对可以从数据的固有结构中选取(例如,网络图像的元数据),对比学习的训练数据无需手动标注,这使得大规模训练和更强大的表示成为可能。
  2. 它通过一种特殊的损失函数,同时最大化正样本对的相似性,最小化负样本对的相似性,CLIP模型就是一个很好的例子。

示例代码:使用CLIP进行零样本分类和图像搜索

在对多模态嵌入的工作原理有了大致了解之后,让我们来看两个具体示例,看看它们能实现什么功能。这里,我将使用开源的CLIP模型执行两项任务:零样本图像分类和图像搜索。

这些示例的代码可在GitHub仓库中免费获取。

用例1:零样本图像分类

使用CLIP进行零样本图像分类的基本思路是,将一张图像与一组可能的类别标签一同输入模型。然后,通过评估哪个文本输入与输入图像最相似来进行分类。

我们首先导入Hugging Face Transformers库,以便在本地下载CLIP模型。此外,还需使用PIL库在Python中加载图像。

from transformers import CLIPProcessor, CLIPModel
from PIL import Image

接下来,我们可以导入CLIP模型及其相关的数据处理器。注意:处理器负责对输入文本进行分词和图像预处理。

model = CLIPModel.from_pretrained("openai/clip-vit-base-patch16")
processor = CLIPProcessor.from_pretrained("openai/clip-vit-base-patch16")

我们加载下方这张猫的图像,并创建一个包含两个可能类别标签的列表:“一张猫的照片”或“一张狗的照片”。

image = Image.open("images/cat_cute.png")
text_classes = ["a photo of a cat", "a photo of a dog"]

接下来,我们对图像/文本输入进行预处理,并将它们传入模型。

inputs = processor(text=text_classes, images=image, return_tensors="pt",
                   padding=True)
outputs = model(**inputs)

为了进行类别预测,我们必须提取图像的对数几率(logits),并评估哪个类别对应最大值。

logits_per_image = outputs.logits_per_image
probs = logits_per_image.softmax(dim=1)
predicted_class = text_classes[probs.argmax()]
print(predicted_class, "| Probability = ",
      round(float(probs[0][probs.argmax()]), 4))

输出结果:

a photo of a cat | Probability =  0.9979

模型以99.79%的概率准确判断出这是一张猫的照片。不过,这是个非常简单的例子。让我们看看,当我们将类别标签改为“丑猫”和“可爱的猫”时,对同一张图像会有什么结果。

cute cat | Probability =  0.9703

模型轻松识别出这张图像是一只可爱的猫。让我们尝试更具挑战性的标签:“猫模因”或“不是猫模因”。

not cat meme | Probability =  0.5464

虽然模型对这个预测的信心较低,概率为54.64%,但它正确判断出这张图像不是模因。

用例2:图像搜索

CLIP的另一个应用本质上是用例1的反向操作。不是识别哪个文本标签与输入图像匹配,而是评估一组图像中哪张图像与文本输入(即查询)最匹配,换句话说,就是对图像进行搜索。

我们首先将一组图像存储在一个列表中。这里,我有三张图像,分别是猫、狗和山羊。

image_name_list = ["images/cat_cute.png", "images/dog.png", "images/goat.png"]
image_list = []
for image_name in image_name_list:
    image_list.append(Image.open(image_name))

接下来,我们可以定义一个查询,如“一只可爱的狗”,并将其与图像一起传入CLIP。

query = "a cute dog"
inputs = processor(text=query, images=image_list, return_tensors="pt",
                   padding=True)

然后,我们通过提取文本的对数几率,并评估对应最大值的图像,来匹配与输入文本最匹配的图像。

outputs = model(**inputs)
logits_per_text = outputs.logits_per_text
probs = logits_per_text.softmax(dim=1)
best_match = image_list[probs.argmax()]
prob_match = round(float(probs[0][probs.argmax()]), 4)
print("Match probability: ", prob_match)
display(best_match)

输出结果:

Match probability:  0.9817

我们看到,模型又一次准确匹配了这个简单的例子。但让我们尝试一些更具挑战性的例子。

query = "something cute but metal 🤘"

输出结果:

Match probability:  0.7715
query = "a good boy"

输出结果:

Match probability:  0.8248
query = "the best pet in the world"

输出结果:

Match probability:  0.5664

虽然最后这个预测可能存在争议,但其他所有匹配都非常准确!这可能是因为这类图像在互联网上随处可见,因此CLIP在预训练过程中多次见过。

未来展望

多模态嵌入开启了无数涉及多种数据模态的人工智能应用场景。在这里,我们看到了两个这样的用例,即使用CLIP进行零样本图像分类和图像搜索。

像CLIP这样的模型的另一个实际应用是多模态检索增强生成(RAG),它包括自动为大语言模型检索多模态上下文信息。

本文由mdnice多平台发布


柏企科技圈
15 声望5 粉丝