相似性搜索:第 1 部分- kNN 和倒置文件索引

图片来源:维亚切斯拉夫·叶菲莫夫

一、说明

        SImilarity 搜索是一个问题,给定一个查询的目标是在所有数据库文档中找到与其最相似的文档。

        在数据科学中,相似性搜索经常出现在NLP领域,搜索引擎或推荐系统中,其中需要检索最相关的文档或项目以进行查询。通常,文档或项目以文本或图像的形式表示。但是,机器学习算法不能直接处理原始文本或图像,这就是为什么文档和项目通常被预处理并存储为数字向量的原因。

        有时,向量的每个组件都可以存储语义含义。在这种情况下,这些表示也称为嵌入。这样的嵌入可以有数百个维度,它们的数量可以达到数百万个!由于数量如此之大,任何信息检索系统都必须能够快速检测相关文档。

在机器学习中,向量也称为对象

二、索引指数

        为了提高搜索性能,在数据集嵌入之上构建了一个特殊的数据结构。这种数据结构称为索引。该领域已经有很多研究,并且已经发展了许多类型的索引。在选择要申请某项任务的索引之前,有必要了解它在引擎盖下的运作方式,因为每个索引都有不同的用途,并且各有优缺点。

        在本文中,我们将看看最幼稚的方法 — kNN。基于 kNN,我们将切换到倒排文件 — 用于更具可扩展性的搜索的索引,可以将搜索过程加速数倍。

2.1 kNN

        kNN是最简单、最幼稚的相似性搜索算法。考虑一个向量数据集和一个新的查询向量 Q。我们想找到与 Q 最相似的前 k 个数据集向量。要考虑的第一个方面是如何测量两个向量之间的相似性(距离)。事实上,有几个相似性指标可以做到这一点。其中一些如下图所示。

相似性指标

2.2 knn相似性训练和使用

2.2.1 训练

        kNN是机器学习中为数不多的不需要训练阶段的算法之一。选择合适的指标后,我们可以直接进行预测。

2.2.2 推理

        对于新对象,该算法会详尽地计算到所有其他对象的距离。之后,它找到距离最小的 k 个对象并将它们作为响应返回。

kNN 工作流程

        显然,通过检查到所有数据集向量的距离,kNN 保证 100% 准确的结果。但是,就时间性能而言,这种蛮力方法效率非常低。如果数据集由 n 个具有 m 维的向量组成,则对于 n 个向量中的每一个,都需要 O(m) 时间来计算从查询 Q 到它的距离,这会导致 O(mn) 的总时间复杂度。正如我们稍后将看到的,存在更有效的方法。

        此外,原始矢量没有压缩机制。想象一个包含数十亿个对象的数据集。将它们全部存储在RAM中可能是不可能的!

        kNN 性能。具有 100% 的准确性且没有训练阶段会导致在向量推理和无内存压缩期间进行详尽搜索。注意:这种类型的图表显示了不同算法的相对比较。根据情况和所选的超参数,性能可能会有所不同。

2.3 如何应用

        kNN 的应用范围有限,应仅在以下场景之一中使用:

  • 数据集大小或嵌入维度相对较小。这方面确保算法仍然快速执行。
  • 算法所需的精度必须为 100%。在准确性方面,没有其他最近邻算法可以超越kNN的性能。

        根据一个人的指纹检测一个人是需要100%准确性的问题的一个例子。如果该人犯罪并留下了指纹,则仅检索正确的结果至关重要。否则,如果系统不是100%可靠的,那么另一个人可能会被判犯有罪行,这是一个非常严重的错误。

        基本上,有两种主要方法可以改善 kNN(我们将在后面讨论):

  • 缩小搜索范围。
  • 降低矢量的维数。

使用这两种方法之一时,我们不会再次执行详尽搜索。这种算法被称为近似最近邻(ANN),因为它们不能保证100%准确的结果。

三、倒排文件索引

“倒排索引(也称为帖子列表帖子文件或倒排文件)是一种数据库索引,存储从内容(如单词或数字)到其在表格、文档或一组文档中的位置的映射” — 维基百科

        执行查询时,将计算查询的哈希函数,并从哈希表中获取映射值。这些映射值中的每一个都包含其自己的一组潜在候选项,然后根据条件完全检查这些候选项,使其成为查询的最近邻域。这样,所有数据库向量的搜索范围都会缩小。

        倒排文件索引工作流

        此索引有不同的实现,具体取决于哈希函数的计算方式。我们将要研究的实现是使用Voronoi图(或狄利克雷镶嵌)的实现。

3.1 训练

该算法的思想是创建每个数据集点所属的几个非相交区域。每个区域都有自己的质心,指向该区域的中心。

有时沃罗诺伊地区被称为单元分区

沃罗诺伊图的示例。白点是包含一组候选项的相应分区的中心。

Voronoi 图的主要性质是,从一个质心到其区域的任何一点的距离小于从该点到另一个质心的距离。

3.2 推理

        当给定一个新对象时,将计算到Voronoi分区的所有质心的距离。然后选择距离最小的质心,然后将该分区中包含的向量作为候选。

通过给定的查询,我们搜索最近的质心(位于绿色区域)

最终,通过计算到候选人的距离并选择离候选人最近的前 k 个,返回最终答案。

查找所选区域中最近的邻居

如您所见,这种方法比前一种方法快得多,因为我们不必查看所有数据集向量。

3.3 边缘问题

        随着搜索速度的提高,反转文件有一个缺点:它不能保证找到的对象始终是最近的。

        在下图中,我们可以看到这样的场景:实际的最近邻位于红色区域,但我们仅从绿色区域中选择候选人。这种情况称为边缘问题

边缘问题

        当查询的对象位于与另一个区域的边界附近时,通常会发生这种情况。为了减少这种情况中的错误数量,我们可以增加搜索范围,并根据最接近对象的前 m 个质心选择几个区域来搜索候选者。

在多个区域内搜索最近的邻居 (m = 3)

探索的区域越多,结果就越准确,计算它们所需的时间就越多。

3.4 应用

        尽管存在边缘问题,但反转文件在实践中显示出不错的结果。在我们想要权衡精度略有下降以实现多次速度增长的情况下,它是完美的选择。

        其中一个用例示例是基于内容的推荐系统。想象一下,它根据用户过去看过的其他电影向用户推荐一部电影。该数据库包含一百万部电影可供选择。

  • 通过使用kNN,系统确实为用户选择了最相关的电影并推荐它。但是,执行查询所需的时间很长。
  • 让我们假设使用倒排文件索引,系统会推荐第 5 部最相关的电影,这在现实生活中可能就是这种情况。搜索时间比 kNN 快 20 倍。

        从用户体验来看,很难区分这两个推荐的质量结果:第 1 和第 5 个最相关的结果都是来自一百万个可能的电影的好推荐。用户可能会对这些建议中的任何一个感到满意。从时间的角度来看,倒置文件显然是赢家。这就是为什么在这种情况下最好使用后一种方法。

        倒排文件索引性能。在这里,我们略微降低了在推理过程中实现更高速度的精度。

四、Faiss库实施

Faiss(Facebook AI Search Similarity)是一个用C++编写的Python库,用于优化的相似性搜索。该库提供了不同类型的索引,这些索引是用于有效存储数据和执行查询的数据结构。

根据 Faiss 文档中的信息,我们将了解如何创建和参数化索引。

4.1 实现kNN

        实现 kNN 方法的索引在 Faiss 中被称为平面索引,因为它们不压缩任何信息。它们是保证正确搜索结果的唯一索引。实际上,Faiss中存在两种类型的平面索引:

  • 索引平L2.相似性计算为欧几里得距离。
  • 索引平面IP。相似性计算为内积。

        这两个索引都需要在其构造函数中包含一个参数 d:数据维度。这些索引没有任何可调参数。

IndexFlatL2 和 IndexFlatIP 的 Faiss 实现

存储矢量的单个分量需要 4 个字节。因此,要存储维度为 d 的单个向量,需要 4 * d 字节。

4.2 倒排文件索引

        对于描述的倒置文件,Faiss 实现了类 IndexIVFFlat。与 kNN 的情况一样,单词“Flat”表示原始向量没有解压缩并且它们已完全存储。

        要创建此索引,我们首先需要传递一个量化器 — 一个确定如何存储和比较数据库向量的对象。

        IndexIVFFlat 有 2 个重要参数:

  • nlist:定义训练期间要创建的多个区域(Voronoi 单元)。
  • nprobe:确定搜索候选项的区域数。更改 nprobe 参数不需要重新训练。

Faiss 实现 IndexIVFFlat

与前面的情况一样,我们需要 4 * d 字节来存储单个向量。但是现在我们还必须存储有关数据集向量所属的Voronoi区域的信息。在 Faiss 实现中,此信息每个向量占用 8 个字节。因此,存储单个向量所需的内存为:

五、结论

        我们已经在相似性搜索中经历了两种基本算法。实际上,朴素的kNN几乎不应该用于机器学习应用程序,因为它的可扩展性很差,除非在特定情况下。另一方面,反转文件为加速搜索提供了良好的启发式方法,可以通过调整其超参数来提高其质量。仍然可以从不同的角度增强搜索性能。在本系列文章的下一部分中,我们将介绍一种旨在压缩数据集向量的方法。

系列下篇:相似性搜索:第 2 部分:产品量化_无水先生的博客-CSDN博客

参考资源

  • 倒排索引 |维基百科
  • 费斯文档
  • 费斯存储库
  • 费斯指数摘要
  • 选择索引的准则

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/104470.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C# OpenVINO Cls 图像分类

效果 耗时 class idbrown_bear, score0.86 preprocess time: 0.00ms infer time: 2.72ms postprocess time: 0.02ms Total time: 2.74ms项目 代码 using OpenCvSharp; using Sdcb.OpenVINO; using Sdcb.OpenVINO.Natives; using System; using System.Diagnostics; using Sys…

地产三维实景vr展示的功能及特点

随着科技的不断发展,VR(虚拟现实)技术也越来越成熟。VR技术的广泛应用,已经逐渐渗透到各个领域,其中引人注目的就是虚拟展馆。虚拟展馆是一种利用VR技术构建的线上展示空间,让观众可以在家中就能参观展览,带来了极大地…

模板进阶和反向迭代器

文章目录 模板非类型模板参数模板特化函数模板特化类模板特化 模板分离编译 反向迭代器 模板 非类型模板参数 模板参数分类类型形参与非类型形参。 类型形参即:出现在模板参数列表中,跟在class或者typename之类的参数类型名称。 非类型形参&#xff0c…

基于CodeFormer实现图片模糊变清晰,去除马赛克等效果

前言 CodeFormer是一种基于AI技术深度学习的人脸复原模型,由南洋理工大学和商汤科技联合研究中心联合开发。该模型通过结合了VQGAN和Transformer等技术,可以通过提供模糊或马赛克图像来生成清晰的原始图像。可以实现老照片修复、照片马赛克修复、黑白照…

【ARM Coresight 系列文章 9.1 -- ITM 仪器化跟踪宏单元详细介绍】

文章目录 1.1 ITM 介绍1.1.1 ITM 功能介绍1.1.2 Cortex-M ITM 的地址范围1.2 ITM 使用1.2.1 ITM 寄存器介绍1.2.2 Cortex-M7 ITM 代码示例1.2.3 Cortex-M33 ITM 代码示例1.1 ITM 介绍 在debug 调试阶段通常都是使用 printf(printk) 来进行进行 log 输出,然后定位问题。那么如…

排序算法-希尔排序法(ShellSort)

排序算法-希尔排序法(ShellSort) 1、说明 我们知道当原始记录的键值大部分已排好序的情况下插入排序法非常有效,因为它不需要执行太多的数据搬移操作。希尔排序法是D.L.Shell在1959年7月发明的一种排序法,可以减少插入排序法中数…

Java IO流

IO 即 Input / Output ,输入输出流。IO流在Java中分为输入流和输出流,而根据数据的处理方式又分为字节流和字符流。 Java IO 流的 40 多个类都是从如下 4 个 抽象类基类中派生出来的。 InputStream /Reader : 所有的输入流的基类,前者是字节…

论文阅读之《Learn to see in the dark》

Learning to See in the Dark-CVPR2018 Chen ChenUIUC(伊利诺伊大学厄巴纳-香槟分校) Qifeng Chen, Jia Xu, Vladlen Koltun Intel Labs(英特尔研究院) 文章链接:https://arxiv.org/pdf/1805.01934.pdfhttps://arxiv.org/pdf/1805.01934.p…

Android Studio展示Activty生命周期

前言 本文章以及之后文章的程序版本使用Android Studio 2022.3.1 Patch 1 版本编辑,使用语言为java,最低支持API 27 Android 8.1,构建工具版本如下: 本文章主要是介绍Activty跳转和删除,以备后续使用,所以就…

计算机的字符与编码集

文章目录 前言一、字符编码集的历史1.ASCII码2.Extended ASCII码3.字符编码集的国际化 二、中文编码集 前言 今天给大家介绍计算机的字符与编码集,分为两部分:字符编码集的历史、中文编码集。 一、字符编码集的历史 这部分包含三个板块内容&#xff1a…

【通信系列 5 -- HTTPS 介绍】

文章目录 1.1 HTTPS链接网址1.1.1 HTTPS 产生背景1.1.2 HTTPS工作内容1.1.3 SSL/TLS1.1.4 TLS 的命名规范1.1.5 TLS 加密算法1.1.6 分组模式1.1.7 摘要算法1.1.8 非对称加密1.1.9 CA认证 1.2 openssl1.2.1 RSA 签名验签 1.1 HTTPS链接网址 HTTP 是一种 超文本传输协议(Hyperte…

DOCKER本地仓库

概述 随着docker的应用越来越多,安装部署越来越方便,批量自动化的镜像生成和发布都需要docker仓库的本地化应用。 试用了docker的本地仓库功能,简单易上手,记录下来以备后用。 环境 centos:CentOS release 7.0 (F…

CANoe创建仿真工程

CANoe创建仿真工程 写在前面仿真工程的创建创建工程添加CAN数据库添加系统变量创建面板创建网络节点为节点添加代码工程运行测试总结 写在前面 Canoe的安装不是特别方便,我是参加了松勤的培训课程,不仅需要安装软件还需要安装驱动,刚刚学习的…

【PWN · 栈迁移】[CISCN 2019东南]PWN2

一道非常典型、适合用作学习栈迁移的题目。 前言 当存在栈溢出但是溢出字符数并不多的情况下,可以尝试在别处构造rop链,通过栈迁移到目标内存区域,执行rop链。这里不讲栈迁移原理,仅是对题目的分析,适合对栈迁移有初步…

WPF中的多重绑定

MultiBinding 将会给后端传回一个数组, 其顺序为绑定的顺序. 例如: <DataGridMargin"10"AutoGenerateColumns"False"ItemsSource"{Binding Stu}"><DataGrid.Columns><DataGridTextColumn Binding"{Binding Id}" Header…

bash一行输入,多行回显demo脚本

效果图&#xff1a; 脚本&#xff1a; #!/bin/bash # 定义一个变量&#xff0c;用来存储输入的内容 input"" # 定义一个变量&#xff0c;用来存储输入的字符 char""# 为了让read能读到空格键 IFS_store$IFS IFS# 提示内容&#xff0c;在while循环中也有&a…

three.js入门 —— 实现第一个3D案例

前言&#xff1a; three.js入门&#xff0c;根据文档实现第一个3D案例 效果图&#xff1a; 代码实现&#xff1a; const scene new THREE.Scene();//创建一个长方体几何对象Geometryconst geometry new THREE.BoxGeometry(100, 100, 100);//创建一个网络基础材质的材质对象…

机器人革命:脑洞大开的前沿机器人技术!

原创 | 文 BFT机器人 01 由生物启发的多模式移动形态机器人 在一个不断运动的世界中&#xff0c;一种新开发的名为M4&#xff08;多模式移动形态机器人&#xff09;的机器人展示了在包括滚动、飞行和行走在内的八种不同运动模式之间切换的能力。这款机器人由加州理工学院自主…

SOLIDWORKS® 2024 新功能 - 3D CAD

1、 先前版本的兼容性 • 利用您订阅的 SOLIDWORKS&#xff0c;可将您的 SOLIDWORKS 设计作品保存为旧版本&#xff0c;与使用旧版本 SOLIDWORKS 的供应商无缝协作。 • 可将零件、装配体和工程图保存为新版本前两年之内的SOLIDWORKS 版本。 优点&#xff1a; 即使其他用户正…

conda 创建虚拟环境

1.为什么要创建虚拟环境 我们在做开发或者跑论文实验可能会同时进行多个任务&#xff0c;这些任务可能会依赖于不同的python环境&#xff0c;比如有的用到3.6有的用到3.7&#xff0c;这时我们创建不同版本的python&#xff0c;放到虚拟环境中给不同的任务分别提供其所需要的版本…