Faiss向量检索引擎入门指南
入门指南
以下内容假设您已经安装了 Faiss。我们提供了 C++ 和 Python 的代码示例。您可以直接复制粘贴这些代码,或者从 Faiss 发行版的 tutorial/
子目录中运行它们。
获取数据
Faiss 处理固定维度 (d) 的向量集合,通常维度在几十到几百之间。这些集合可以存储在矩阵中。我们假设采用行主序存储,即第 (i) 个向量的第 (j) 个分量存储在矩阵的第 (i) 行、第 (j) 列。Faiss 只使用 32 位浮点矩阵。
我们需要两个矩阵:
-
xb
用于数据库,包含所有需要索引的向量,我们将在其中进行搜索。其大小为 (nb \times d)。 -
xq
用于查询向量,我们需要为这些向量查找最近邻。其大小为 (nq \times d)。如果只有一个查询向量,则 (nq=1)。
在以下示例中,我们将处理从 64 维均匀分布中抽取的向量。为了有趣起见,我们还根据向量索引在第一个维度上添加了一个小的平移量。
Python 版本
1 | import numpy as npd =64 # 维度nb =100000 # 数据库大小nq =10000 # 查询数量np.random.seed(1234) # 使结果可复现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. |
int d =64; // 维度int nb =100000; // 数据库大小int nq =10000; // 查询数量floatxb =new float[d * nb];floatxq =new float[d * nq];for(int i =0; i < nb; i++){ for(int j =0; j < d; j++) xb[d * i + j]=drand48(); xb[d * i]+= i /1000.;}for(int i =0; i < nq; i++){ for(int j =0; j < d; j++) xq[d * i + j]=drand48(); xq[d * i]+= i /1000.;}
1 |
|
import faiss # 使 Faiss 可用index = faiss.IndexFlatL2(d) # 构建索引print(index.is_trained)index.add(xb) # 将向量添加到索引print(index.ntotal)
1 | ### C++ 版本 |
faiss::IndexFlatL2 index(d); // 调用构造函数printf(“is_trained = %s\n”, index.is_trained ? “true” : “false”);index.add(nb, xb); // 将向量添加到索引printf(“ntotal = %ld\n”, index.ntotal);
1 | ### 结果 |
k = 4 # 我们希望看到 4 个最近邻D, I = index.search(xb[:5], k) # 合理性检查print(I)print(D)D, I = index.search(xq, k) # 实际搜索print(I[:5]) # 前 5 个查询的最近邻print(I[-5:]) # 最后 5 个查询的最近邻
1 | ### C++ 版本 |
int k =4;{ // 合理性检查:搜索 xb 的前 5 个向量 idx_t *I =new idx_t[k 5]; floatD =newfloat[k *5]; index.search(5, xb, k, D, I); printf(“I=\n”); for(int i =0; i <5; i++){ for(int j =0; j < k; j++)printf(“%5ld “, I[i * k + j]); printf(”\n”); } … delete[] I; delete[] D;}{ // 搜索 xq idx_t I =new idx_t[k * nq]; floatD =newfloat[k * nq]; index.search(nq, xq, k, D, I); …}
1 |
|
[[ 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 |
|
[[ 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]]
由于在向量的第一个分量上添加的值,数据集在 (d) 维空间中沿着第一个轴被拉伸。因此,前几个向量的最近邻位于数据集的开头附近,而大约在 10000 附近的向量的最近邻也位于数据集的 10000 附近。
在 2016 年的机器上执行上述搜索大约需要 3.3 秒。
