这个坑值得记一笔。百万级数据用 IndexIVFFlat 检索,返回的结果里经常漏掉明显相关的文档,换成暴力索引就能命中。
刚开始盯着「查询向量分布与训练集聚类中心偏离」,折腾了半个多小时,排掉了。
真正麻烦的地方在于,几个原因的现象几乎一样。nprobe 默认值太小,只扫描了少量聚类;聚类数 nlist 设得过大,单簇样本太少;训练索引用的样本不足,聚类中心质量差。
第一件事是查当前索引的聚类与探测参数
python -c "print(index.nlist, index.nprobe)"
提高探测簇数换取召回
index.nprobe = 32
然后用已知答案构造小测试集评估召回
python eval_recall.py --index faiss.index --q 200 --k 10
必要时减少聚类数重训索引
index = faiss.IndexIVFFlat(faiss.IndexFlatL2(dim), dim, 1024)
我习惯把每一步的执行时间和结果记在一边,后面复盘省事。
别只看报错消失,验证要多做一步。召回率在测试集上提升到九成以上,单次查询耗时增加但仍在可接受范围。
补一句。nprobe 越大越准也越慢,线上要按延迟预算选值,别直接用默认值也别直接拉满。这类问题最好一次改到位,反复小改反而容易把原因搅混。