总:KNN 这一算法在工业界几乎不用了,但它回答的那个问题——“给我最相似的 K 个”——是现在重要的基础设施:向量数据库、RAG 召回、推荐系统召回层、以图搜图,都可以视为最近邻思想的工程化延伸。这篇把 KNN 的思想接到 ANN(近似最近邻)上。
一、研究定位
- KNN 的问题:预测要算全部样本距离,O(n·d),数据规模增大后成本迅速上升 → 工业方案是 ANN:牺牲一点点召回,换百倍千倍速度
- 2025-2026 最重要的落点:RAG 的 top-k 召回就是一次带过滤条件的 ANN 查询,HNSW 是常见的索引
- 这个问题在现代系统里通常表现为:HNSW 如何工作、为什么不用暴力检索、召回率和延迟如何权衡。它和课内 KNN 共享同一个最近邻问题。
二、机制回顾
- 思想:k 个最近邻居多数表决(分类)/ 求平均(回归),相似性 = 欧氏距离
- K 小 → 过拟合(对噪声敏感);K 大 → 欠拟合(被远处点稀释)
- 距离类算法必须标准化,量纲大的特征会支配距离
- 限制:lazy learning 无训练过程,预测慢 + 高维距离失效(维度灾难)
三、研究与应用脉络
3.1 从精确 KNN 到 ANN
暴力检索是 O(n·d),一亿条 × 1024 维就成本不可接受。ANN 的思路是允许漏掉 1% 的真邻居,换 100 倍速度:
| 索引 | 思想 | 适用观察 |
|---|---|---|
| HNSW | 分层跳表图:上层稀疏长边快速定位,下层稠密短边精修 | 当前默认选型,Faiss/Milvus/qdrant/pgvector 都有 |
| IVF | 先 K-Means 聚成 nlist 个桶,查询只扫最近的几个桶 | K-Means 直接当了索引,nprobe 调召回/速度 |
| PQ 乘积量化 | 向量切段、每段聚类用质心 ID 代替 → 压缩存储 | 内存省 10-100 倍,有量化损失 |
(这里的联系是:IVF 的分桶就是 K-Means,向量数据库的底层思想在课里全学过。)
3.2 RAG 系统里的 KNN(我的主要场景)
一条 RAG 查询的召回层拆开看:
- query → embedding 模型(bge-m3 / text-embedding-3)→ 向量
- 向量库 ANN 检索 top-k(这里就是 KNN 的 K!K 过小会降低召回,K 过大则会把噪声带入上下文)
- 常配混合检索:BM25(稀疏,管关键词/术语精确匹配)+ 向量(稠密,管语义)→ RRF 融合排序
- 需要进一步提高精度时再加 reranker(cross-encoder 精排)
工程要点(都是需要记录的问题):
- K 和 chunk_size 是 RAG 最敏感的两个超参——对应 KNN 的 K 值选择问题
- embedding 前文本要归一化(去 HTML、去重),对应特征预处理
- 过滤条件(租户/时间)用 filtered HNSW,先过滤后搜或边搜边滤是两种策略
- 评估用 Recall@k——这是 KNN 的”近邻命中率”在 RAG 里的化身
3.3 推荐系统召回层
工业推荐 = 召回(万→千)+ 粗排(千→百)+ 精排(百→几十)。召回层的经典打法就是双塔模型:user 向量和 item 向量各自过塔,内积算相似度,线上用 ANN 检索 top-k——KNN 思想 + 学习出来的向量。
3.4 距离度量选型速查
| 距离 | 用法 | 场景 |
|---|---|---|
| L2 欧氏 | 绝对位置差异 | 图像特征、聚簇数据 |
| 内积 IP | 方向相似性 | 推荐系统双塔 |
| 余弦 | 方向,对模长不敏感 | 文本 embedding 默认(bge/OpenAI 系都按余弦/内积训的) |
坑:bge-m3 这类模型训练时用的是特定度量,向量库建索引时度量选错,召回质量会显著下降。
四、研究问题与讨论
问题: KNN 的优缺点? 讨论: 优点:思想简单、天然多分类、无训练成本。缺点:预测 O(n·d) 慢(lazy learning)、对量纲敏感必须标准化、K 和距离度量是超参、高维下距离区分度失效(维度灾难)。工业界的答案:把”精确”换成”近似”(ANN),用 HNSW/IVF 索引。
问题: HNSW 为什么快? 讨论: 多层跳表式图结构。上层节点稀疏、边长,像高速公路快速跨域;下层稠密、边短,负责精修。查询从顶层贪心下降,每层只维护少量候选,复杂度近似 O(log n)。代价:内存大(存图)、建索引慢、删除不方便。
问题: RAG 为什么要混合检索? 讨论: 向量检索管语义但弱于精确匹配——型号、报错码、人名这类 token 级信号会被语义平滑掉;BM25 反之。RRF(倒数排名融合)不依赖分数可公度性,可以把两路排名融合,是常见工程方案。
五、后续实验
KNN 教给我的是“相似性就是生产力”:定义好嵌入和距离,检索、推荐、去重全都自动成立。 动手项:拿 FAISS 对 10 万条 bge-m3 向量分别建 IndexFlatL2(暴力)和 IndexHNSWFlat,压测 QPS 和 Recall@10——记录”近似换速度”这种速度与召回交换的边界。
六、研究向延伸
这一篇适合转成向量检索实验。固定一批 query 和人工标注相关文档,分别比较暴力检索、HNSW、IVF、PQ 和混合检索:记录 Recall@k、MRR、延迟、索引体积、构建时间,以及过滤条件加入前后的召回损失。
需要特别记录失败样例:术语、型号、人名、缩写、跨语言查询、长文档切块边界。这些样例比平均分更能解释为什么 RAG 系统需要 BM25、向量召回和 reranker 协同。