当前位置:网站首页 > 数据科学与大数据 > 正文

faiss数据库(faiss数据库可视化)



Faiss 在项目中的使用Faiss Indexs 的进一步了解

这里跟着上面两篇文章的思路,对faiss理解更多一些。

1.再问faiss 是什么?

撇开具体定义不管,Faiss 就可以类比为一个可以设置索引数据库
faiss这个“数据库”里存的什么?对于Faiss来讲就是巨多的向量。
只是在 Faiss 中没有数据库存储介质这一层的概念,全部都是 Index,索引是干什么的? 更快的读取。




2. 构建Index

3. 查询Index

4. 构建 API 服务

5.环境

上面看完是不是还是挺懵,或者说感觉很神奇,为什么索引构建一下,训练一下,查询一下,就能出相似向量的结果了,还那么快。这就要说到faiss的核心了,各种索引。

理论基础

代码

得到的结果是:

结论

把 nprobe 上升到10的结果就是正确的结果(与蛮力搜索相同)。 请注意,在这种情况下获得完美结果仅仅是数据分布的工件,因为它在x轴上具有强大的组件,这使得它更容易处理。

nprobe 参数始终是调整结果的速度和准确度之间权衡的一种方法。 设置nprobe = nlist会产生与暴力搜索相同的结果(但速度较慢)。

理论基础

参考Faiss基于PQ的倒排索引实现

代码

实验结果1:

结论1

我们可以观察到我们正确找到了最近邻居(它是矢量ID本身),但是矢量与其自身的估计距离不是0,尽管它明显低于到其他邻居的距离。 这是由于有损压缩造成的。

这里我们将64个(d=64)32位浮点数压缩为8个字节(m=8),因此压缩因子为32。

实验结果2:

结论2

它们可以与上面的IVFFlat结果进行比较。 对于这种情况,大多数结果都是错误的,但它们位于空间的正确区域,如10000左右的ID所示。 实际数据的情况更好,因为:

  • 统一数据(这里的输入是random的)很难索引,因为没有可用于聚类或降低维度的规律性
  • 对于自然数据,语义最近邻居通常比不相关的结果更接近。

简化索引构建

由于构建索引可能变得复杂,因此有一个工厂函数在给定字符串的情况下构造它们。 上述索引可以通过以下简写获得:

当需要预处理(PCA)应用于输入向量时,工厂就特别有用。 例如,要使用PCA投影将矢量减少到32D的预处理时,工厂字符串应该时:”PCA32,IVF100,Flat”。

获取单个 GPU 资源

使用GPU资源构建GPU索引

多个索引可以使用单个GPU资源对象,只要它们不发出并发查询即可。

使用

获得的GPU索引可以与CPU索引完全相同的方式使用:

使用多个 GPU

使用多个GPU主要是声明几个GPU资源。 在python中,这可以使用index_cpu_to_all_gpus帮助程序隐式完成。

上面看完是不是感觉索引真的很好用,而且原理大概也能看懂。但faiss是出了名的索引多,也就是说可选范围多,那我们大概要如何选了,这里有一点指引,其实也可以多试试,最后结果都是准确性和速度的折中权衡。

需要注意:

  • 以下都通过 index_factory 字符串来表示不同 Index
  • 如果需要参数,使用相应的 ParameterSpace 参数

1. 是否需要精确的结果?

那就使用 “Flat”

可以保证精确结果的唯一索引是 IndexFlatL2。

它为其他索引的结果提供基线。

是否支持 GPU: yes

2. 是否关心内存?

请记住,所有Faiss索引都存储在RAM中。 以下的这些考虑是,如果我们不需要精确的结果而 RAM 又是限制因素,那么,我们就需要在内存的限制下,来优化精确-速度比(precision-speed tradeoff)。

如果不需要关心内存:“HNSWx”

如果你有大量的RAM或数据集很小,HNSW 是最好的选择,它是一个非常快速和准确的索引。 x 的范围是[4, 64],它表示了每个向量的链接数量,越大越精确,但是会使用越多的内存。

速度-精确比(speed-accuracy tradeoff)可以通过 efSearch 参数来设置。 每个向量的内存使用是情况是(d * 4 + x * 2 * 4 )。

HNSW 只支持顺序添加(不是add_with_ids),所以在这里再次使用 IDMap 作为前缀(如果需要)。 HNSW 不需要训练,也不支持从索引中删除矢量。

是否支持 GPU: no
如果有些担心内存:“…,Flat”

“…” 表示必须事先执行数据集的聚类(如下所示)。 在聚类之后,“Flat”只是将向量组织到不同桶中,因此它不会压缩它们,存储大小与原始数据集的大小相同。 速度和精度之间的权衡是通过 nprobe 参数设置的。

是否支持 GPU: yes(但是聚类方法也需要支持GPU)
如果相当关心内存:“PCARx,…,SQ8”

如果存储整个向量太昂贵,则执行两个操作:

是否支持 GPU: no
如果非常关心内存:“OPQx_y,…,PQx”

PQx 代表了通过一个product quantizer压缩向量为 x 字节。 x 一般 <= 64,对于较大的值,SQ 通常是准确和快速的。

OPQ 是向量的线性变换,使其更容易压缩。 y是一个维度:

是否支持 GPU: yes(注意:OPQ转换是在软件中完成的,但它不是性能关键)

3. 数据集有多大

这个问题用于选择聚类选项(就是上面的那些”…“)。 数据集聚集到存储桶中,在搜索时,只访问了一小部分存储桶(nprobe 个存储桶)。 聚类是在数据集矢量的代表性样本上执行的,通常是数据集的样本。 我们指出该样本的最佳大小。

如果向量数量低于1百万:”…,IVFx,…”

当数据集的数量为 N 时,那么 x 应该处于 4 * sqrt(N) 和 16 * sqrt(N) 之间。 这只是用k-means聚类向量。 你需要 30 * x 到 256 * x 的矢量进行训练(越多越好)。

是否支持 GPU: yes
如果向量数量位于1百万-1千万之间:”…,IMI2x10,…”

(这里x是文字x,而不是数字)

IMI在训练向量上执行具有2 ^ 10 个质心的 k-means,但它在向量的前半部分和后半部分独立地执行。 这将簇的数量增加到 2^(2 * 10)。您将需要大约64 * 2 ^ 10个向量进行训练。

是否支持 GPU: no
如果向量数量位于1千万-1亿之间:”…,IMI2x12,…”
如果向量数量位于1亿-10亿之间:”…,IMI2x14,…”

1 单元-探测(Cell-probe) 方法

以失去保证以找到最近邻居为代价来加速该过程的典型方法是采用诸如k均值的分区技术。 相应的算法有时被称为 cell-probe 方法:

我们使用基于多探测的基于分区的方法(可以联想到best-bin KD-tree的一种变体)。

  • 特征空间被划分为 ncells 个单元格。
  • 由于散列函数(在k均值的情况下,对最靠近查询的质心的分配),数据库向量被分配给这些单元中的一个,并且存储在由ncells反向列表形成的反向文件结构中。
  • 在查询时,会选择一组 nprobe 个的反向列表
  • 将查询与分配给这些列表的每个数据库向量进行比较

这样做,只有一小部分数据库与查询进行比较:作为第一个近似值,这个比例是 nprobe / ncells,但请注意,这个近似值通常被低估,因为反向列表的长度不相等。 当未选择给定查询的最近邻居的单元格时,将显示失败案例。

在C++中,相应的索引是索引IndexIVFFlat。

构造函数将索引作为参数,用于对反转列表进行赋值。 在该索引中搜索查询,并且返回的向量id(s)是应该被访问的反向列表。

2. 具有平坦索引作为粗量化器的单元探测方法

一般的,我们使用一个 Flat index 作为粗糙量化。 IndexIVF 的训练方法给 flat index 添加了质心。 nprobe 的值在搜索时设置(对调节速度-准确比很管用)。

注意: 根据经验,n 表示要被索引的点的数量, 一般确定合适质心数量的方法是在“分配向量到质心的开销(如果是纯粹的kmeans:ncentroids * d)” 和 “解析反转列表时执行的精确距离计算的数量(按照 kprobe / ncells * n * C 的顺序,其中常量 C 考虑了列表的不均匀分布, 以及当使用质心批处理时单个矢量比较更有效的事实,比如 C = 10)”之间找平衡。

这导致了许多质心的数量都遵循 ncentroids = C * sqrt(n)。

注意: 在引擎盖下,IndexIVFKmeans 和 IndexIVFSphericalKmeans 不是对象,而是返回正确设置的 IndexIVFFlat 对象的函数。

警告: 分区方法容易受到维数的诅咒。对于真正高维数据,实现良好的召回需要具有非常多的probe。

3. 基于量化的方法

基于产品量化的索引由关键字PQ标识。 例如,基于产品量化的最常见索引声明如下:

位数n_bits必须等于8,12或16. 维度d应为m的倍数.

4. 具有PQ细化的反转文件

IndexIVFPQ 可能是大规模搜索最有用的索引结构。

有关ncentroids的设置,请参阅有关IndexIVFFlat的章节。 code_size 通常是4到64之间的2的幂。 对于 IndexPQ,d 应该是 m 的倍数。

5. 示例:应用PCA以减少尺寸数

6. IndexRefineFlat:重新排名搜索结果

在查询向量时,使用实际距离计算对搜索结果进行重新排序可能是有用的。 以下示例使用 IndexPQ 搜索索引,然后通过计算实际距离重新排列第一个结果:

搜索功能将从 IndexPQ 中获取4 * 10个最近邻居,然后计算每个结果的实际距离,并保留10个最佳结果。 请注意,IndexRefineFlat 必须存储完整的向量,因此它不具有内存效率。

7. IndexShards:组合来自多个索引的结果

当数据集分布在多个索引上时,可以通过它们调度查询,并将结果与 IndexShards 结合使用。 如果索引分布在多个GPU上并且查询可以并行完成,这也很有用. 请参阅在 GpuClonerOptions中 将 shards 设置为 true 的 index_cpu_to_gpus 。

到此这篇faiss数据库(faiss数据库可视化)的文章就介绍到这了,更多相关内容请继续浏览下面的相关推荐文章,希望大家都能在编程的领域有一番成就!

版权声明


相关文章:

  • odl数据库(ods数据库是干什么的)2025-12-14 10:36:08
  • 自动驾驶数据集采集(自动驾驶数据库)2025-12-14 10:36:08
  • 数据中台 技术中台(数据中台 技术中台 业务中台)2025-12-14 10:36:08
  • 自动驾驶数据集回灌(自动驾驶数据存储)2025-12-14 10:36:08
  • 自动驾驶数据库(自动驾驶 数据处理)2025-12-14 10:36:08
  • 数据库端口号(数据库端口号怎么修改)2025-12-14 10:36:08
  • mongodb数据库的优势(简述mongoDB数据库的优势)2025-12-14 10:36:08
  • udp报文格式解析(udp数据报文格式)2025-12-14 10:36:08
  • cmip6(cmip6数据处理)2025-12-14 10:36:08
  • springboot数据库密码加密(springboot 数据库密码加密)2025-12-14 10:36:08
  • 全屏图片