首页/AI/RAG 与向量库速查/MRR 与 NDCG 排序质量
Embedding 与检索50 条

MRR 与 NDCG 排序质量

MRR(平均倒数排名)关注首个相关结果的位次,适合问答类单一答案场景;NDCG 引入位置折损与相关度分级,更适合多相关文档的排序评估。

RAG 与向量库速查AI更新于 2026-10-13

两个指标各看什么

MRR(平均倒数排名)只看首个相关结果排在第几位,适合答案是唯一片段的问答场景;NDCG 引入位置折损与相关度分级,更适合多个相关文档、重要程度不同的排序评估。两个指标一起看最稳妥:MRR 反映第一个正确答案有多靠前,NDCG 反映整份排序的质量与分级合理性。

基本信息

MRR首个相关结果名次的倒数取平均,1.0 为理论最好
NDCG@k按位置折损累加相关度并归一化,取值 0 到 1
相关度分级需人工标注等级,如 2 表示直接回答、1 表示部分相关
使用建议问答看 MRR,多片段排序看 NDCG,报告里同时给出

典型使用场景

  • 检索调参:调 nprobe 或融合权重后,看 MRR 是否上升
  • 重排验证:重排上线后 NDCG 提升说明排序更合理
  • 回归门禁:两项指标同时不低于基线,才允许发布
  • 方案对比:混合检索与纯向量检索在同一评测集上比排序质量
  • 问题定位:召回够但 MRR 低,说明正确片段被挤在后面,需要看重排

MRR 与 NDCG 计算

MRR 与 NDCG 计算
import math

def mrr(runs):
    total = 0.0
    for ranked in runs:                      # 每次查询的排序列表
        for i, rel in enumerate(ranked, start=1):
            if rel:
                total += 1 / i               # 只取首个相关结果
                break
    return total / len(runs)

def ndcg_at_k(ranked_relevances, k):
    dcg = sum(r / math.log2(i + 1) for i, r in enumerate(ranked_relevances[:k], start=1))
    ideal = sorted(ranked_relevances, reverse=True)[:k]
    idcg = sum(r / math.log2(i + 1) for i, r in enumerate(ideal, start=1))
    return dcg / idcg if idcg else 0.0       # 归一化后可跨查询比较

指标对照

指标关注点何时优先
MRR首个相关结果的位置单一答案的问答场景
NDCG@k整体排序质量与相关度分级多片段、相关度有分级的场景
Recall@k是否被召回,不考虑位置检索阶段的覆盖体检
P95 延迟性能约束体验与容量规划
NDCG 需要相关度等级(如 2 表示直接回答、1 表示部分相关):标注成本换来的是排序灵敏度,标注口径要写进文档并固定下来。
指标口径变化会让历史数据失去可比性:分级标准或 k 值调整后要重跑基线,不能直接把新旧数字放在一起比较,否则会把口径差异误读成效果变化。
报告里附上指标置信区间或样本量:小评测集上的一次提升可能只是抽样波动,给出样本规模能让评审者判断差异是否值得采纳。

易错点

  • 问答场景只报 NDCG,首个命中未排前位的问题被平均数掩盖
  • 相关度分级标注口径不统一,跨版本 NDCG 不可比
  • 只报单一指标,掩盖另一个维度的退化
  • 评测集规模太小,指标波动大,改动效果被噪声淹没

数据来源与参考

  • Manning et al., Introduction to Information Retrieval(MRR / NDCG)
  • scikit-learn 官方文档(ndcg_score)
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌