Faiss向量相似性搜索

移步bdata-cap.com

Faiss 快速入门(1)

Faiss 更快的索引(2)

Faiss低内存占用(3)

Faiss 构建: clustering, PCA, quantization(4)

如何选择Faiss索引(5)

官网地址 ,你也可以访问我的Github,运行代码。

本文是基于官网整理,为了防止理解偏差或简化,有些直接用英文。另外,也加了一点自己的理解。

数据准备



Faiss可以处理固定维度d的向量集合,typically a few 10s to 100s。向量集合被保存在矩阵中。我们假设行主存储(例如,the j‘th component of vector number i is stored in row i, column j of the matrix)。Faiss只能使用32位浮点矩阵。

我们需要两个矩阵:

  • xb 为语料, that contains all the vectors that must be indexed, and that we are going to search in. 它的大小为nb-by-d
  • xq 为查询的向量集合, for which we need to find the nearest neighbors. 大小为nq-by-d. 如果我们只有一个查询向量,那么nq=1.

下面例子,我们将学习在d=64维空间中向量,是0-1均匀分布,他们的值在(0,1)范围内。为了增加娱乐性,我们在第一个向量上加个小平移。

import numpy as np

d = 64                           # dimension
nb = 100000                      # database size
nq = 10000                       # nb of queries
np.random.seed(1234)             # make reproducible
xb = np.random.random((nb, d)).astype(‘float32‘)
xb[:, 0] += np.arange(nb) / 1000.
xq = np.random.random((nq, d)).astype(‘float32‘)
xq[:, 0] += np.arange(nq) / 1000.

# import matplotlib.pyplot as plt 

# plt.hist(xb[6])
# plt.show()

创建一个索引,并向它添加向量



Faiss始终围绕着索引对象展开的. 它封装了数据向量集合, 并且可以对他们进行预处理,以提高搜索效率. 有很多类型的索引, 我们使用最简单的一个,执行暴力L2距离搜索(brute-force L2 distance search):IndexFlatL2.

所有索引构建时都必须指定向量的维度d。而大多数索引还需要一个训练阶段,以便分析向量的分布。对于IndexFlatL2来说,可以跳过训练这步(因为是暴力搜索,不用分析向量).

当构建和训练索引后,在索引上执行两个操作:add和search.

向索引添加数据,在xb上调用add方法. 有两个索引的状态变量:

  • is_trained, 布尔型,表示是否需要训练
  • ntotal, 被索引的向量集合的大小

一些索引也可以对每个向量存储整型ID(IndexFlatL2不用). 如果不提供ID,使用向量的序号作为id,例如,第一个向量为0,第二个为1……以此类推

import faiss                   # make faiss available
index = faiss.IndexFlatL2(d)   # build the index
print(index.is_trained)
index.add(xb)                  # add vectors to the index
print(index.ntotal)

结果:

True
True
100000

搜索



在索引上可以执行的最基本操作是 k-nearest-neighbor search(knn), 例如,对每个向量,在数据库中查找它的 k近邻.

结果保存在大小为 nq-by-k 的矩阵中, 其中,第i行是其向量i的近邻id, 按距离升序排序. 除了k近邻矩阵外, 还会返回一个平方距离(squared distances)的矩阵,其大小为nq-by-k的浮点矩阵。

常用距离计算方法:https://zhuanlan.zhihu.com/p/101277851

  • 先来一个简单测试,用数据库中的小部分向量进行检索,来确保其最近邻确实是向量本身

先用训练数据进行检索,理论上,会返回自己。

k = 4                          # we want to see 4 nearest neighbors
D, I = index.search(xb[:5], k) # sanity check
print(xb.shape)
print(‘I‘, I)
print(‘D‘, D)

结果:

(100000, 64)
I [[  0 393 363  78]
[  1 555 277 364]
[  2 304 101  13]
[  3 173  18 182]
[  4 288 370 531]]
D [[0.        7.1751733 7.207629  7.2511625]
[0.        6.3235645 6.684581  6.7999454]
[0.        5.7964087 6.391736  7.2815123]
[0.        7.2779055 7.5279865 7.6628466]
[0.        6.7638035 7.2951202 7.3688145]]
  • 再用查询向量搜索
D, I = index.search(xq, k)     # actual search
print(‘I[:5]‘, I[:5])          # neighbors of the 5 first queries
print(‘D[:5]‘, D[:5])
print(‘-----‘)
print(‘I[-5:]‘, I[-5:])        # neighbors of the 5 last queries
print(‘D[-5:]‘, D[-5:])

结果:

I[:5] [[ 381  207  210  477]
[ 526  911  142   72]
[ 838  527 1290  425]
[ 196  184  164  359]
[ 526  377  120  425]]
D[:5] [[6.8154984 6.8894653 7.3956795 7.4290257]
[6.6041107 6.679695  6.7209625 6.828682 ]
[6.4703865 6.8578606 7.0043793 7.036564 ]
[5.573681  6.407543  7.1395226 7.3555984]
[5.409401  6.232216  6.4173393 6.5743675]]
-----
I[-5:] [[ 9900 10500  9309  9831]
[11055 10895 10812 11321]
[11353 11103 10164  9787]
[10571 10664 10632  9638]
[ 9628  9554 10036  9582]]
D[-5:] [[6.5315704 6.97876   7.0039215 7.013794 ]
[4.335266  5.2369385 5.3194275 5.7032776]
[6.072693  6.5767517 6.6139526 6.7323   ]
[6.637512  6.6487427 6.8578796 7.0096436]
[6.2183685 6.4525146 6.548767  6.581299 ]]

结果



进行一下结果的合理性检查,如果是用训练数据搜索,得到如下结果

[[  0 393 363  78]
[  1 555 277 364]
[  2 304 101  13]
[  3 173  18 182]
[  4 288 370 531]]

[[ 0.          7.17517328  7.2076292   7.25116253]
[ 0.          6.32356453  6.6845808   6.79994535]
[ 0.          5.79640865  6.39173603  7.28151226]
[ 0.          7.27790546  7.52798653  7.66284657]
[ 0.          6.76380348  7.29512024  7.36881447]]

可以看到:

  1. 上面是knn矩阵,结果的确是它自己
  2. 下面距离矩阵,相应的距离是0,按升序排序
  • 如果用查询向量搜索,会得到如下结果
[[ 381  207  210  477]
[ 526  911  142   72]
[ 838  527 1290  425]
[ 196  184  164  359]
[ 526  377  120  425]]

[[ 9900 10500  9309  9831]
[11055 10895 10812 11321]
[11353 11103 10164  9787]
[10571 10664 10632  9638]
[ 9628  9554 10036  9582]]

Because of the value added to the first component of the vectors, the dataset is smeared along the first axis in d-dim space. So the neighbors of the first few vectors are around the beginning of the dataset, and the ones of the vectors around ~10000 are also around index 10000 in the dataset.

(END.)

原文地址:https://www.cnblogs.com/liuning8023/p/12623339.html

时间: 2024-07-31 19:28:42

Faiss向量相似性搜索的相关文章

facebook 相似性搜索库 faiss

faiss 个人理解: https://github.com/facebookresearch/faiss 上把代码clone下来,make编译 我们将CNN中经过若干个卷积/激励/池化层后得到的激活映射(向量形式)存储到硬盘上, Faiss是一个高效的相似性搜索和密集向量聚类的库.它包含了搜索任意大小的向量集合的算法,这些算法可能不适合RAM.它还包含用于评估和参数优化的支持代码.Faiss是用c++编写的,带有Python/numpy的完整包装.一些最有用的算法是在GPU上实现的.它是由Fa

【Similarity Search】多探头LSH——构建高维相似性搜索的高效索引

摘要 针对高维数据的相似性索引非常适于构建内容相关的检索系统,尤其对于音频.图像.视频等内容丰富的数据.近年来,位置敏感哈希及其变种算法以近似相似性搜索的索引技术被提出,这些方法的一个显著缺点是需要很多的哈希表来保证良好的搜索效果.该文章提出了一个新的索引策略来克服上述缺点,称作多探头LSH. 多探头LSH建立在LSH技术基础上,它可以智能地探测哈希表中可能包含查询结果的多个桶(buckets),该方法受基于熵的LSh方法(设计用于降低基本LSH方法对空间的要求)的启发.根据评估显示,多探头LS

基于lucene的案例开发:搜索索引

转载请注明出处:http://blog.csdn.net/xiaojimanman/article/details/42884921 此事例中的索引数据来自于上一篇博客创建的索引,索引中包含两篇文档,每一篇文档中有两个域 name . content . 索引搜索demo 还是老样子在介绍之前先看一个简单索引搜索 demo程序. /** *@Description: 索引检索demo */ package com.lulei.lucene.study; import java.io.File;

全文搜索基本原理(倒排索引、搜索结果排序)

总结:全文搜索可以认为是搜索引擎最重要的功能,很多系统(如Luence)也支持全文搜索.全文搜索背后涉及的最重要的原理有两个:倒排索引.搜索结果排序 1.倒排索引: 给定若干搜索词 {Ti},可以根据倒排索引快速搜得相关的文档 {Di}. 2.搜索结果排序(文档排序),主要思想是先找出搜索词扮重要作用的文档(定评价标准),接着通过比较作用的大小来排序(通过评价标准评价).分两步: 2.1.找出各搜索词在各搜得的文档内的权重Wtd,从而得到搜得的每个文档的搜索词权重向量 2.2.将各搜索词也看做一

Python开源项目Top30

No 1:Home-assistant (v0.6+) 基于Python 3的开源家庭自动化平台[Github 11357 stars,由Paulus Schoutsen提供] https://github.com/home-assistant/home-assistant No 2:Pytorch PyTorch是使用GPU和CPU优化的深度学习张量库,基于Python语言编写.[Github 11019 stars,由PyTorch团队的Adam Paszke和其他人提供] https://

配送交付时间轻量级预估实践

1. 背景 可能很多同学都不知道,从打开美团App点一份外卖开始,然后在半小时内就可以从骑手小哥手中拿到温热的饭菜,这中间涉及的环节有多么复杂.而美团配送技术团队的核心任务,就是将每天来自祖国各地的数千万份订单,迅速调度几十万骑手小哥按照最优路线,并以最快的速度送到大家手中. 在这种场景下,骑手的交付时间,即骑手到达用户附近下车后多久能送到用户手中,就是一个非常重要的环节.下图是一个订单在整个配送链路的时间构成,时间轴最右部分描述了交付环节在整个配送环节中的位置.交付时间衡量的是骑手送餐时的交付

【E2LSH源码分析】E2LSH源码综述及主要数据结构

上一小节,我们对p稳定分布LSH的基本原理进行了介绍(http://blog.csdn.net/jasonding1354/article/details/38237353),在接下来的博文中,我将以E2LSH开源代码为基础,对E2LSH的源码进行注解学习,从而为掌握LSH的基本原理以及未来对相似性搜索的扩展学习打下基础. 1.代码概况 E2LSH的核心代码可以分为3部分: LocalitySensitiveHashing.cpp--主要包含基于LSH的RNN(R-near neighbor)数

从K近邻算法、距离度量谈到KD树、SIFT+BBF算法

从K近邻算法.距离度量谈到KD树.SIFT+BBF算法 从K近邻算法.距离度量谈到KD树.SIFT+BBF算法 前言 前两日,在微博上说:“到今天为止,我至少亏欠了3篇文章待写:1.KD树:2.神经网络:3.编程艺术第28章.你看到,blog内的文章与你于别处所见的任何都不同.于是,等啊等,等一台电脑,只好等待..”.得益于田,借了我一台电脑(借他电脑的时候,我连表示感谢,他说“能找到工作全靠你的博客,这点儿小忙还说,不地道”,有的时候,稍许感受到受人信任也是一种压力,愿我不辜负大家对我的信任)

Object Tracking

l  方法综述 l   Kalman 滤波器,扩展Kalman 滤波器, l   点追踪,轮廓追踪,3D建模追踪,基于颜色分布的追踪方法. l   3D建模方法跟踪很有效,但耗费时间.颜色直方图方法因为简单,有效并且高效的特性,成为了目前比较流行的一个用于表示被跟踪目标的方法.但颜色直方图也有局限性.隐马尔科夫模型是另一个得到认可的车辆状态估计和跟踪方法.(注:隐马尔可夫模型(Hidden Markov Model,HMM)是统计模型,用来描述一个含有隐含未知参数的马尔可夫过程.目的是从可观察的