从零构建HNSW并对比FAISS基准测试:在5,183篇文档下暴力检索仍然胜出。[P]

Reddit r/MachineLearning 新闻

摘要

作者从零构建了一个检索引擎,将HNSW与FAISS进行对比基准测试。研究发现,对于小型文档集,暴力搜索速度更快;编码器延迟主导了检索时间;而通过RRF融合BM25与稠密检索能显著提升检索质量。

我构建了一个核心不依赖检索库的检索引擎——使用手工实现的倒排索引进行BM25检索,基于Malkov & Yashunin论文实现HNSW算法,并通过RRF进行融合——主要目的是理解HNSW的原理,而非将其视为向量数据库中的黑盒组件。FAISS、bm25s和rank_bm25仅用于基准测试的对比端。测试结果出乎意料。每个查询的中位延迟:系统 NFCorpus(3,633篇文档) SciFact(5,183篇文档) faiss-flat(精确检索) 0.153 ms 0.237 ms faiss-hnsw M=16, ef=256 0.135 ms 0.323 ms mini-brute(精确检索,我实现的) 0.295 ms 0.410 ms mini-hnsw M=16, ef=256 3.227 ms 7.517 ms 我的HNSW实现比我的暴力检索慢了10.9倍和18.3倍。其中部分延迟源于纯Python的图遍历——这确实很慢。至于与Python无关的部分:在SciFact数据集上,FAISS的暴力索引比其HNSW索引快1.36倍;在NFCorpus上,HNSW运行间延迟波动(0.023 ms)甚至超过了两系统平均延迟的差值(0.019 ms),第95百分位延迟分别为0.207 ms和0.209 ms。构建图索引的成本是暴力索引的500倍——0.93秒对比0.0017秒。所有四个系统的检索质量相同:在NFCorpus上的nDCG@10介于0.3159和0.3162之间,在SciFact上均为0.6451。暴力检索为何在此场景胜出。对3,633篇384维文档进行精确检索是一次稠密矩阵乘法——140万次乘加运算,BLAS库可轻松处理。HNSW则将其替换为指针追踪、逐节点距离计算和优先队列,这些操作均未向量化,在Python中存在解释器开销,在C++中存在缓存未命中。当线性扫描足够长,以至于跳过大部分扫描比遍历图更高效时,图索引才会胜出。在数千篇文档的规模下,这一点尚未成立。验证环节——未经验证的代码性能发现毫无价值。使用MiniLM-L6-v2的稠密检索复现了已发布的BEIR基线(在NFCorpus上为0.3159对比已发布的约0.314,在SciFact上为0.6451对比约0.645)。对FAISS进行323个查询的配对bootstrap检验,经BH校正后涉及36组对比:mini-brute与faiss-flat对比,d = +0.0000,p = 1.00;mini-hnsw与faiss-flat对比,d = +0.0002,p = 0.68。两者无法区分——这是重新实现时的合理结果,因为没有人会期望从零构建的版本能胜过原始实现。我的BM25在NFCorpus上比已发布结果低0.019。我认为这源于分词处理(未进行词干提取,未使用停用词表),依据是我测试的三种BM25实现结果差异在0.0036以内,但均低于已发布数据。这定位了差距范围但未量化其大小;我尚未构建词干提取变体。针对精确检索的ANN召回率,在NFCorpus上调整efSearch参数:我的实现在ef=16/32/64/128/256时分别为0.9034/0.9548/0.9811/0.9954/0.9975,FAISS分别为0.8755/0.9430/0.9740/0.9904/0.9985。两者均能平稳收敛。真正超越所有这些指标的关键数据。在NFCorpus上,查询嵌入耗时25.8毫秒,而为该查询提供的精确检索仅需0.295毫秒。编码器延迟是检索步骤的87倍。此处所有关于索引结构的讨论,其时间尺度都比紧邻其前的处理步骤低了两个数量级。整个项目中唯一显著的质的飞跃是RRF融合BM25与稠密检索:在NFCorpus上达到0.3423,而单一最佳方法为0.3162;在SciFact上达到0.6969,而单一最佳方法为0.6644(与faiss-flat对比,d = +0.0264,p = 0.0045 和 d = +0.0518,p = 0.0009)。两个表现平平的排序器有效协同,效果优于任何单一方法,且融合仅耗时7.36微秒。所有成本高昂的组件最终都与参考实现无异;胜出的反而是廉价方案。明确陈述局限性。仅两个数据集、一台设备、一个嵌入模型——关于文档集规模的论断仅基于两个数据点及论证框架。未进行延迟的显著性检验:质量比较使用bootstrap方法,时间统计报告中位数与波动范围。昂贵的HNSW构建仅单次采样(同一配置三次运行分别为270.0秒、95.4秒和216.0秒,差异原因不明),因此构建成本比在约2倍精度内可信。所有测试均为单线程,这本应扩大暴力检索的优势,因为BLAS能利用多核而图遍历不能——我尚未测量,因此不做主张。我不知道性能交叉点在哪里。在更大语料库上,差距进一步向暴力检索倾斜——这显然不是渐近行为,因为ANN索引确实有效,且两个语料库在规模之外还有其他差异。因此该趋势仅是这两个数据集的观察结果。我将坚持的结论很明确:在5,183篇文档时翻转尚未发生,而许多生产环境的向量存储规模小于该数值。代码与复现步骤:https://github.com/sankalp021/mini-search 完整分析文章:https://snklp.dev/blog/hnsw-vs-brute-force 希望获得两点反馈:是否有人曾在固定数据上跨规模进行过严格的交叉点测量;我的第0层链接预算偏离了针对聚类分布调优的算法1——我仅在合成均匀向量上测试过两种预算的A/B对比,因此无法将该偏离与我在BEIR上观察到的低ef召回率关联起来。
查看原文

相似文章

FAISS内部:十亿级相似性搜索

Hacker News Top

教育性文章,解释FAISS(一个用于十亿级相似性搜索的库),涵盖向量嵌入、最近邻搜索以及IVF和Product Quantization等高效检索技术。

@vintcessun: RAG喂太多文档,检索质量反而从75%掉到40%?向量搜索被大量无关内容稀释,真实部署中命中率暴跌。 问题根源:异构文档混在一起检索,噪声淹没了信号。多智能体编排看似智能,实际引入精度-忠实度悖论——配置稍差就两头不讨好。 论文提出的MA…

X AI KOLs Timeline

This paper identifies 'vector search dilution' in RAG systems when scaling to large heterogeneous document collections, where accuracy dropped from 75% to 40% in a real-world deployment. The proposed MASDR-RAG method uses domain scoping via organizational metadata before retrieval, improving P@10 from 0.77 to 0.86 with low cost and easy deployment.