ANN,IVF,HNSW
ANN,IVF,HNSW
哈喽大家好!
上回我们聊到了向量数据库是 LLM 的"外挂硬盘",而相似性搜索是这个硬盘的"检索魔法"。
今天这篇是硬核实战篇!我们不整那些虚头巴脑的概念,直接把工业界最主流、最核心的三个算法:K-Means 聚类、IVF 倒排索引、以及大名鼎鼎的 HNSW,彻底拆解清楚!
别被这些英文缩写吓跑,其实它们的原理,和你平时在超市找商品、或者在城市里找路的逻辑是一模一样的。
📌 还记得我们的专利案例吗?
在上一篇里,我们设定了一个贯穿全系列的案例:
场景:你在科技公司搜索研发部实习,要从 1000 万条专利 中检索相似专利。
查询:
"一种基于深度学习的图像去噪方法"目标:找到最相关的 3 条专利(真实答案是:卷积神经网络降噪、深度学习图像增强、自编码器去噪)
今天我们就用这个案例,一步步演示 K-Means、IVF、HNSW 到底是怎么工作的!
一、 核心思想:ANN(近似最近邻)
在讲具体算法前,我们要先达成一个共识:ANN (Approximate Nearest Neighbor)。
翻译成人话就是:“差不多得了,要的是速度”。
在海量数据(比如 1 亿条)面前,要找到“绝对”最近的那个向量(暴力搜索),计算机得算断气。ANN 的目标是:允许你稍微有一点点误差(比如本来是第 1 名,你找出了第 2 名),但速度要快几百倍,内存要省几倍。
接下来的所有算法,都是为了实现这个“又快又准”的平衡。
二、 基础中的基础:K-Means 聚类
在讲高级的 IVF 之前,必须先懂 K-Means,因为它是很多索引算法的“地基”。
1. 这是在干嘛?
想象操场上站了 1000 个学生(向量),乱七八糟的。教官吹哨子:“所有人分成 4 个班,每班选个班长!”
K-Means 就是这个自动分班、选班长的过程。
2. 算法怎么动?(迭代过程)
这是一个“动态调整”的过程:
- 随机点将:电脑先在人堆里随便指 4 个人当“临时班长”(质心 Centroids)。
- 各自归队:剩下 996 个人,看自己离哪个临时班长最近,就站到哪个班的队伍里。
- 篡位(重新计算):队伍站好后,大家发现临时班长其实站得偏了。于是算出这个队伍真正的“正中心”位置,那个位置变成“新班长”。
- 循环:新班长上任 -> 大家根据新班长调整队伍 -> 再算新中心……直到班长的位置不再变动,队伍稳定了。
我画个图你就能看懂这个循环:
1 | graph TD |
3. 有啥 Bug?
现实中,数据是密密麻麻连在一起的。如果查询点刚好在两个班级的交界处(边界相邻),它的"真爱"可能在隔壁班,但因为它离本班班长稍微近了 0.01 毫米,它就被锁死在本班里找,结果就错过了隔壁班最近的那个邻居。
这个问题怎么解决?看下面 IVF 的操作。
🔬 专利案例演示:K-Means 聚类过程
让我们看看 1000 万条专利是怎么被"分班"的:
1 | 🏫 K-Means 分班过程(K=1000,即分成 1000 个班) |
关键发现:我们的三个"真爱"专利,有 2 个在 #789 班,1 个在 #791 班!
这就是为什么后面 IVF 要用 nprobe 参数——如果只搜 1 个班,就会漏掉那个在隔壁班的"自编码器去噪"!
三、 中流砥柱:IVF (倒排文件索引)
IVF (Inverted File Index) 是目前数据库里用得超级多的一种技术。它的灵感直接来源于 K-Means。
1. 什么是“倒排”?
- 在搜索引擎里,倒排是:
单词 -> 包含这个词的文章列表。 - 在向量数据库里,倒排是:
班长(中心点) -> 属于这个班的所有向量列表。
2. Voronoi 单元(泰森多边形)[了解]
你在很多技术文章里会看到“Voronoi”这个词,其实就是划分势力范围。
空间中每一个点,都有一个对应的“最近中心点”。把所有离中心点 A 最近的区域画个圈,就是 A 的地盘(Voronoi 单元)。这就把无限的空间切成了有限的小块。
3. 检索过程(怎么找?)
这招叫:擒贼先擒王。
假设来了一个查询向量 Query(比如用户问“哪里有可爱的猫”):
- 找班长(粗筛):先别管那是几亿个小兵,先拿
Query去跟那几千个“班长”比。算算离哪个班长最近。 - 搜小兵(细筛):找到最近的班长后,通过倒排表拿到这个班的花名册,只在这个班里挨个算距离。
这样,计算量瞬间从“1 亿次”变成了“几千次(找班长)+ 几百次(班里找)”,速度起飞!
4. 解决边界问题的绝招:nprobe
为了防止“真爱在隔壁班”的情况,我们不光搜最近的那 1 个班,我们搜最近的 n 个班。
这就是参数 nprobe 的含义。
nprobe = 1:只搜最近的 1 个笼子,快但可能漏。nprobe = 10:搜最近的 10 个笼子,稍微慢点,但基本不会漏。
🔬 专利案例演示:IVF 检索全过程
好,现在让我们完整走一遍 IVF 检索流程!
Step 1:查询来了
1 | 用户输入:"一种基于深度学习的图像去噪方法" |
Step 2:找班长(粗筛)
1 | Query 和 1000 个班长(中心点)比距离: |
Step 3:搜小兵(细筛)
假设 nprobe = 1(只搜最近的 1 个班):
1 | 📊 IVF 搜索结果(nprobe=1) |
假设 nprobe = 3(搜最近的 3 个班):
1 | 📊 IVF 搜索结果(nprobe=3) |
结论:nprobe 就是你的"保险系数"。调大一点,多花点时间,但不容易漏人!
1 | graph TD |
四、 HNSW (分层图索引)
IVF 虽然好,但它有个瓶颈:如果维数特别高,找班长也是要时间的。而且数据分布不均匀时,有的班特别挤,有的班没人。
于是,HNSW (Hierarchical Navigable Small World) 横空出世。它是目前性能最强的算法之一。
1. NSW:小世界理论
你肯定听过“六度人脉”:你通过不超过 6 个人,就能认识美国总统。
在图论里,这意味着:虽然节点很多,但任意两点之间的路径其实很短。
NSW (Navigable Small World) 的朴素思想是:贪婪搜索。
- 我要找目标点 T。
- 我先随便从一个入口点 E 进去。
- 看看 E 的朋友里,谁离 T 最近?假如是 A。
- 那就跳到 A。再看 A 的朋友里谁离 T 最近?
- 一步步逼近,直到找不到更近的朋友为止。
2. HNSW:给 NSW 修高架桥
NSW 的问题是:如果我不认识那个能“跨越半个地球”的朋友,我就得像走迷宫一样一步步挪,也就是“步长太短”。
HNSW 的改进核心是:分层 (Hierarchical)。
你可以把它想象成交通系统:
- 第 0 层 (最底层):包含所有数据,大家都是邻居,密密麻麻(社区街道)。
- 第 1 层:抽出一部分节点,建个稀疏点的网(城市主干道)。
- 第 2 层 (顶层):再抽出一部分,建个超稀疏的网(高速公路/航线)。
3. 检索过程:跳伞战术
搜索过程就像坐飞机 -> 转高铁 -> 打车 -> 步行。
- 从顶层出发:视野开阔,一步能跨很远。快速锁定大概区域(比如从北京定位到上海)。
- 降落一层:在那个大概区域里,利用更密的网,稍微精细一点找(定位到徐汇区)。
- 降落到底层:在最密集的网里,进行最后的精确搜索(找到那家咖啡馆)。
🔬 专利案例演示:HNSW 检索全过程
让我们跟着查询向量,走一遍 HNSW 的"跳伞之旅"!
第 2 层(高速公路层):只有 500 个节点
1 | 🛫 从入口点出发 |
第 1 层(城市主干道层):有 5000 个节点
1 | 🚄 降落到第 1 层,从"图像处理枢纽"继续 |
第 0 层(社区街道层):全部 1000 万个节点
1 | 🚶 降落到底层,精细搜索 |
对比一下:
- 暴力搜索:比较 1000 万次
- HNSW:只比较了约 200 次(每跳检查几十个邻居)
这就是 HNSW 的魔力:通过分层 + 贪婪跳跃,把 O(n) 的复杂度降到了 O(log n)!
我画了个分层图帮大家理解:
1 | graph TD |
4. HNSW 的优缺点 (Trade-off)
天下没有免费的午餐,HNSW 这么强,代价是什么?
-
优点:非常快!召回率极高! 它是目前最接近完美的搜索算法。
-
缺点:吃内存(空间换时间)。
-
除了存向量本身,还得存它在每一层的“朋友关系”(邻接表)。数据量越大,这些关系占的内存越多。
-
建索引慢:每插入一个新数据,都要计算它在每一层跟谁连,写入速度不如 IVF。
五、 终极 PK
看完这三大金刚,咱们最后做一个大总结,帮你决定怎么选:
| 算法 | 原理一句话 | 核心优势 | 核心劣势 | 适用场景 |
|---|---|---|---|---|
| Flat | 暴力硬算,绝不偷懒 | 100% 准确 | 慢到令人发指 | 数据极少(<1万条)做验证时用 |
| IVF | 划分地盘,擒贼先擒王 | 内存占用低,速度均衡 | 精度受 nprobe 影响,需要预训练 |
数据量大(亿级),内存预算有限,追求高性价比 |
| HNSW | 修建分层高速公路 | 最快,最准 | 内存占用大,写入稍慢 | 追求极致检索性能,内存管够,实时性要求高 |
小白选型指南:
- 默认首选:如果不差内存,无脑上 HNSW。现在的向量数据库(Milvus, Chroma, Weaviate)很多默认都推这个。
- 海量省钱:如果数据量几千万上亿,想省点内存,用 IVF_PQ(IVF倒排 + PQ量化压缩)。
好啦!这次咱们把**“怎么聚类分班”、“怎么倒排查表”、“怎么分层跳跃”**这三个最硬核的逻辑都拆干净了。
希望这篇“人话版”教程能让你下次看到这些技术名词时,脑海里直接浮现出“找班长”和“修高速”的画面,那是真的懂了!
我是 Richard,咱们下期见!👋


