faiss 稠密向量检索框架

本文介绍了Faiss库在稠密向量相似度搜索和聚类中的应用,涉及IndexFlatL2索引、IVFFlat加速搜索、IVFPQ压缩算法及索引构造的简化表达。通过实例演示了如何创建、训练和使用这些索引来提升查询性能。
部署运行你感兴趣的模型镜像

faiss是为稠密向量提供高效相似度搜索和聚类的框架,一下是官网提供的demo

# 1. 首先构建训练数据和测试数据
import numpy as np

d = 64  # dimension
nb = 100000  # database size
nq = 10000  # nb of queries
np.random.seed(1024)  # make reproduciable
xb = np.random.random(nb, d).astype("float32")  # [10000,64]的训练数据,shape为[10000,63]的查询数据
xb[:, 0] += np.arange(nb) / 1000.
xq = np.random.random((nq, d)).astype('float32')
xq[:, 0] += np.arange(nq) / 1000.

# 2.创建索引index,faiss创建索引对向量预处理,提高查询效率,faiss提供了多种索引的方法,这里选择最简单的暴力检索L2距离的索引:indexFlatL2
# 创建索引时必须指定向量的维度d,并且大部分索引需要训练的步骤,indexFlat2跳过这一步。
import faiss

index = faiss.IndexFlatL2(d)  # build the index
print(index.is_trained)

# 3. 当索引创建好并训练(如果需要)之后,就可以执行add和search方法了。add方法一般添加训练时的样本,search就是寻找相似向量
index.add(xb)  # ad vectors to the index
print(index.ntotal)

# 传入搜索向量查找相似向量

k = 4  # we want to seee 4 nearest neighbor
D, I = index.search(xq, k)  # actual  search, 表示每个查询向量的最近4个向量,D表示与相似向量的距离(distance)维度, I表示相似用户的ID

print(I[:5])  # neighbors of the 5 first queries
print(D[-5:])  # neighbors of the 5 last queries

加速搜索

如果需要存储的向量太多,通过暴力搜索索引IndexFlat2速度很慢,加速搜索的方法的索引IndexVFFlat(倒排文件)。其实是使用K-means建立聚类中心,
然后通过查询最近的聚类中心,然后比较聚类中的所有向量得到相似的向量
创建indexVFFlat时需要指定一个其他的索引作为量化器(quantizer)来计算距离或者相似度。add方法之前需要先训练
参数简介:
faiss.METRIC_L2: faiss定义了两种衡量相似度的方法(metrics),分别为faiss.METRIC_INNER_PRODUCT。一个是欧式距离,一个向量内积
nlist:聚类中心的个数
k:查找最相似的k个向量
index.nprobe:查找聚类中心的个数,默认为1个

nlist = 100  # 聚类中心的个数
k = 4
quantizer = faiss.IndexFlatL2(d)  # the other index
index = faiss.indexIVFFlat(quantizer, d, nlist,
                           faiss.METRIC_L2)  # here we specify METRIC_L2,by default it performs inner-product search
assert not index.is_trained
index.train(xb)
assert index.is_trained

index.add(xb)  # add may be a bit slower as well
D, I = index.search(xq, k)  # actual search
print(I[-5:])  # neighbors of the 5 last queries

index.nporbe = 10  # default nprobe is 1, try a few more
D, I = index.search(xq, k)
print(I[-5:])

减少内存的方法:使用 磁盘存储inverted indexes 的方式

上面我们看到的索引indexFlatL2和indexIVFFlat都会全量存储所有的向量在内存中,为满足大的数据量的需求,faiss提供一种基于Product Quantizer(乘积量化)的压缩算法编码向量大小到指定的字节数。此时,储存的向量压缩过的,查询的距离也是近似的。

nlist = 100
m = 8
k = 4
quantizer = faiss.IndexFlatL2(d)  # this remains the same

index = faiss.IndexIVFPQ(quantizer, d, nlist, m, 8)  # 8 specifies that each sub_vector is encoded as 8 bits

index.train(xb)
index.add(xb)
D, I = index.search(xb[:5], k)  # sanity check
print(I)
print(D)
index.nprobe = 10  # make comparable with experiment above
D, I = index.search(xq, k)
print(I[-5:])

简化索引的表达

通过上面indexIVFFlat和indexIVVFPQ我们可以看到,他们的构造需要先提供另外一个index。类似的,faiss还提供pca,lsh等方法,有时候他们会组合使用,这样组合的对构造索引会比较麻烦,faiss提供了通过字符串表达的方式构造索引。如,下面表达式就能表示上面的创建indexIVFPQ的实例

index = faiss.index_factory(d, "IVF100,PQ8")

参考:
Faiss使用教程详解
faiss技术积累

您可能感兴趣的与本文相关的镜像

Seed-Coder-8B-Base

Seed-Coder-8B-Base

文本生成
Seed-Coder

Seed-Coder是一个功能强大、透明、参数高效的 8B 级开源代码模型系列,包括基础变体、指导变体和推理变体,由字节团队开源

### RAG架构中向量检索的工作原理及实现方式 #### 向量检索的核心概念 向量检索是一种基于相似度的搜索方法,它将文本或其他数据表示为高维空间中的向量,并通过计算这些向量之间的距离来衡量它们的相似程度。在RAG(Retrieval-Augmented Generation)框架中,向量检索被广泛应用于从大规模文档集合中提取与查询相关的上下文信息[^2]。 #### 向量检索的具体工作流程 1. **文本嵌入生成** 首先,利用预训练的语言模型(如SentenceTransformer),将文档和查询分别转化为固定维度的稠密向量表示。这种转化过程能够捕捉到语义级别的特征,使得具有相似含义的不同表达形式能够在向量空间中靠近彼此[^1]。 2. **构建索引结构** 接下来,使用高效的近似最近邻算法库(例如FAISS或HNSWLib),针对已有的文档向量建立索引。这一阶段的目标是优化存储效率以及加速后续的大规模相似性匹配操作[^1]。 3. **执行向量搜索** 当接收到新的查询请求时,同样借助相同的编码机制得到对应的向量表现形式;随后,在预先创建好的索引之上实施快速查找动作——即寻找那些同当前输入最为接近的一组候选对象[^2]。 4. **返回结果并融合至生成环节** 经过上述步骤筛选出来的若干条高度关联的内容片段会被传递给下游的任务模块(比如大型语言模型LLM)。最终由后者综合考虑原始提示词加上额外补充的知识点共同完成高质量的回答创作任务[^3]。 以下是具体代码示例展示如何运用 `sentence-transformers` 和 `faiss` 实现基本功能: ```python from sentence_transformers import SentenceTransformer import faiss import numpy as np # 初始化句子嵌入模型 model = SentenceTransformer('all-MiniLM-L6-v2') # 假设我们有一系列文档作为语料库 corpus = ["这是一篇关于机器学习的文章。", "深度神经网络正在改变世界!", "自然语言处理领域发展迅速。"] # 将每篇文档转成向量 embeddings_corpus = model.encode(corpus, convert_to_tensor=True).cpu().numpy() # 创建 FAISS 索引 dimensionality = embeddings_corpus.shape[1] index = faiss.IndexFlatL2(dimensionality) index.add(np.ascontiguousarray(embeddings_corpus.astype('float32'))) # 查询部分 query_text = "什么是人工智能?" embedding_query = model.encode(query_text, convert_to_tensor=True).cpu().numpy() embedding_query = embedding_query.reshape(1, -1) # 调整形状以便于比较 k = 2 # 获取前两个最相近的结果 distances, indices = index.search(embedding_query, k=k) for idx in range(len(indices)): print(f"Query '{query_text}' is most similar to document {indices[idx]} with distance {distances[idx]}") ``` 以上脚本清晰地演示了一个完整的端到端流程:从加载外部资源开始经过内部加工处理直至最后输出预期答案为止。 #### 注意事项 尽管如此强大的工具可以帮助提升许多应用场景下的性能指标,但也存在一些潜在挑战需要注意规避。例如当面对海量级的数据集时可能会面临内存占用过高或者响应时间延长等问题;另外由于缺乏足够的监督信号指导整个系统运作方向的缘故,有时仍可能出现误判现象从而影响整体用户体验满意度水平下降等情况发生。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值