Faiss Wiki
Faiss
Faiss是一个高效的相似搜索和密集向量聚类库。它包含了搜索任意大小的向量集合的算法,其中包括那些可能不适合RAM的向量。它还包含用于评估和参数调优的支持代码。Faiss是用c++编写的,带有完整的Python包装器(版本2和3)。一些最有用的算法是在GPU上实现的。它主要是由Facebook人工智能研究在外部贡献者的帮助下开发的。
What is similarity search?
给定维数为d的一组向量x_i, Faiss在RAM中构建了一个数据结构。构造结构后,当给定一个维数为d的新向量x时,它高效地执行操作:
i = argmin_i ||x - x_i||
where ||.|| is the Euclidean distance (L2).
如果是Faiss项,则数据结构是一个索引,一个具有添加x_i向量的方法的对象。注意,x_i是假定是固定的。
计算argmin是对索引的搜索操作。
这就是Faiss的意义所在。它还可以:
-
return not just the nearest neighbor, but also the 2nd nearest, 3rd, ..., k-th nearest neighbor
- 返回多个近邻对象
-
search several vectors at a time rather than one (batch processing). For many index types, this is faster than searching one vector after another
- 批处理搜索,更快
- trade precision for speed, ie. give an incorrect result 10% of the time with a method that's 10x faster or uses 10x less memory
- 牺牲精度换速度
-
perform maximum inner product search argmax_i <x, x_i> instead of minimum Euclidean search. There is also limited support for other distances (L1, Linf, etc.).
- 执行最大内积距离替代欧氏距离,对其他距离也有限支持
-
return all elements that are within a given radius of the query point (range search)
- 返回查询点给定半径内的所有元素
-
store the index on disk rather than in RAM
- 存储index在disk上,rather than in RAM
-
index binary vectors rather than floating-point vectors.
- 索引二进制向量,rather than 浮点型向量
Research foundations of Faiss
等待进一步更新。。。
Getting started
Getting some data
Faiss处理固定维数d的向量集合,通常是10秒到100秒。这些集合可以存储在矩阵中。我们假设行为主存储。向量I的第j个分量存储在矩阵的第I行第j列中。Faiss只使用32位浮点矩阵。
We need two matrices:
xb
for the database, that contains all the vectors that must be indexed, and that we are going to search in. Its size is nb-by-d
xq
for the query vectors, for which we need to find the nearest neighbors. Its size is nq-by-d. If we have a single query vector, nq=1.
在下面的例子中,我们将使用在d=64维中形成均匀分布的向量。为了好玩,我们沿着第一个维度添加小的平移,这取决于向量索引。
In Python, the matrices are always represented as numpy arrays. The data type dtype
must be float32
.
本例使用普通数组,因为这是所有c++矩阵库支持的最小公分母。Faiss可以容纳任何矩阵库,只要它提供一个指向底层数据的指针。例如std::vector<float>的内部指针是由data()方法给出的。
Building an index and adding the vectors to it
Faiss是围绕Index对象构建的。它封装了数据库向量集,并选择性地对它们进行预处理,以提高搜索效率。索引有很多种类型,我们将使用最简单的版本,只对它们执行强力L2距离搜索:IndexFlatL2。
所有的index都需要知道它们是什么时候建立的也就是它们作用的向量的维数,在我们的例子中是d。然后,大多数指标还需要一个训练阶段,以分析向量的分布。对于IndexFlatL2,我们可以跳过这个操作。
当建立和训练索引时,可以对索引执行两项操作:添加和搜索。
要向索引中添加元素,我们调用add on xb。我们还可以显示索引的两个状态变量:is_training(表示是否需要训练的布尔值)和ntotal(索引向量的数量)。
有些索引还可以存储与每个向量对应的整数id(但不包括IndexFlatL2)。如果没有提供id, add只使用序数向量作为id。第一个向量是0,第二个是1,等等。
In Python
In C++
Results
这应该只显示true(索引已经过训练)和100000(向量存储在索引中)。
Searching
可以在索引上执行的基本搜索操作是k近邻搜索。对于每个查询向量,找到它在数据库中的k个最近的邻居。
该操作的结果可以方便地存储在一个大小为nq × k的整数矩阵中,其中第i行包含查询向量i的邻居的id,按距离增加排序。除了这个矩阵之外,搜索操作还返回一个nq × k的浮点矩阵,它具有相应的平方距离。
作为一个完整性检查,我们可以首先搜索一些数据库向量,以确保最近的邻居确实是向量本身。
In Python
In C++
该摘录是经过编辑的,否则c++版本会变得非常冗长,请参阅Faiss的教程/cpp子目录中的完整代码。
Results
健全检查的输出应该如下所示
ie。每个查询的最近邻居确实是向量的索引,对应的距离为0。在一行内,距离在增加。
实际搜索的输出类似于
由于添加到向量的第一个分量的值,数据集沿着d-dim空间的第一个轴被涂抹。因此,前几个向量的邻域在数据集的开始附近,而在~10000附近的向量也在数据集的索引10000附近。
在一台2016年的机器上执行上述搜索大约需要3.3秒。
Home · facebookresearch/faiss Wiki (github.com)