ANN搜索—Faiss库的基本使用

Faiss是一个用于高效相似性搜索和密集向量聚类的C++库,支持Python接口和GPU实现。文章介绍了Faiss的安装、基本使用,包括构建索引、执行L2距离搜索,以及如何通过IndexIVFFlat加速近似最近邻(ANN)搜索,通过调整nprobe参数平衡搜索精度和速度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

ANN搜索—Faiss库的基本使用

Faiss 是一个用于高效相似性搜索和密集向量聚类的库。它包含搜索任意大小的向量集的算法,直到可能不适合 RAM 的向量集。它还包含用于评估和参数调整的支持代码。Faiss 是用 C++ 编写的,具有完整的 Python/numpy 包装器。一些最有用的算法是在 GPU 上实现的。

1. 安装

使用python调用Faiss的接口,官方推荐使用 conda 安装;

# CPU-only version
$ conda install -c pytorch faiss-cpu

# GPU(+CPU) version
$ conda install -c pytorch faiss-gpu

# or for a specific CUDA version
$ conda install -c pytorch faiss-gpu cudatoolkit=10.2 # for CUDA 10.2

2. 快速上手

Faiss处理固定维度的向量集合,这些向量集合一般以矩阵的形式存储,Faiss仅使用32位浮点数

下面展示一个简单的示例

2.1 生成一些数据

生成一些维度为64的服从均匀分布向量,分别作为查询向量集和数据库向量集,然后使用查询向量在数据库向量中进行查询搜索。

import numpy as np

# In Python, the matrices are always represented as numpy arrays.
# The data type dtype must be float32.
dim = 64                        # 向量维度
database_size = 300000          # 数据库大小             
query_size = 10000              # 查询数量
np.random.seed(1234)            
vec_database = np.random.random((database_size, dim)).astype('float32')
vec_queries = np.random.random((query_size, dim)).astype('float32')

2.2 构建索引

Faiss通过 Index 对象来构建索引,它封装了数据库向量,并且可以对数据库向量进行预处理以提高搜索效率。Faiss 提供很多类型的 Index ,下面以最简单的版本 IndexFlatL2 为例,它表示对查询和数据库执行L2距离的暴力搜索。

示例:

import faiss

index = faiss.IndexFlatL2(dim)     # 传入向量维度以实例化一个 Index 对象

# Index对象具有两个属性,is_trained 和 ntotal
# is_trained 表示是否训练了的的bool状态值
# ntotal 表示索引的数量
index.add(vec_database)                  # 将数据库向量添加到 index 中
print(index.ntotal)                      # database_size
print(index.is_trained)                  # True

2.3 搜索

构建好索引后,就可以对查询向量进行近似 k 近邻搜索了,即在数据库向量集中查找到与查询向量的最近的k个向量。

搜索结果返回数据向量库中k个最近邻的向量索引 和 对应的k个距离分数(递增),以 numpy.ndarray 的数据类型返回。

k = 4                          # we want to see 4 nearest neighbors

distances, result_indexs = index.search(vec_queries, k)     # actual search
print(result_indexs[:5])                   # neighbors of the 5 first queries
print(result_indexs[-5:])                  # neighbors of the 5 last queries

print(type(distances))

3. 加快搜索速度

快速上手 中使用的是基于L2距离的暴力搜索,其实质就是计算查询向量和数据库中所有向量的L2距离,然后根据距离分数从小到大排序给出结果,并不是采用ANN算法进行搜索。Faiss 提供 IndexIVFFlat 对象来实现 ANN 搜索算法,关于ANN算法可参考下面链接:

https://towardsdatascience.com/comprehensive-guide-to-approximate-nearest-neighbors-algorithms-8b94f057d6b6

https://zhuanlan.zhihu.com/p/454511736

快速上手 示例中的查询向量和数据库向量的基础上采用ANN搜索,示例如下:

nlist = 100     # 类似于聚类, 将数据库中的向量聚类为100类
k = 4           # k 近邻

# IndexIVFFlat 需要传入一个 Index对象,作为ANN搜索算法采用的量化器 
quantizer = faiss.IndexFlatL2(dim)
# 创建一个应用ANN算法的 index 对象
index = faiss.IndexIVFFlat(quantizer, dim, nlist)

# 因为是采用ANN算法进行近似搜索,所以需要根据数据集中的向量集进行预处理,即将数据库所有向量聚类为 nlist 簇向量集
# 因此 index 的 is_trained 状态为 False
print(index.is_trained)
assert not index.is_trained

# 聚类预处理
index.train(vec_database)

print(index.is_trained)     # True
assert index.is_trained

# 将数据库中向量添加到 index 对象中
index.add(vec_database)

# 进行 ANN 搜索
distances, result_indexs = index.search(vec_queries, k)
print(result_indexs[:5])
print(result_indexs[-5:])

# IndexIVFFlat 的 nprobe 属性默认为1,在nprobe个最近邻的簇向量空间中进行 k 近邻搜索;
# 修改 nprobe 属性值,查看搜索结果
index.nprobe = 10
distances, result_indexs = index.search(vec_queries, k)
print(result_indexs[:5])
print(result_indexs[-5:])

index.nprobe = 20
distances, result_indexs = index.search(vec_queries, k)
print(result_indexs[:5])
print(result_indexs[-5:])

使用基于L2距离的暴力查询结果
在这里插入图片描述

nlist = 100, nprobe = 1 的 ANN搜索结果和暴力搜索结果对比
在这里插入图片描述

nlist = 100, nprobe = 10 的 ANN搜索结果和暴力搜索结果对比
在这里插入图片描述

nlist = 100, nprobe = 20 的 ANN搜索结果和暴力搜索结果对比在这里插入图片描述

参考链接:

https://github.com/facebookresearch/faiss/wiki/

### Faiss与大模型的整合方案 Faiss 是 Facebook 开源的一个高效相似度搜索,特别适合处理大规模向量数据集中的最近邻查询[^1]。它能够加速基于嵌入空间(embedding space)的检索操作,在结合大模型的应用场景下具有显著优势。 #### 1. 数据预处理阶段 在使用 Faiss 和大模型之前,通常需要先通过大模型生成高质量的数据表示(embeddings)。这些 embeddings 可以由自然语言处理模型(如 BERT 或其他 Transformer 架构)、图像编码器或其他模态的大规模学习框架生成。具体来说: - **文本数据**:可以利用预训练的语言模型提取语义特征。 - **图片或视频数据**:可以通过卷积神经网络 (CNN) 提取视觉特征。 此过程的核心在于确保 embedding 的维度适配于后续索引构建的需求[^2]。 #### 2. 建立 Faiss 索引 一旦获得了 embeddings 向量集合,则可将其传递给 Faiss 来创建高效的近似最近邻索引结构。以下是建立索引的一些常见选项及其适用情况: - **Flat Indexes**: 对小型到中型数据非常有效,提供精确的结果但计算成本较高。 - **IVF (Inverted File)**: 将整个数据划分为若干子簇(cluster),从而减少每次比较的数量;适用于更大规模的数据集。 - **HNSW (Hierarchical Navigable Small Worlds)**: 支持快速高维稀疏数据上的 ANN 查询[^3]。 对于超大型数据集推荐采用复合策略比如 `IndexIVFPQ` 结合量化技术进一步降低存储需求并提升性能。 ```python import faiss import numpy as np d = 128 # dimension of the vectors nb = 100000 # number of vectors to index nlist = 100 # number of clusters in IVF # Generate random data for demonstration purposes only. np.random.seed(1234) xb = np.random.random((nb, d)).astype('float32') quantizer = faiss.IndexFlatL2(d) # Define quantizer used within IVF structure index = faiss.IndexIVFFlat(quantizer, d, nlist) assert not index.is_trained # Check if training is required before adding any vector index.train(xb[:5000]) # Train using a subset of your dataset index.add(xb) # Add all remaining points after successful train step print(f"Total indexed items count={index.ntotal}") ``` 上述代码片段展示了如何初始化一个简单的 IVF Flat 索引实例,并完成基本配置流程[^4]。 #### 3. 集成至实际应用环境 当 Faiss 已经准备好之后就可以无缝集成进入各种在线服务或者离线批处理作业当中去了。例如在一个问答系统里边,每当接收到新的提问时就调用相应的大模型得到其对应的 embedding 表达形式然后再交给预先搭建好的 Faiss 搜索引擎去寻找最接近的历史记录作为候选答案返回给前端展示出来。 值得注意的是为了保证实时响应速度可能还需要考虑缓存机制以及分布式部署等问题来优化整体架构设计[^5]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值