博客算法工具链从分类到搜索:用 CLIP 实现图文双向检索

从分类到搜索:用 CLIP 实现图文双向检索

Nimue🍊2026-10-29
19
0

一句话理解:先把图片和文本都变成向量,搜索时只需要找到方向最接近的那些向量。

上一篇《CLIP 的零样本分类:一组文本如何变成图像分类器?》中,我们把几个候选类别写成文本,再让图片与它们逐一比较:

如果不再把候选文本限制为类别名称,而是换成任意描述,会发生什么?

例如,我们可以输入:

然后从一整个图片库中找出最符合这句话的图片。反过来,我们也可以输入一张图片,从许多文字描述中找出与它最匹配的几条。

这就是 Image-Text Retrieval(图文检索)。

这一篇将完成一个可以直接运行的双向检索 Demo:

  • Text-to-Image:输入文字,搜索图片;

  • Image-to-Text:输入图片,搜索候选描述;

  • 将图片和文本特征提前保存为索引;

  • 返回相似度最高的 Top-K 结果;

  • 使用 Recall@K 评估检索效果。

全文不需要训练模型,也不会更新 CLIP 的参数。


一、零样本分类和图文检索有什么关系?

零样本分类与图文检索看起来是两个任务,底层计算却几乎相同。

在零样本分类中,候选项是几个类别 Prompt:

模型计算图片与每条文本的相似度,再选择最高分。

在文本搜图中,候选项变成了图片库:

模型把查询文本与每张图片进行比较,返回得分最高的几张。

两者的区别主要在于“谁是查询,谁是候选库”:

任务

查询

候选库

输出

零样本分类

图片

类别文本

最可能的类别

文本搜图

文本

图片

最匹配的图片

以图搜文

图片

文本

最匹配的描述

所以,上一期的零样本分类其实可以看成一个规模很小、候选文本形式很特殊的图文检索任务。


二、CLIP 为什么能用于跨模态搜索?

普通搜索系统最容易处理的是同一种数据:用文本搜索文本,或者用图片搜索图片。

CLIP 的特别之处在于,它把两种不同模态映射到了同一个特征空间:

如果图片是一只在草地上奔跑的狗,而文本也在描述这个场景,它们的向量方向通常会比较接近。

如果文本描述的是一架停在机场的飞机,那么它与这张狗的图片之间的向量方向通常会更远。

经过 L2 归一化后,我们可以直接使用向量点积作为余弦相似度:

余弦相似度越大,代表语义越接近。

在检索任务中,我们通常只关心排序,因此不一定要再做 Softmax。把相似度从高到低排列,就能得到 Top-1、Top-5 或 Top-10 结果。


三、双向检索的完整流程

一个最小的 CLIP 检索系统可以分为两个阶段。

阶段 1:离线构建索引

图片库和文本库通常不会在每次搜索时发生变化,所以这些向量可以提前计算并保存。

阶段 2:在线执行查询

文本搜图:

以图搜文:

这两个方向使用的是同一套模型和同一种相似度计算,只是查询向量与候选向量互换了位置。


四、先准备一个最小数据集

我们使用一个 JSON 文件同时记录图片路径和对应描述。

项目结构如下:

captions.json 的内容如下:

这里的描述既是示例数据,也是“以图搜文”时的候选文本库。

如果一张图片有多条描述,可以在 JSON 中放入多条记录。正式评估时,要注意同一张图片可能对应多个正确文本,不能只把其中一条视为正确答案。


五、安装运行环境

安装 PyTorch、OpenCLIP、Pillow 和 tqdm:

本文使用下面这组模型配置:

第一次运行时需要下载权重,之后通常会从本地缓存加载。

原始 OpenAI CLIP 的英文能力更稳定,因此示例中的查询和描述都使用英文。如果要直接使用中文查询,应该选择支持中文或多语言的 CLIP 类模型,并在自己的数据上重新验证效果。


六、完整代码:构建索引并执行双向检索

新建 clip_retrieval.py,写入下面的代码:
这段代码使用 normalize=True 直接获取归一化后的特征。图像特征与文本特征都保存在 CPU 上,查询时使用矩阵与向量的乘法计算全部相似度。

七、构建图文索引

在项目目录中运行:

Windows PowerShell 可以写成一行:

执行完成后,index 目录中会出现三个文件:

它们分别保存:

  • 所有图片的归一化特征;

  • 所有文字描述的归一化特征;

  • 图片路径、文字描述以及模型配置。

只要图片库、文本库和模型没有改变,就不需要重复构建索引。

下面这些情况需要重新构建:

  • 添加、删除或替换了图片;

  • 修改了候选描述;

  • 更换了 CLIP 模型或预训练权重;

  • 改变了与模型配套的图片预处理。

尤其不能使用模型 A 生成候选库特征,却使用模型 B 编码查询。即使两者输出维度相同,它们也不一定处于同一个特征空间。


八、用文本搜索图片

运行:

可能得到:

这里显示的是余弦相似度,不是概率。

0.3127 不能直接解释为“31.27% 的概率是正确图片”。它只有在当前模型、查询和候选库中进行相对比较时才有意义。

候选库发生变化后,第一名的分数可能不变,但排名后的结果会发生变化;换一个模型后,分数范围也可能完全不同。


九、用图片搜索文本

输入一张查询图片:

可能得到:

需要注意:这里完成的是 从已有文本中检索,不是自动生成新描述。

CLIP 会回答:

候选文本中,哪一条与图片最匹配?

CLIP 不会直接回答:

请从零开始为这张图片写一句描述。

如果候选文本库中没有合适答案,CLIP 仍然会返回其中分数最高的几条。要生成全新的图片描述,需要使用具备文本生成能力的图像描述模型或视觉语言模型。


十、为什么构建索引比每次重新编码更合理?

假设图片库里有 10 万张图片。

最直接的做法,是每次收到一个文本查询时,都重新把 10 万张图片送入 Image Encoder。这会浪费大量时间,因为图片库根本没有变化。

更合理的方式是:

  1. 图片入库时只编码一次;

  2. 把图像向量保存到索引;

  3. 查询时只编码一条新文本;

  4. 用查询向量与已有图像向量计算相似度。

这样就把最昂贵的图像编码过程从“每次查询”移到了“数据入库”。

本例使用 PyTorch Tensor 保存特征,并通过矩阵乘法完成精确搜索。它适合学习、小型 Demo 和中等规模数据。

当候选数量增长到百万甚至更大时,通常会使用专门的向量检索系统,例如 FAISS 或其他向量数据库,以减少延迟和内存占用。


十一、矩阵乘法是如何完成批量检索的?

假设索引中有 N 张图片,每张图片被编码为 D 维向量,那么图像特征可以排成一个形状为 N × D 的矩阵。
查询文本会被编码成一个 D 维向量。

代码中对应这一行:

它一次性计算了查询与所有图片的相似度。

随后:

会找出分数最高的 K 个结果。
以图搜文完全相同,只是把 image_features 换成了 text_features。

十二、查询文本应该怎样写?

在零样本分类中,我们经常使用统一模板,例如 a photo of a dog。在文本搜图任务中,用户查询本身通常已经是一句自然语言,不一定需要再套固定模板。

下面几种写法表达的检索意图不同:

从上到下,查询越来越具体:

  • dog 更关注主体;
  • a photo of a dog 加入了图片语境;
  • a dog running on grass 同时要求主体、动作和环境;
  • a close-up photo of a wet dog 还加入了构图和状态。

查询越具体,检索结果未必一定越好。CLIP 对物体、场景和整体语义通常比较敏感,但对数量、精确空间关系、细微动作和复杂否定的理解可能不稳定。

例如,下面两个查询对人类来说差异很清晰:

模型可能更关注两句话中共同出现的 dog、cat 和 chasing,却没有稳定地区分谁追谁。因此,检索效果必须通过真实数据评估,而不能只看几个成功案例。

十三、如何评估图文检索效果?

观察几个 Top-K 结果可以帮助调试,但不能代表系统整体效果。图文检索中常见的指标是 Recall@K。

1. Recall@1

检查正确结果是否排在第 1 名。

2. Recall@5

检查正确结果是否出现在前 5 名中。

3. Recall@10

检查正确结果是否出现在前 10 名中。

通常 K 越大,Recall@K 越高,但用户需要浏览的候选也越多。

评估时应该分别报告两个方向:

指标

含义

Text-to-Image R@1

正确图片排在文本查询第一名的比例

Text-to-Image R@5

正确图片进入文本查询前五名的比例

Image-to-Text R@1

正确描述排在图片查询第一名的比例

Image-to-Text R@5

正确描述进入图片查询前五名的比例

如果一张图片有多条正确描述,或者一条描述对应多张合理图片,评估代码需要把这些结果都当作正例,否则指标会低估模型表现。


十四、怎样进一步提升检索效果?

1. 选择更适合任务的模型

不同 CLIP 权重在速度、显存占用、多语言能力和特定领域表现上都有差异。更大的模型不一定在所有业务数据上都更好,应该在自己的验证集上比较。

2. 改善文本描述质量

过短、含糊或错误的描述会直接影响文本索引。对于商品、遥感或医学等领域,可以加入准确的类别、属性和场景信息,但不要堆叠与画面无关的关键词。

3. 为图片准备多条描述

同一张图片可以从主体、动作、环境等多个角度描述。多条文本能覆盖更多查询表达,但也会扩大索引,并带来去重和结果聚合问题。

4. 对查询进行改写

当用户查询很短或很口语化时,可以先将其改写为更清晰的视觉描述。例如把“草地狗狗”改写为 a dog on green grass。但改写系统也可能改变用户原意,所以必须保留原查询进行对照评估。

5. 使用两阶段检索

大型系统常先用向量相似度快速召回一批候选,再使用更精细的模型进行重排:

双编码器适合快速检索,因为候选特征可以提前保存;交叉编码或更复杂的视觉语言模型通常计算更慢,却可能更准确地理解细节。

参考资料

算法工具链
技术深度解析征程6
评论0
0/600