
怎么证明 Rerank 真的有用nDCG、P95 延迟与冻结测试集结论先放前面证明一个检索策略有效不能靠挑几条 query 看效果而要靠三件事分级相关性指标nDCG、尾部延迟P95、以及调参用 dev、验收用冻结 test的纪律。少任何一件你的结论都可能是自欺欺人。文章目录怎么证明 Rerank 真的有用nDCG、P95 延迟与冻结测试集一、先讲一个自欺欺人的场景二、指标一nDCG比 Top1 更细的尺子2.1 Top1 和 MRR 的局限2.2 nDCG 的手算逻辑2.3 真实手算示例三、指标二P50/P95平均值会骗你四、纪律一dev 调参test 冻结4.1 问题边调边测 过拟合4.2 解法拆分 冻结五、纪律二hard negative让指标不虚高5.1 问题太简单的评估集5.2 解法加入近似干扰文档六、把四件事串起来一次可信的评估长什么样七、常见自欺行为自查表八、写在最后一、先讲一个自欺欺人的场景假设你刚给检索链路加了 Rerank想证明它有用。最简单的办法挑 3 条你记得的 query 跑一遍。发现 Rerank 把相关文档排到了第一。宣布Rerank 有效上线。问题在哪样本偏差你挑的 query 可能恰好是 Rerank 擅长的。指标单一只看 Top1不知道整体排序是否变好。没有代价意识Rerank 让 P95 延迟从 500ms 涨到 2 秒你没提。边调边测你一边看结果一边调参数调出的最优参数只是过拟合了这几条 query。我在 EasySearch 2.3 上做 Week3 实验时专门设计了一套流程来防这些坑。这篇文章把它摊开讲。二、指标一nDCG比 Top1 更细的尺子2.1 Top1 和 MRR 的局限Week2 我们用过 Top1 Acc 和 MRR但它们有个共同问题只关心第一个相关结果。实际检索里一个 query 可能有多个相关文档相关程度还不同relevance2直接相关能直接解决问题。relevance1部分相关有参考价值。relevance0不相关。假设两个排序结果排序A[relevance1, relevance2, relevance0] 排序B[relevance2, relevance1, relevance0]Top1 指标看A 的第一名是部分相关B 的第一名是直接相关——B 更好。但如果只看有没有命中A 和 B 前两名都包含了同样的文档集合。Top1 和 Recall 都没法完整刻画这种排序质量的差异。这就是nDCG要解决的问题。2.2 nDCG 的手算逻辑nDCG 分三步算第一步DCG折损累积增益位置越靠后相关性的贡献打折扣DCG Σ (2^rel - 1) / log2(rank 1)第二步IDCG理想 DCG把所有文档按相关性从高到低排算出的 DCG 就是理论最大值。第三步nDCG DCG / IDCG归一化到 0~11.0 表示完美排序。2.3 真实手算示例用我们实验报告里的例子返回前三名等级为[1, 2, 0]。DCG (2^1-1)/log2(2) (2^2-1)/log2(3) (2^0-1)/log2(4) 1/1.0 3/1.585 0/2.0 2.8928理想排序是[2, 1, 0]IDCG 3/1.0 1/1.585 0/2.0 3.6309nDCG 2.8928 / 3.6309 0.7967关键点nDCG 惩罚的是部分相关排在直接相关前面。即使相关文档都召回了排错位置也会扣分。三、指标二P50/P95平均值会骗你只看平均延迟是最常见的自欺方式。来看我们实验的真实延迟数据EasySearch 2.3 本地 CPU策略P50 (ms)P95 (ms)RRF167.82577.74RRFRerank(5)752.321661.41RRFRerank(10)1445.161967.96如果只看 P50Rerank(10) 的中位请求约 1.45 秒好像“可以接受”。但这 25 条串行 dev 样本算出的插值 P95 已接近 2 秒。样本很小不能直接外推成精确的线上用户比例。P95 能暴露中位数看不到的尾部延迟它是否可接受还要结合真实并发、目标硬件和业务 SLO 再判断。工程原则评估检索策略质量指标nDCG和尾部延迟P95必须同时出现。只报质量的是在隐藏成本只报延迟的是在回避效果。四、纪律一dev 调参test 冻结这是最容易被忽视、也最重要的一条。4.1 问题边调边测 过拟合如果你用同一批 query 反复做这两件事跑实验看指标。发现某个 query 效果不好调参数。那么你调出来的“最优参数”可能过拟合这批 query。反复使用 dev 做模型选择属于开发集过拟合风险只有当 test 信息被用于调参时才构成更明确的测试集泄漏。两者要区分。4.2 解法拆分 冻结我的做法Week3 实验40 条 query ├── 25 条 dev开发集随便调参、随便跑、随便看 └── 15 条 test测试集人工复核标签后冻结冻结的含义test 只在所有参数定下来之后运行一次。跑完的结果就是最终结论不管好坏都不许回头改参数再跑。如果 test 结果不好承认它分析原因改进留给下一轮。我目前的实验状态如实说25 条 dev 已经跑完用于选参数15 条 test 还在人工复核标签没有冻结所以没有最终结论。dev 数字可以作为开发阶段实验结果但不能包装成冻结 test 或泛化结论。五、纪律二hard negative让指标不虚高5.1 问题太简单的评估集如果你的文档库里相关文档和不相关文档差异巨大比如 query 问Elasticsearch 黄灯候选里混着苹果手机评测那任何检索策略都能拿高分。这种评估集测出来的指标是虚高的没有区分度。5.2 解法加入近似干扰文档hard negative难负例指的是主题和关键词接近但不能真正回答 query 的文档。我的 Week3 文档集80 条专门加了这类文档。比如query 问磁盘 await 很高接口变慢期望磁盘 IO 文档部分相关文档ops-cpu-003“Load Average 高但 CPU 不高”标签为 relevance1因为正文也涉及不可中断 IO 等待。hard negativeops-net-005“跨可用区调用延迟升高”同样描述调用变慢但标签为 relevance0不能直接回答磁盘 await 问题。有了 hard negative才能测出策略之间真正的差异——比如我们的实验就发现Rerank 在好几个这种 case 上把部分相关文档排到了直接相关前面导致 nDCG 下降。六、把四件事串起来一次可信的评估长什么样一次可信的 Rerank 效果评估流程应该是1. 建评估集80 文档含 hard negative40 条 query0/1/2 分级标签 2. 拆 dev/test25 dev 调参15 test 冻结 3. dev 上跑对比 BM25 / KNN / RRF / RRFRerank 的 Top1/MRR/nDCG10 4. dev 上选参确定 rerank 候选数5/10/20 5. 冻结参数test 只跑一次 6. 报告质量指标 P50/P95 延迟 badcase 分析 实验边界这里还要检查“候选深度”和“最终评估深度”是否一致。本项目的Rerank(5)只能返回 5 条却报告 nDCG10因此不能把它与返回 Top10 的策略做完全公平的 nDCG 横向比较10 与 20 都最终评估 Top10可以直接比较。我们在 dev 上的真实结果80 文档、25 query策略Top1MRRnDCG10P95 (ms)KNN0.9600.9600.891320.65RRF0.8400.9250.871577.74RRFRerank(10)0.9200.9460.8811967.96结论如实说在这个 dev 集上Rerank 没有超过单路 KNN其 P95 约为 KNN 的 6.1 倍1967.96ms vs 320.65ms。这个结论只有在 test 冻结运行后才能最终确认但 dev 数据已经足够说明“Rerank 不是免费的午餐”。七、常见自欺行为自查表发布检索效果结论前对照检查评估集有没有 hard negative还是全是一眼就能区分的文档指标有没有包含 nDCG分级相关性和 P95尾部延迟test 是不是只跑了一次有没有边看结果边调参有没有如实呈现策略变差的 case还是只挑了变好的报告里有没有写明数据规模、硬件环境CPU/GPU结论有没有注明是 dev 还是冻结 test 的结果如果任何一条打叉你的结论就先别急着发。八、写在最后检索系统的效果证明本质上是一场和自己的博弈你的直觉想让你挑好看的数字。你的工程纪律应该逼你看完整的数字。nDCG 描述分级排序质量P95 描述本次样本中的尾部延迟冻结 test 用于减少调参污染。它们能让结论更可信但小样本 P95 仍不能直接代表线上用户等待分布。下一篇我会写8 个真实 badcase 的证据链——Rerank 到底在哪些场景会翻车以及怎么判断是召回的锅还是精排的锅。环境EasySearch 2.3.0 Python 3.14.4 sentence-transformers 5.6.0 BAAI/bge-reranker-baseCPU你做检索评测时有没有遇到过dev 上调得很好一上 test 就掉的情况欢迎评论区交流。