向量数据库FAISS之二:基础进阶版

基础

1.评价类型和距离

1.METRIC_L2

Faiss 使用了欧几里得 (L2) 距离的平方,避免了平方根。

这仍然与欧几里德距离一样单调,但如果需要精确距离,则需要结果的额外平方根。

2.METRIC_INNER_PRODUCT

这通常用于推荐系统中的最大内积搜索

查询向量的范数不会影响结果的排名(当然数据库向量的范数也很重要)。

这本身并不是余弦相似度,除非向量被归一化

3.其他评价指标

其他指标也被支持在 IndexFlat, IndexHNSW 和 GpuIndexFlat.

METRIC_L1, METRIC_Linf, METRIC_Lp

此外还有METRIC_Canberra, METRIC_BrayCurtis and METRIC_JensenShannon

2.Faiss 构建模块:clustering, PCA, quantization

Faiss 建立在一些具有非常高效实现的基本算法之上:k-means 聚类PCAPQ 编码/解码

1.clustering

Faiss 提供了一个高效的 k-means 实现。

对存储在给定二维张量 x 中的一组向量进行聚类,如下所示:

ncentroids = 1024
niter = 20
verbose = True
d = x.shape[1]
kmeans = faiss.Kmeans(d, ncentroids, niter=niter, verbose=verbose)
kmeans.train(x)

生成的质心位于 kmeans.centroids 中。

在这里插入图片描述

迭代过程中的目标函数值(k-means 的总平方误差)存储在 kmeans.obj 变量中,更多的统计信息存储在 kmeans.iteration_stats 变量中。

如果附加选项,gpu=True 那么将运行在 GPU 上

  • 一些参数:
  • nredo:运行聚类的次数,保留最佳质心(根据聚类目标选择)
  • verbose:使聚类过程更详细
  • spherical:执行球面 k-means – 每次迭代后质心都进行 L2 归一化
  • int_centroids:将质心坐标四舍五入为整数
  • update_index:每次迭代后重新训练索引?
  • min_points_per_centroid / max_points_per_centroid:低于此值会发出警告,高于此值会对训练集进行子采样
  • seed:随机数生成器的种子

要想计算 k-means 训练完后,向量 x 到聚类中心的映射

D, I = kmeans.index.search(x, 1)

这将返回 x 中每行向量的最近质心在 I 中。D 包含 L2 距离的平方。

对于相反的操作,例如。要查找 x 中距计算质心最近的 15 个点,必须使用新索引:

index = faiss.IndexFlatL2(d)
index.add(x)
D, I = index.search(kmeans.centroids, 15)

I 大小 (ncentroids, 15) 包含每个质心的最近邻居

在这里插入图片描述

2.计算 PCA

减少 40D 向量 到 10D

mt = np.random.rand(1000, 40).astype('float32')
mat = faiss.PCAMatrix(40, 10)
mat.train(mt)
assert mat.is_trained
tr = mat.apply(mt)
print(tr **2).sum(0)

3.量化器

量化器对象继承自 Quantizer,提供三种常用方法.

  • train: 在向量矩阵上训练量化器
  • compute_codesdecode: 编码和解码。编码器通常是有损的,并为每个输入向量返回一个 uint8 代码矩阵。
  • get_DistanceComputer: 返回一个 DistanceComputer 对象的方法

Quantizer 对象的状态是训练的结果。字段 code_size 指示由量化器生成的每个代码的字节数。

量化类型

  • ScalarQuantizer: 在线性范围内,分别量化每个向量组件
  • ProductQuantizer: 在子向量上执行向量量化
  • AdditiveQuantizer: 把一个向量编码成 代码表实体的集合,加性量化器细节在这里。加性量化能被训练以几种方式,因此有子类 ResidualQuantizer, LocalSearchQuantizer, ProductAdditiveQuantizer

Additive quantizers
加性量化器在维度 d 上近似一个向量 x 如下
x ≈ x ’ = T 1 [ i 1 ] + … + T M [ i M ] x≈x’=T_1[i_1]+…+T_M[i_M] xx=T1[i1]++TM[iM]
T m T_m Tm i m i_m im 索引化的 d 维向量表。表 m 的大小是 K m K_m Km。被存储去表示 x 的 code 是 ( i 1 , … , i M ) (i_1, … , i_M) (i1,,iM)。他的大小是 ⌈ l o g 2 ( k 1 ) ⌉ + … + ⌈ l o g 2 ( k M ) ⌉ ⌈log_2(k_1)⌉ + … +⌈log_2(k_M)⌉ log2(k1)⌉++log2(kM)⌉ 位。
与 寻常的数据适应量化器一样, T 1 , … , T M T_1,…,T_M T1,,TM 表在训练集上学习。

乘积量化可以被认为是加性量化的一种特殊情况,其中只有大小为 d / M d/M d/M 的子向量在每个表中是非零的

论文

摘要

我们引入了一种新的高维矢量压缩方案,该方案使用来自 M 个不同码本的 M 个码字的和来近似矢量。

我们表明,所提出的方案允许压缩和未压缩矢量之间的有效距离和标量积计算。 我们进一步建议矢量编码和码本学习算法,其可以最小化所提出的方案内的编码误差。

在实验中,我们证明了所提出的压缩可以代替乘积量化或与乘积量化一起使用。

简介

我们提出了一种称为加性量化(AQ)的新编码方法,它可以推广 PQ 并进一步提高 PQ 精度,同时在很大程度上保持其计算效率。

与 PQ 类似,AQ 将每个向量表示为几个组件的总和每个组件来自单独的码本

与 PQ 不同,AQ 不会将数据空间分解为正交子空间,因此不会进行任何子空间独立性假设。

因此,每个 AQ 数据集内的码字具有与输入矢量相同的长度,并且通常彼此不正交

因此,与 PQ 不同,AQ 中的码本是在联合优化过程中学习的。

在这里插入图片描述

图1.在大小 K=4 的 M=4 个码本的情况下,乘积量化(PQ)与相加量化(AQ)的比较。
两种编码方法都用 1 到 K 之间的 M 个数字对输入向量进行编码。在 PQ 的情况下,该码对应于长度为 D/M 的 M 个码字的级联。在 AQ 的情况下,该码对应于长度为 D 的 M 个码字的和。
给定合适的码本,AQ 能够实现对输入向量的更好的近似。

至关重要的是,我们表明,与 PQ 类似,AQ 允许使用未压缩向量的基于查找表的非对称距离和标量积计算。 对于 PQ 通常使用的小型码本,AQ 的标量积计算效率与 PQ 几乎相同。

与 PQ 相比,具有 AQ 的距离计算(ADC)需要少量额外时间或少量额外存储器,这在许多应用中通过提高的准确度是合理的。

编码,码本学习,距离计算和对 PQ 的改进,对于短码(例如,四个或八个字节)即极端压缩率都特别有利。 对于更长的代码,可以无缝地组合这两种技术(AQ 和 PQ )。

加性量化

我们现在引入符号并详细讨论加法量化(AQ)。 下面,我们假设我们处理 D 维向量。

AQ 基于一组 M 个码本,每个码本包含 K 个向量(码字)。 我们将第 m 个码本表示为 C m C^m Cm,将第 m 个码本中的第 k 个码字表示为 c m ( k ) c^m(k) cm(k),此设置类似于 PQ。

然而,在 PQ 中,码字具有长度 D = M,AQ 中的码字长度是 D,即它们具有与正被编码的矢量相同的维度。

AQ 模型将矢量 x ∈ R D x∈R^D xRD 编码为 M 个码字的总和(每个码本一个码字)。 更详细地,矢量用码元的 M 元组编码 [ i 1 , i 2 , … , i M ] [i_1,i_2,… , i_M] [i1,i2,,iM] ,其中每个 ID 在 1 和 K 之间。 编码过程(如下所述)寻找最小化x与相应码字之和之间距离的码:

在这里插入图片描述

如果,例如 K = 256(如在我们的大多数实验中那样),则将矢量编码为 M 个字节,每个字节编码单个码字 ID。 AQ 编码矢量的存储器占用空间将与 PQ 编码矢量(对于相同的M和K)相同,而 AQ 可以更准确地表示矢量。 AQ 中的码本占用的内存比 PQ 多 M 倍,但是对于足够大的数据集,这种内存增加通常可以忽略不计。

有趣的是,每个量化器都是前一个量化器的超集。

每个量化器都有一个相应的索引类型,该索引类型还存储一组量化向量。

Quantizer classFlat index classIVF index class
ScalarQuantizerIndexScalarQuantizerIndexIVFScalarQuantizer
ProductQuantizerIndexPQIndexIVFPQ
AdditiveQuantizerIndexAdditiveQuantizerIndexIVFAdditiveQuantizer
ResidualQuantizerIndexResidualQuantizerIndexIVFResidualQuantizer
LocalSearchQuantizerIndexLocalSearchQuantizerIndexIVFLocalSearchQuantizer

此外,除 ScalarQuantizer 之外的所有索引都存在于 FastScan 版本中,请参阅 PQ 和 AQ 代码的快速累积

4.距离计算

某些量化器返回 DistanceComputer 对象。其目的是在将一个向量与多个 code 进行比较时有效地计算向量到 code 的距离。在这种情况下,通常可以预先计算一组表来直接计算压缩域中的距离。

因此,DistanceComputer 提供:

  • set_query 方法,设置当前未压缩向量以进行比较
  • distance_to_code 方法,用于计算给定 code 的实际距离。

5.示例:PQ 编码/解码

d = 32  # data dimension
cs = 4  # code size (bytes)# train set 
nt = 10000
xt = np.random.rand(nt, d).astype('float32')# dataset to encode (could be same as train)
n = 20000
x = np.random.rand(n, d).astype('float32')pq = faiss.ProductQuantizer(d, cs, 8)
pq.train(xt)# encode 
codes = pq.compute_codes(x)# decode
x2 = pq.decode(codes)# compute reconstruction error
avg_relative_error = ((x - x2)**2).sum() / (x ** 2).sum()

标量量化器的工作原理类似

d = 32  # data dimension# train set 
nt = 10000
xt = np.random.rand(nt, d).astype('float32')# dataset to encode (could be same as train)
n = 20000
x = np.random.rand(n, d).astype('float32')# QT_8bit allocates 8 bits per dimension (QT_4bit also works)
sq = faiss.ScalarQuantizer(d, faiss.ScalarQuantizer.QT_8bit)
sq.train(xt)# encode 
codes = sq.compute_codes(x)# decode
x2 = sq.decode(codes)# compute reconstruction error
avg_relative_error = ((x - x2)**2).sum() / (x ** 2).sum()

3.选择一个索引的指南

选择索引并不明显,因此这里有一些可以帮助选择索引的基本问题。它们主要适用于 L2 距离。我们指出:

  • 它们每个的 index_factory 字符串。
  • 如果有参数,我们将它们表示为相应的 ParameterSpace 参数。

1.您会执行少量搜索吗?

“Flat”

如果您计划仅执行少量搜索(例如 1000-10000),则索引构建时间将不会被搜索时间摊销。那么直接计算是最有效的选择。
这是通过 Flat 索引完成的。如果整个数据集无法容纳在 RAM 中,您可以依次构建小索引,然后合并搜索结果。

2.你需要准确的结果么?

唯一可以保证准确结果的索引是 IndexFlatL2IndexFlatIP

它为其他指数的结果提供了基线。

不会压缩向量不会在向量之上添加开销

不支持使用 ids 添加add_with_ids),仅支持顺序添加,因此如果需要 add_with_ids,请使用“IDMap,Flat”。

扁平索引不需要训练,也没有参数。

Supported on GPU: yes

3.关心内存吗?

请记住,所有 Faiss 索引都存储在 RAM 中。下面考虑的是,如果不需要精确的结果,RAM 是限制因素,并且在内存限制内我们优化精度与速度的权衡。

  1. 如果不关心内存:HNSW M 或 IVF1024, PQ N x4fs, RFlat

    如果您有大量 RAM 或 数据集很小,HNSW 是最佳选择,它是一个非常快速且准确的索引。

    4 <= M <= 64 是每个向量的链接数,越高越准确,但使用更多 RAM。

    速度与精度的权衡是通过 efSearch 参数设置的。每个向量的内存使用量为 (d * 4 + M * 2 * 4) 字节。

    HNSW 只支持顺序添加(不支持 add_with_ids),因此这里再次说明,如果需要,请使用 IDMap 前缀。 HNSW 不需要训练,也不支持从索引中删除向量。

    第二种选择比 HNSW 更快。然而,它需要重新排序阶段,因此有两个参数需要调整:重新排序的 k_factorIVFnprobe

    Supported on GPU: no

  2. 如果有点在意,使用”…, Flat”

    “...” 表示必须事先执行数据集的聚类(请参阅下文)。

    聚类后,“Flat” 只是将向量组织到桶中,因此不会压缩它们,存储大小与原始数据集相同。速度和精度之间的权衡是通过 nprobe 参数设置的。

    Supported on GPU: yes

  3. 如果非常重要,则 OPQM_D,...,PQMx4fsr

    如果存储整个向量成本太高,则执行两个操作:

    OPQ 变换到 D 维以减少维度

    将向量 PQ 量化为 M 4 位代码。

    因此,每个向量的总存储量为 M/2 字节。

    Supported on GPU: yes

  4. 如果超级重要,OPQM_D,…,PQM

    PQM 使用输出 M 字节代码的乘积量化器来压缩向量。

    M 通常 <= 64,对于较大的代码,SQ 通常同样准确且更快。

    OPQ 是向量的线性变换,使它们更容易压缩。

    D 是一个维度,使得:

    • D 是 M 的倍数(必填)
    • D <= d,其中 d 是输入向量的维度(首选)
    • D = 4*M(优选)

    Supported on GPU: yes (note: the OPQ transform is done on CPU, but it is not performance critical)

4.数据集多大

该问题用于填写聚类选项(上文 ...)。

数据集被聚类为多个数据桶,在搜索时,只访问其中的一部分数据桶(nprobe 数据桶)。

聚类是在数据集向量的代表性样本(通常是数据集的样本)上进行的。我们将指出该样本的最佳大小。

  1. 如果在 1M 向量以下:...,IVFK,...

    其中 K 为 4**sqrt(N)16**sqrt(N),N 为数据集的大小。

    这只是用 K 均值对向量进行聚类。训练需要 30K 到 256K 的向量(越多越好)。

    Supported on GPU: yes

  2. 如果 1M - 10M:”...IVF65536_HNSW32,...”

    IVF 与 HNSW 结合使用 HNSW 进行集群分配。您将需要 30 * 65536 到 256 * 65536 个向量进行训练。

    Supported on GPU: no (on GPU, use IVF as above)

  3. 如果 10M-100M:"...,IVF262144_HNSW32,..."

    同上,将 65536 替换为 262144 (2^18)。

    请注意,训练会很慢,为了避免这种情况,有两种选择:

    仅在 GPU 上进行训练,其他所有内容都在 CPU 上运行,请参阅 train_ivf_with_gpu.ipynb。

    进行两级聚类,请参阅 demo_two_level_clustering.ipynb

  4. 如果 100M - 1B:"...,IVF1048576_HNSW32,..."

    同上,将 65536 替换为 1048576 ( 2 20 2^{20} 220)。训练会更慢!

请添加图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

家庭网络常识:猫与路由器

这张图大家应该不陌生——以前家庭网络的连接方式。 图1 家庭网络连接示意图 来说说猫/光猫&#xff1a; 先看看两者的图片。 图2 猫 图3 光猫 这个东西因为英文叫“modem”&#xff0c;类似中文的“猫”&#xff0c;所以简称“猫”。 猫和光猫的区别就是&#xff0c;一…

华三预赛学习笔记(每日编辑,复习完为止)

知识点分布 路由交换技术基础 计算机网络基本概念 计算机网络基本概念&#xff1a; 很多电脑和设备通过电线或无线信号连在一起&#xff0c;可以互相“说话”和“分享东西” 网络的主要形式和发展历程&#xff1a; 诞生阶段-最早的计算机网络是以单个计算机为中心的联机系统-终…

技术速递|Microsoft.Extensions.VectorData 预览版简介

作者&#xff1a;Luis Quintanilla - 项目经理 排版&#xff1a;Alan Wang 我们很高兴推出 Microsoft.Extensions.VectorData.Abstractions 库&#xff0c;该库现已提供预览版。 正如 Microsoft.Extensions.AI 库为使用 AI 服务提供了一个统一层一样&#xff0c;此包为 .NET 生…

第5章-总体设计 5.3 硬件架构设计

5.3 硬件架构设计 1.哪些类型的产品需要架构设计&#xff1f;2.硬件架构师到底做什么&#xff1f;&#xff08;1&#xff09;理解需求和业务模型的情况。&#xff08;2&#xff09;背板设计&#xff0c;既需要考虑业务数据交换能力&#xff0c;也需要考虑子模块的管理监控能力。…

图像/文字差异类型验证码识别 无需训练

某像差异在个别全家桶验证方便有使用&#xff0c;对于这种验证码类型如下&#xff1a; 首先还是目标检测&#xff0c;直接用 dddd 自带的detection 就足够了。 特征提取 其次经过观察&#xff0c;差异答案与其他三个无非就是颜色&#xff0c;字体&#xff0c;方向&#xff0c…

新华三H3CNE网络工程师认证—生成树协议

新华三H3CNE网络工程师认证本节讲解生成树协议&#xff0c;关于生成树协议&#xff0c;提到生成树协议&#xff0c;这个时候不得不提到另外一个概念叫二层环路。二层环路导致的原因是交换机的转发机制导致的&#xff0c;本博客将分析这个机制导致这个问题的原因。 文章目录 一…

使用ai工具探究论文的工作流(阅读一个EEG的cnn-lstm文献(2021))

文章目录 李沐老师的方法论第一遍&#xff1a;做海选第二遍&#xff1a;对相关论文进行精选第三遍&#xff1a;重点研读 AI是怎么分析一个文章的标题&#xff08;Title&#xff09;和关键词摘要&#xff08;Abstract&#xff09;分析引言&#xff08;Introduction&#xff09;梳…

Scala的Array习题

答案&#xff1a;CBBBB import scala.collection.mutable.ArrayBuffer //1 case class DreamItem(content:String,var isDone:Boolean,deadline:String,var order:Int) object p5 {def main(args: Array[String]): Unit {//2val dreamListArrayBuffer[DreamItem]()//梦想清单/…

深度学习的实践层面

深度学习的实践层面 设计机器学习应用 在训练神经网络时&#xff0c;超参数选择是一个高度迭代的过程。我们通常从一个初步的模型框架开始&#xff0c;进行编码、运行和测试&#xff0c;通过不断调整优化模型。 数据集一般划分为三部分&#xff1a;训练集、验证集和测试集。常…

TPU-MLIR 总览

TPU-MLIR 总览 &#x1f4a1;深度学习编译器可以实现一次性代码开发和重用各种计算能力处理器的目标 ## 项目简介&#xff1a; TPU-MLIR 是 AI 芯片的 TPU 编译器工程。该工程提供了一套完整的工具链, 其可以将不同框架下预训练的神经网络, 转化为可以在算能 TPU 上高效运算的…

Vue3 + Vite 项目引入 Typescript

文章目录 一、TypeScript简介二、TypeScript 开发环境搭建三、编译方式1. 自动编译单个文件2. 自动编译整个项目 四、配置文件1. compilerOptions基本选项严格模式相关选项&#xff08;启用 strict 后自动包含这些&#xff09;模块与导入相关选项 2. include 和 excludeinclude…

苹果MacOS 调用自编译opencv的Dylib显示一个图片程序的步骤

前言 为了测试自编译的opencv库是否能在苹果MacOS系统下使用&#xff0c;需要写一个简单的测试程序。这个测试程序写起来不难&#xff0c;麻烦的是一些配置。网上的办法很多&#xff0c;里面因为版本的问题有一些坑。特此写了一个建立步骤&#xff0c;供大家参考。 1、新建一个…

AI赋能:高职院校实验实训教学如何拥抱人工智能浪潮?

随着信息技术的迅猛发展&#xff0c;人工智能技术已成为推动社会各行业转型升级的核心力量。它不仅在提升生产效率、优化管理流程、提高服务质量方面发挥着关键作用&#xff0c;也深刻影响着高职教育的专业发展和课程教学内容的改革。作为培养专业技术技能人才的摇篮&#xff0…

消费者行为学领域的顶级期刊

一、期刊 1.Journal of Consumer Research 2.Journal of Consumer Psychology 3.Journal of Research in Interactive Marketing 4.Journal of the Academy of Marketing Science 5.Tourism Management 下面是我整理的一个excel&#xff0c;大家按需丝我获取。 二、期刊&z…

STM32单片机CAN总线汽车线路通断检测-分享

目录 目录 前言 一、本设计主要实现哪些很“开门”功能&#xff1f; 二、电路设计原理图 1.电路图采用Altium Designer进行设计&#xff1a; 2.实物展示图片 三、程序源代码设计 四、获取资料内容 前言 随着汽车电子技术的不断发展&#xff0c;车辆通信接口在汽车电子控…

Zmap+python脚本+burp实现自动化Fuzzing测试

声明 学习视频来自 B 站UP主泷羽sec&#xff0c;如涉及侵权马上删除文章。 笔记的只是方便各位师傅学习知识&#xff0c;以下网站只涉及学习内容&#xff0c;其他的都与本人无关&#xff0c;切莫逾越法律红线&#xff0c;否则后果自负。 ✍&#x1f3fb;作者简介&#xff1a;致…

3.tree of thought 源码 (Thought 和ToTDFSMemory 类)

本教程将介绍 tree of thought 源码 中的Thought 和ToTDFSMemory 类 定义思维有效性 使用Enum模块来定义思维的有效性。 from enum import Enumclass ThoughtValidity(Enum):"""Enum for the validity of a thought."""VALID_INTERMEDIATE 0…

从ES的JVM配置起步思考JVM常见参数优化

目录 一、真实查看参数 &#xff08;一&#xff09;-XX:PrintCommandLineFlags &#xff08;二&#xff09;-XX:PrintFlagsFinal 二、堆空间的配置 &#xff08;一&#xff09;默认配置 &#xff08;二&#xff09;配置Elasticsearch堆内存时&#xff0c;将初始大小设置为…

【C++】list使用详解

本篇介绍一下list链表的使用&#xff0c;后续也是会对list进行模拟实现的。list是链表里面的双向链表。 1.文档介绍 list - C Referencehttps://legacy.cplusplus.com/reference/list/list/ list中的接口比较多&#xff0c;此处类似&#xff0c;只需要掌握如何正确的使用&am…

分布式事务

参考 Seata 详解Mysql分布式事务XA CAP 这个定理的内容是指&#xff1a;在一个分布式系统中、Consistency(一致性)、Availability(可用性)、Partitiontolerance(分区容错性)&#xff0c;三者不可得兼。 一致性&#xff08;C&#xff09; 在分布式系统中的所有数据备份&…