图像嵌入:增强图像搜索的深入解释
**图像嵌入**
图像嵌入允许高级计算机系统识别不同的视觉数据。计算机只能使用算术运算处理数值数据;因此,像文本和图像这样的数据被嵌入到由数值组成的向量中。这些向量存储在向量数据库中,以实现快速、简便和及时的访问和检索。
存在多种嵌入技术,从手动注释到视觉数据的密集向量表示。早期技术需要手动为图像分配独特的数值标识符以便计算机处理,但是随着深度学习模型的出现,嵌入技术已经发生了转变。它们已经变得如此先进,以至于我们现在可以通过给计算机文本提示来生成图像。
本文将介绍这些技术,并强调何时选择它们。之后,我们将实现一个图像搜索检索系统。
**理解图像嵌入**
图像嵌入是包含有关图像的所有信息的密集向量表示。这些信息可能包括特征、纹理、颜色、构图或其他图像语义。计算机可以处理嵌入并执行图像分类、检索和分割等任务。
**图 1:作为数值或嵌入图像的图像表示**
图像嵌入是在一个特定的向量空间中表示图像的向量。它们可以表示为稀疏或密集向量。前者只存储非零元素,使其内存高效,但可能丢失信息。相反,后者提供有关图像最细微细节的信息,并为复杂任务提供更好的帮助。
早期的图像模型依赖于手动编码,这很繁琐。然而,现代编码器使用复杂的深度学习算法来捕获复杂的数据模式。神经网络可以理解细微的细节并创建微妙的连接,以提高效率和准确性。
**传统嵌入方法**
传统的图像处理技术有限,最适合小型和特定的数据集。早期技术使用颜色直方图和视觉词袋概念。
颜色直方图映射出代表特定颜色的每个图像像素的频率。然后用于识别或检索图像,因为相似的图像将具有相似的颜色直方图组成。尽管这种技术令人印象深刻,但我们不能排除两幅图像具有相似颜色组成的可能性,导致歧义。此外,我们无法使用这种技术根据空间特征进行分类。
**图 2:展示颜色直方图如何映射图像中不同颜色通道的值以及每种颜色的像素数量。**
视觉词袋的概念是一个字典,包含图像中最突出的特征,然后将它们聚类到定义某个类别的不同类别中。这个字典充当视觉词袋,将图像与这些词进行比较。然后根据图像中视觉词袋中最频繁的特征对图像进行嵌入。这种技术的缺陷是,我们可能在视觉词袋中具有来自视觉词袋的不相关特征的高频率计数,导致错误信息和误解。
**图 3:上面的图像展示了视觉词袋的工作原理。它展示了如何使用距离矩阵比较区域。**
尽管这些技术并不是很成功,但它们仍然是图像嵌入演变中的领先步骤。
**深度学习的突破**
像 CNN(卷积神经网络)这样的深度学习模型可以在像 ImageNet 这样的大型数据集上进行训练。这种方法产生了高效的模型,能够以最高准确度生成有效的嵌入。ImageNet 是一个由数百万张注释图像组成的数据集,用于模型训练。这些图像被归类为多个类别和子类别,并使用 WordNet 数据集进行注释。
**图 4:2014年引入的 CNN 模型 VGG-16 的架构。**
CNN由两个块组成:卷积块和分类块。卷积块负责将复杂的图像缩小为低维密集向量,该向量存储了图像的所有信息。这些信息包括空间特征、颜色组成、纹理细节等。卷积块之后的输出是一个包含图像本质的密集向量。然后,这个嵌入表示继续到分类块,在那里图像被赋予与所需类别相对应的标签。分类过程涉及将分类块的结果与实际类别标签进行比较。
**图像处理中 Transformer 的兴起**
ViT(视觉 Transformer)是使用自注意力和位置嵌入技术的机器学习(ML)模型,用于分类和处理输入数据。通过将图像划分为小块并通过内部层传递,ViT 从这些小块计算向量,将它们与其他向量进行比较以生成对齐分数。此外,在层中还包括两个额外的嵌入:一个用于分类的类别嵌入和一个用于维护小块序列完整性的位置嵌入。
ViT的基于小块的设计允许并行输入,促进了模型训练和在大型数据集上的预训练。这些预训练模型随后可以微调以适应特定用例。
**图 5:ViT 模型概述**
ViT 与 CNN
CNN通过分析每个像素来处理图像,而 ViT 通过将图像分割成较小的小块来处理图像。CNN 生成的向量是密集的,并包含有关图像的每个方面的信息,而在 ViT 中,不同小块的向量用于计算对齐分数。ViT 提供了快速计算的优势,因为它顺序处理整个图像,而 CNN 必须逐个处理每个像素。
**CLIP 的多模态方法**
CLIP(对比语言-图像预训练)是一种高级机器学习模型,它使用文本数据和视觉输入来识别图像。CLIP 有两个不同的 Transformer,一个用于编码文本嵌入向量,另一个用于编码图像嵌入向量。这些向量位于相似的向量空间,并对应相似的视觉和文本数据。
CLIP 在传达相似含义的文本-图像对上进行训练。例如,考虑一张红色苹果的图像,描述它的文本将是“一个甜红苹果”。这对将被传递给 CLIP,在那里将通过文本和图像 Transformer 生成类似的向量。这一概念有助于改进图像搜索。
**图 6:CLIP 模型的简单说明。可以看到如何使用文本-图像对进行训练。**
CLIP 支持零样本对象分类和检测,无需事先训练即可检测和分类对象。这开辟了许多应用:
CLIP 可以仅根据文本描述在图像中定位和分类对象,即使对于它没有明确训练过的对象类别。
CLIP 的零样本能力有助于根据文本查询检索图像,使其适用于图像搜索系统。
**高级嵌入技术**
计算机视觉领域的一个有趣突破是扩散模型。这些模型从提供的输入文本或参考图像生成图像。
**图 7:向输入数据添加噪声,然后尝试通过执行去噪算法来构建原始数据。**
扩散模型通过在每一层向输入数据添加噪声进行训练。一旦达到最后一层,它们旨在通过去噪生成的输出来重建实际或类似的数据作为输入。
**将嵌入模型与向量数据库集成**
嵌入模型生成输入数据的数值向量表示。这些向量存储在被称为向量数据库的专业存储中。我们可以使用存储在像 Milvus 和 Zilliz Cloud(完全托管的 Milvus)这样的向量数据库中的嵌入来根据我们的查询检索图像。
传统数据库的精确搜索与向量数据库的向量搜索之间的区别在于,精确搜索通过完全映射给定的查询来检索结果。然而,向量搜索检索与给定查询相似的结果。这是通过使用近似最近邻(ANN)算法实现的。向量数据库使用此算法来映射和检索具有相似空间的向量。因此,我们可以为特定查询获得多个结果,所有这些结果都与生成的查询相关。
向量数据库有助于存储和索引非结构化和半结构化数据。应用于高维向量的专业算法有助于几乎立即检索与生成的查询相关的信息。
**构建强大的图像搜索系统**
在本节中,我们将使用 Milvus 和 Timm 从头开始构建一个图像搜索系统(图像到图像)。Milvus 是 AI 的顶级开源向量数据库,支持数百万条目的最近邻搜索。同时,Timm 是一个深度学习库,包含一系列模型,将帮助生成图像嵌入。
**设置**
以下是创建图像搜索系统所需的安装:
```
!pip install pymilvus --upgrade
!pip install timm
!pip install gdown
```
在此之前,请确保已安装所需的依赖项。
Torch、Numpy、sklearn、pillow。
**导入**
以下是开始编码所需的导入:
```python
import torch
import gdown
import os
import timm
from sklearn.preprocessing import normalize
from timm.data import resolve_data_config
from timm.data.transforms_factory import create_transform
from pymilvus import MilvusClient
from PIL import Image
```
**数据集**
在本文中,我们将使用 Caltech-101 数据集,该数据集包括来自 101 个类别的对象图像。每个图像都用单个对象标记。每个类别大约有 40 到 800 张图像,总共约 9000 张图像。图像大小不一,通常边长为 200-300 像素。
数据集具有如下目录结构:
```
+---Caltech-101
\---test
\---ant
\---0.jpg
\---1.jpg
\---....jpg
\---train
\---aeroplane
\---0.jpg
\---1.jpg
\---....jpg
```
在从该驱动器下载数据集之前,需要进行一些预处理。这包括数据集和一个稍后将用于图像检索的 CSV 文件。我们将以以下方式下载并解压缩:
```python
url = '<drive_url>'
output = 'Caltech-101.zip'
gdown.download(url, output, quiet=False)
```
下载完成后,我们可以按如下方式解压缩:
```bash
!unzip -q -o /Caltech-101.zip
```
我们可以用 Pandas 这样可视化它:
```python
import pandas as pd
df = pd.read_csv('Caltech-101/image_search.csv')
df.head()
```
它看起来像这样:
我们完成了数据集的准备;现在,让我们在 Milvus 中创建我们的集合。
**Milvus 集合**
像传统的数据库引擎一样,Milvus 允许您创建数据库并为特定用户分配权限以管理它们。
`MilvusClient` 是 Pymilvus 的一个更易于使用的包装器。它旨在简化流程并隐藏原始 SDK 中的许多复杂性。客户端的 `create_collection` API 用其他参数创建集合。以下是实现方式。
```python
from pymilvus import MilvusClient
client = MilvusClient(uri="example.db")
client.create_collection(
collection_name="image_embeddings",
vector_field_name="vector",
dimension=512,
auto_id=True,
enable_dynamic_field=True,
metric_type="COSINE",
)
```
上述代码指定了集合和向量字段名称。集合 ID 将自动生成。它将作为嵌入字段的 512 维主键。
**使用 Timm 进行嵌入**
我们的图文搜索系统使用深度神经网络从图像和文本中提取嵌入,然后与存储在 Milvus 中的嵌入进行比较。
我们利用 Timm(PyTorch Image Models 的简称),这是 PyTorch 生态系统中一个流行的库,用于实现这一点。它提供了一系列最先进的预训练图像分类模型和用于训练和评估的实用工具。
本节将利用 Timm 的 Resnet-34 从图像中提取嵌入。在下面的代码中,我们将定义我们的 FeatureExtractor 类,它将加载模型和必要的配置,然后在预处理后将图像传递给模型。
```python
class FeatureExtractor:
def __init__(self, modelname):
# 加载预训练模型
self.model = timm.create_model(
modelname, pretrained=True, num_classes=0, global_pool="avg"
)
self.model.eval()
self.input_size = self.model.default_cfg["input_size"]
config = resolve_data_config({}, model=modelname)
self.preprocess = create_transform(**config)
def __call__(self, imagepath):
input_image = Image.open(imagepath).convert("RGB")
input_image = self.preprocess(input_image)
input_tensor = input_image.unsqueeze(0)
with torch.no_grad():
output = self.model(input_tensor)
feature_vector = output.squeeze().numpy()
return normalize(feature_vector.reshape(1, -1), norm="l2").flatten()
```
**在 Milvus 中插入嵌入**
在这一部分,我们将使用前面定义的 FeatureExtractor 对模型进行推理,处理指定目录中的图像。
```python
extractor = FeatureExtractor("resnet34")
root = "./Caltech-101/train"
for dirpath, foldername, filenames in os.walk(root):
for filename in filenames:
if filename.endswith(".jpg"):
filepath = dirpath + "/" + filename
image_embedding = extractor(filepath)
client.insert(
"image_embeddings",
{"vector": image_embedding, "filename": filepath},
)
```
好的,我们已经完成了在 Milvus 中插入嵌入。让我们在测试数据集上检查一下。
**在 Milvus 上查询图像**
在这一部分,我们将使用搜索 API 查询 Milvus。作为搜索指标,我们将指定集合、查询图像和余弦距离。
```python
query_image = "./test/laptop/image_0001.jpg"
results = client.search(
"image_embeddings",
data=[extractor(query_image)],
output_fields=["filename"],
search_params={"metric_type": "COSINE"},
)
```
**测试和优化您的图像搜索系统:**
测试是图像搜索行业中一个艰难的过程。以下是一些可以采用的步骤来测试系统:
- 多样化数据集选择:选择一个多样化的数据集,代表系统预期处理的图像。包括不同类别、风格、分辨率和光照条件下的图像。
- 真实标注:为了评估检索系统的准确性,使用真实标签或注释对数据集进行注释。这可以包括相关的元数据,如类别、标签或描述。
- 基准测试:将系统性能与现有基准或最先进的方法进行比较,以评估其相对有效性并确定改进的领域。
- 真实场景:在模拟实际使用条件的真实场景下测试系统。考虑不同输入查询类型、复杂性和用户行为模式等因素。
- 用户反馈:将用户反馈纳入评估过程,以迭代改进系统。
一旦系统经过测试,可能也需要进行优化。以下是一些优化图像搜索系统的技巧:
- 选择有效的数据类型:为了在存储嵌入时优化存储效率,重要的是充分利用所使用的数据类型。在许多情况下,使用像 Milvus 中的 FLOAT16_VECTOR 这样的数据类型,可以存储半精度的嵌入,从而实现最佳的内存和带宽利用。
- 在更好和平均模型之间的权衡:许多人倾向于选择远远优于其他模型的模型,但这些模型很难扩展。选择能够胜任工作的嵌入模型。例如,看看 CLIP 的两个变体 ViT-B/16 和 ViT-B/32,并选择较小的尺寸以快速生成嵌入(在这种情况下是 ViT-B/16)。
- 总是使用 GPU:GPU 在并行处理方面效率高,可以显著提高系统效率。这使得训练过程的分布和嵌入操作的显著加速成为可能。
- 创建索引:数据库索引是一种数据结构,可以快速访问数据库中的记录。在这里,我们将在 IVF_FLAT 类型的嵌入列上建立索引,这是一种基于量化的索引,使用近似最近邻搜索(ANNS)提供快速搜索。以下是在 Milvus 中创建索引的方法:
```python
index_params = MilvusClient.prepare_index_params()
index_params.add_index(metric_type='COSINE', Index_type="IVF_FLAT",
params={"nlist":512})
client.create_index(collection_name="...", index_params=index_params)
```
根据您的用例,您可以使用许多其他索引。这里是 Milvus 上的完整列表。
**用例和实际应用**
图像嵌入在图像搜索系统中非常有用,以下是一些应用:
- 电子商务中的图像嵌入能够通过提供类似图像来搜索产品,类似于 Mozat 中的功能。Mozat 的图像搜索系统允许用户从他们的数字衣橱中找到类似的服装项目,建议服装搭配,并根据浏览历史记录和衣橱内容提供定制的时尚照片推荐。
- 图像嵌入和向量数据库可以在制造过程中检测图像异常。识别低相似性分数确保质量控制。
- 文本到图像的搜索为用户提供了一种宝贵的手段来获得他们想要的东西。Airbnb 使用图像嵌入和向量数据库将文本描述转换为相关的租赁物业。
**结论**
在文章中,我们讨论了图像嵌入及其各种技术。传统方法如颜色直方图和视觉词袋有缺点,这导致了像 CNN 和 Transformer 这样的高级技术的发展。这些新方法在图像搜索领域表现良好,并为大多数现代嵌入模型奠定了基础。
后来,像 DALL-E 和 Imagen 这样的扩散模型加入了竞争。这些模型使用文本描述从头生成逼真的图像。
人工智能领域正在迅速发展,对于所有类型的数据都是如此,无论是文本、图像还是视频。阅读下面的资源,并尝试不同的嵌入技术以保持领先。
**探索 BGE-M3 和 Splade:两种用于生成稀疏嵌入的机器学习模型**
**比较 SPLADE 稀疏向量与 BM25**
**探索 ColBERT:一种用于高效相似性搜索的标记级嵌入和排名模型**
**什么是二进制嵌入?**
**解锁语言能力:介绍 LangChain**
**向量数据库故事**
技术干货
LlamaIndex 联合创始人下场揭秘:如何使用私有数据提升 LLM 的能力?
如何使用私有数据增强 LLM 是困扰许多 LLM 开发者的一大难题。在网络研讨会中,Jerry 提出了两种方法:微调和上下文学习。
2023-5-18技术干货
GPTCache 悬赏令!寻找最佳捉虫猎手,豪华赏格等你来拿!
捉虫数量越多,奖品越丰厚!
2023-8-2技术干货
LangChain 查询使用指「北」
LangChain 是一种 AI 代理工具,可以为以 ChatGPT 为代表的额大语言模型(LLM)增添更多功能。此外,LangChain 还具备 token 和上下文管理功能。本文主要通过查询 GPT 和查询文档两个示例介绍如何使用 LangChain。
2023-5-30