周末的池塘边,一年一度的钓鱼大赛开始了。每位渔夫带着自己精心设计的“捕捞顺序清单”来到裁判面前——比赛不比力气,比谁更懂鱼。池塘里游着金贵的观赏鱼(相关文档),也混着大量的杂草鱼(不相关文档)。渔夫们要做的,是凭着对水性的理解,报出一份 20 个钓点的顺序清单。裁判的任务则是:这份清单到底排得好不好? 信息检索系统面对的就是同样的问题。用户抛出一个查询(query),搜索引擎在毫秒级返回一长串网页,我们凭什么说这个排序“好”或“不好”?答案是一套标准化的裁判规则——评价指标。这篇文章用钓鱼比赛贯穿始终,把三大主力指标讲透:MAP(平均精度)、NDCG(归一化折损累计增益)、MRR(倒数排名)。它们从不同角度回答同一个问题:你排出来的清单,到底有多懂用户的心?

岗位关联

评价指标是排序模型的“方向盘”,没有它,一切优化都无从谈起。学透 MAP/NDCG/MRR,你就拿到了搜索引擎、推荐系统、问答产品的通用度量衡,无论做召回、排序还是 RAG,都能科学地回答“我的模型到底变好了没有”。

目录
  1. 可视化演示
  2. 评价指标基础
  3. 精确率与召回率
  4. 平均精度MAP
  5. 归一化折损NDCG
  6. 倒数排名MRR
  7. 指标对比与选择
  8. AI 应用场景
  9. Python 演示
  10. 常见误区
  11. 面试题

可视化演示

展示IR三大评价指标:MAP均值平均精确率(每个相关文档位置Precision@k取平均多查询AP均值综合考虑精确率和排序质量)、NDCG归一化折损累积增益(按位置折损累积相关性增益1/log2(k+1)归一化至[0,1]支持多级相关性)、MRR平均倒数排名(第一个相关文档排名的倒数1/rank多查询均值适合QA系统),三模式切换理解评价指标全貌。

本节配有交互动效(进入视口后自动加载,约 3KB)。

'+C1+'

评价指标基础

钓鱼大赛的裁判要做的第一件事,不是拿着秒表计时,而是先和所有参赛者确认“什么算好鱼”。是金鱼算好鱼,还是锦鲤也算?是只看品种,还是也要看个头大小?如果标准都没定,后边的分数就是一笔糊涂账。搜索引擎的评价也一样:第一步永远是定义相关性——一个文档到底跟用户输入的查询匹不匹配。

在信息检索领域,相关性就是“鱼的好坏标准”。最朴素的定义是二元的:文档 d 与查询 q 相关,记为 1;不相关,记为 0。更精细的做法是分多级,比如 0 到 3 级,3 表示高度相关,0 表示完全不相关。定义了相关性之后,系统的输出——一个排序列表——才能被量化打分。评价指标本质上就是一套把“排序列表 + 相关性标注”映射成数值的规则。

这套规则还有一个重要的使用场景:离线评测。渔夫不可能每次比赛都真刀真枪下水试一遍,那太费鱼了。搜索引擎同样不能在线上拿真实用户体验做实验,于是人们用一批人工标注好的“查询-文档”数据,让新模型离线跑一遍,算指标、看涨跌,满意了再上线。这就是评价指标的核心价值。

裁判拿起了标准的鱼种清单。但很快他发现——光有“好鱼”的定义还不够,还得解决一个更棘手的问题:渔夫们捞上来的鱼是排着队的,不同位置的好鱼,含金量能一样吗?

rel(q,d)={1,文档 d 与查询 q 相关0,否则\text{rel}(q, d) = \begin{cases} 1, & \text{文档 } d \text{ 与查询 } q \text{ 相关} \\ 0, & \text{否则} \end{cases}
这个公式是所有评价指标的“原料”:先把每个文档判成好鱼或杂草鱼,后续一切分数都从这出发。
  1. 相关性函数$\text{rel}(q, d)$ 是一个判断函数,输入是查询 $q$ 和文档 $d$。
    rel(q,d)\text{rel}(q, d)
  2. 相关取值当文档和查询匹配时,函数返回 1;不匹配时返回 0。
    1 (相关)或0 (不相关)1 \text{ (相关)} \quad \text{或} \quad 0 \text{ (不相关)}
  3. 评价基础所有排序指标都以这个二元(或多级)判断作为计算原料。
    评价指标=f(排序列表,rel(q,d))\text{评价指标} = f(\text{排序列表}, \text{rel}(q, d))

精确率与召回率

裁判拿到渔夫的清单,第一反应是看前几个钓点。如果前 10 个钓点里有 8 个能钓到好鱼,这渔夫大概有两下子。这个“前 K 个位置里好鱼占比”就是精确率 P@K。但再一想,裁判又犹豫了:万一这个渔夫很保守,只挑了 10 个最稳的钓点报了 10 条好鱼,池塘里还有 90 条好鱼他根本没报呢?所以还得看第二个数:召回率 R@K——他报的清单里,覆盖了全池塘多少比例的好鱼。

精确率和召回率就像一枚硬币的两面:精确率看“我报上来的这一网有多纯”,召回率看“全池塘的好鱼被我一网兜住了多少”。一个只报 1 条且必中好鱼的渔夫,精确率高达 1.0,但召回率可能只有 0.01,对整场比赛毫无意义。反过来,把所有钓点都报一遍,召回率 1.0,精确率却低得可怜。于是裁判常用 F1 把两者调和起来,等于给精确率和召回率各打五十大板再看综合成绩。

在实际搜索中,P@K 特别适合衡量“前几页”的用户体验——毕竟很少有人翻到第 10 页之后。R@K 则适合衡量系统是否漏掉了大量好内容。两者需要配合使用:P 高 R 低,系统像个“精选小馆”;P 低 R 高,系统像个“大杂烩食堂”。好的搜索系统追求的是精选而不遗漏。

裁判陷入了沉思:P@K 只盯着前 K 个位置,K 取 3 还是取 10?取多取少都会改变结果。而且,同样是有好鱼,排在第 2 位和第 8 位体验天差地别。看来,需要一个更聪明的记分方式——把每一个好鱼出现的位置都算进去。

P@K=∣{相关文档}∩{前 K 个结果}∣K,R@K=∣{相关文档}∩{前 K 个结果}∣∣{全部相关文档}∣P@K = \frac{|\{\text{相关文档}\} \cap \{\text{前 }K \text{ 个结果}\}|}{K}, \qquad R@K = \frac{|\{\text{相关文档}\} \cap \{\text{前 }K \text{ 个结果}\}|}{|\{\text{全部相关文档}\}|}
P@K 看“这 K 条里对了几条”,R@K 看“全部对的里被翻出来几条”。一个管纯度,一个管覆盖。
  1. 交集计数分子是“前 K 条结果中,被判定为相关的文档个数”。
    ∣{相关文档}∩{前 K 个结果}∣|\{\text{相关文档}\} \cap \{\text{前 }K \text{ 个结果}\}|
  2. 精确率的归一化除以 K,得到 0 到 1 之间的纯度分数。
    交集数K\frac{\text{交集数}}{K}
  3. 召回率的归一化除以全部相关文档总数,得到覆盖率。
    交集数∣{全部相关文档}∣\frac{\text{交集数}}{|\{\text{全部相关文档}\}|}
  4. F1 调和平均同时惩罚精确率和召回率的短板。
    F1=2×P@K×R@KP@K+R@K\text{F1} = \frac{2 \times P@K \times R@K}{P@K + R@K}

平均精度MAP

想象裁判换了个评分思路:他不直接看清单整体,而是沿着渔夫的清单从头走到尾,每遇到一条好鱼,就停下来回头算一次“到目前为止的精确率”,最后把这些精确率全部加起来取平均。这就是AP(Average Precision,平均精度)。它天生对位置敏感——好鱼排得越靠前,早期回望时精确率越高,AP 也就越高。这比只看 P@K 公平多了。

一个查询算出来一个 AP,但搜索系统每天要面对成千上万个不同的查询。于是裁判把所有查询的 AP 再取一个平均,得到 MAP(Mean Average Precision,平均精度均值)。MAP 是信息检索学术界最经典的排序指标之一,尤其在文本检索、学术搜索这类“相关与否通常按二元判定”的场景中,MAP 几乎是标配。

MAP 的巧妙之处在于,它同时惩罚两类错误:把杂草鱼排在前面会拉低命中位置的精确率;把好鱼排在后面会减少回望时的收益。它不像 P@K 那样只关心前 K 个位置,而是覆盖整个排序列表。因此 MAP 高,意味着系统整体上倾向于把好鱼往前提,而不是只在头部做做样子。

MAP 很公正,但它有一个悄悄的前提:它把每条好鱼都当成同样的价值,只有“是好鱼”和“不是好鱼”两种状态。可现实中的鱼是有等级之分的——观赏鱼里也分普通金鱼和珍稀锦鲤,捞到一条锦鲤的喜悦,哪是十条金鱼能比的?裁判需要一把更精细的尺子。

AP=1R∑k=1nP@k×rel(k),MAP=1Q∑q=1QAPqAP = \frac{1}{R} \sum_{k=1}^{n} P@k \times \text{rel}(k), \qquad MAP = \frac{1}{Q} \sum_{q=1}^{Q} AP_q
AP 是“每钓到一条好鱼就回望一次精度”的累积平均,MAP 则是把多场钓鱼比赛的 AP 再平均一次。
  1. 相关性开关$\text{rel}(k)$ 表示第 $k$ 位是否是好鱼,只有好鱼的位置才参与累加。
    rel(k)∈{0,1}\text{rel}(k) \in \{0, 1\}
  2. 命中位置精度$P@k$ 是第 $k$ 位之前(含第 $k$ 位)的精确率。
    P@k=前 k 位中的好鱼数kP@k = \frac{\text{前 }k \text{ 位中的好鱼数}}{k}
  3. 归一化求和对所有命中位置的 $P@k$ 求和后,除以总好鱼数 $R$。
    AP=1R∑k=1nP@k⋅rel(k)AP = \frac{1}{R} \sum_{k=1}^{n} P@k \cdot \text{rel}(k)
  4. 多查询平均MAP 把所有查询的 AP 相加再除以查询总数 $Q$。
    MAP=1Q∑q=1QAPqMAP = \frac{1}{Q} \sum_{q=1}^{Q} AP_q

归一化折损NDCG

这次裁判换了一个更商业化的思路:每条鱼都有明确的“市场价”,珍稀锦鲤 100 分,普通金鱼 10 分,杂草鱼 0 分。渔夫清单上的每个位置,价值会随排名往后而折损——就像活鱼摆摊,越往后卖,鱼越不新鲜,价格越要打折扣。把每个位置“鱼的等级收益 × 位置折扣”累加起来,就是 DCG(折损累计增益)。

但 DCG 有个问题:不同池塘的鱼总量不同,有的塘全是锦鲤,有的塘全是杂草,直接比 DCG 等于拿不同难度的比赛硬比。所以裁判补了一步——先算出“如果渔夫是神仙,知道每一条鱼的位置”时的最高 DCG,称为 IDCG(理想折损累计增益),再让每个渔夫的实际 DCG 除以这个理想值,得到 NDCG(归一化折损累计增益)。这样分数被压到 0 到 1 之间,跨查询、跨数据集都能比了。

NDCG 是工业界最受宠的排序指标之一。它支持多级相关性标注,把“点没点、加没加购、买没买”这类用户行为映射成 0/1/2/3 级等级分;它的对数折损又精准地模拟了“位置越靠后,用户越懒得看”的心理。一个 NDCG@10 = 0.72 的推荐列表,意味着它已经拿到了理想排序 72% 的收益——这在电商、视频推荐里是实打实的商业价值。

NDCG 把“多级价值”和“位置衰减”都考虑进去了,看起来已经很完美。但裁判很快发现,有些比赛根本不需要这么复杂的规则——比如“儿童钓鱼赛”:池子里只放了一条目标鱼,谁先钓到谁赢。这时候算 NDCG 就像杀鸡用牛刀,一个最简单的指标反而最合适。

DCG@K=∑i=1K2reli−1log⁡2(i+1),NDCG@K=DCG@KIDCG@KDCG@K = \sum_{i=1}^{K} \frac{2^{\text{rel}_i} - 1}{\log_2(i+1)}, \qquad NDCG@K = \frac{DCG@K}{IDCG@K}
NDCG 把“鱼的等级”和“排位越靠后折扣越大”同时塞进公式,再用理想清单归一化,让分数公平可比。
  1. 指数增益$2^{\text{rel}_i} - 1$ 把多级等级分映射成指数级收益,等级高一级、收益翻倍。
    2reli−12^{\text{rel}_i} - 1
  2. 对数折损$\log_2(i+1)$ 随着位置 $i$ 增大而增大,让越靠后的文档收益被稀释得越狠。
    log⁡2(i+1)\log_2(i+1)
  3. DCG 累加对前 $K$ 个位置逐一计算“等级收益 / 位置折扣”并求和。
    DCG@K=∑i=1K2reli−1log⁡2(i+1)DCG@K = \sum_{i=1}^{K} \frac{2^{\text{rel}_i} - 1}{\log_2(i+1)}
  4. NDCG 归一化实际 DCG 除以理想排序下的 IDCG,得到 0 到 1 的可比分数。
    NDCG@K=DCG@KIDCG@KNDCG@K = \frac{DCG@K}{IDCG@K}

倒数排名MRR

有些搜索任务,用户心里其实只有一个标准答案:问“北京地铁首班车几点”,答案只有一个;问“某某软件的安装路径”,正确文档也就那一篇。这种场景下,用户根本不在乎第 2 个、第 3 个结果是什么,他们在乎的是第一个正确答案到底排在第几位。RR(Reciprocal Rank,倒数排名) 就是为这种场景生的:找到第一个相关结果,取它排序位置的倒数。

假设系统把正确答案排在第 2 位,RR 就是 1/2 = 0.5;排在第 1 位,RR 就是满分 1.0;排得越靠后,分数断崖式下跌。把多场“单答案比赛”的 RR 一平均,就得到 MRR(Mean Reciprocal Rank,平均倒数排名)。它算法简单、意图直观,是问答系统、知识图谱查询、导航类检索和 FAQ 匹配的最爱。

MRR 的优点也是它的缺点:它只盯着“第一”,完全无视第一个正确结果之后的所有排序。如果一个问答系统在第 1 位给出正确答案,哪怕第 2 到第 10 位全是垃圾,MRR 也照样给满分。所以在多答案场景中,MRR 会严重失真,必须换用 MAP 或 NDCG 这类覆盖全局的指标。

三种主要的裁判规则都到齐了。MAP 像一丝不苟的教练,逐个回望每次命中;NDCG 像精明的鱼贩,给不同等级的鱼按位置打折;MRR 像爽快的游戏裁判,只看第一名。那么问题来了:正式比赛的时候,到底用哪套规则?

MRR=1Q∑q=1Q1rankqMRR = \frac{1}{Q} \sum_{q=1}^{Q} \frac{1}{\text{rank}_q}
MRR 只回答一个问题:第一条好鱼排在第几?第几的倒数,就是这场的得分。
  1. 首个命中位置$\text{rank}_q$ 是第 $q$ 个查询中,第一个相关结果出现的位置。
    rankq\text{rank}_q
  2. 取倒数$\frac{1}{\text{rank}_q}$ 让位置越靠前分数越高,第 1 位得 1,第 2 位得 0.5。
    1rankq\frac{1}{\text{rank}_q}
  3. 查询平均对所有查询的 RR 求算术平均,得到 MRR。
    MRR=1Q∑q=1Q1rankqMRR = \frac{1}{Q} \sum_{q=1}^{Q} \frac{1}{\text{rank}_q}

指标对比与选择

钓鱼大赛最后一天,主办方发现不同分赛场需要不同规则。专业钓鱼联赛要求渔夫均衡发挥、每网都好鱼比例高,用 MAP 最合适;商业捕捞赛的鱼获有明确等级差价,越早捞到越值钱,NDCG 是首选;而寻宝赛池子里只藏了一条锦鲤,谁先找到谁赢,MRR 一锤定音。没有哪个指标是万能钥匙,关键看三件事:标注粒度、答案数量、位置敏感度。

从标注粒度看,MAP、P@K、R@K 都假设“相关/不相关”二元判定,简单但会丢失强度信息;NDCG 天然接受多级等级分,能用更细的标注换取更细腻的评价。从答案数量看,MRR 假设每个查询只有一个正确答案,一旦任务从“找答案”变成“找一批相关文档”,它就会失真;此时 MAP 和 NDCG 才能看全整份清单。从位置敏感度看,MAP 对排序变化很敏感但不打折,NDCG 用对数折损模拟用户耐心衰减,各有各的刻画方式。

工程实践中,没有人会只盯一个数。成熟的搜索团队通常把 MAP、NDCG@10、MRR 一起挂上监控面板,再配合业务指标(点击率、转化率)联合评估。比如新排序模型上线,NDCG@10 涨了 3 个点、MRR 持平,MAP 反而微降,就得具体分析模型是变激进了还是变保守了。指标之间互相校对,才能避免“刷爆一个指标、搞砸真实体验”的陷阱。

裁判收起了三把尺子,把它们并排挂在了计分板上。每把尺子都有自己最擅长的赛场,也都有自己的脾气和盲区。真正老练的裁判不会只盯一把尺子,而是三把尺子互相印证,看穿渔夫们真正的实力。

综合得分=α⋅MAP+β⋅NDCG@10+γ⋅MRR\text{综合得分} = \alpha \cdot MAP + \beta \cdot NDCG@10 + \gamma \cdot MRR
实际工作中常用加权组合:α、β、γ 按业务场景调参,让三个指标相互牵制、互为补充。
  1. 权重系数$\alpha$、$\beta$、$\gamma$ 是根据业务目标手动配置的权重。
    α+β+γ=1\alpha + \beta + \gamma = 1
  2. 指标互补MAP 管整体排序质量,NDCG 管多级折损收益,MRR 管首个答案命中。
    MAP⊕NDCG⊕MRRMAP \oplus NDCG \oplus MRR
  3. 联合评估综合得分作为单一观测值,同时三个分项分别监控避免盲区。
    综合得分=α⋅MAP+β⋅NDCG@10+γ⋅MRR\text{综合得分} = \alpha \cdot MAP + \beta \cdot NDCG@10 + \gamma \cdot MRR

AI 应用场景

企业搜索引擎排序迭代

阶段:离线评测与模型迭代

解决的问题:新排序算法上线前,不能直接拿线上流量冒险。传统做法靠人工抽查几十条结果,主观且无法复现。用 MAP/NDCG@K 在标注好的“查询-文档”数据集上离线评测,可以快速、量化地对比新旧模型,形成可回归的评估管道。

具体案例:某电商搜索团队准备把排序模型从线性模型换成 GBDT。先用 3 万条人工标注的“查询-商品相关度”数据,分别计算新旧模型的 MAP 和 NDCG@10,发现新模型 NDCG@10 从 0.58 提升到 0.62、MAP 从 0.51 提升到 0.55,这才决定推进到线上 AB 实验,避免了一次盲目上线。

电商推荐列表的多级相关评估

阶段:推荐排序效果评估

解决的问题:用户对商品有“浏览 → 加购 → 购买”等多级兴趣强度,二元相关标注会丢失大量强度信息。NDCG 天然支持多级等级分,能更细腻地刻画“用户到底有多想要这条结果”。

具体案例:某视频推荐系统把“看完超过 30 秒 / 完整观看 / 点赞转发”映射成 3 / 4 / 5 级等级分,用 NDCG@20 评估排序质量,同时配合 MRR 观测“用户第一个点击是否落在很靠前的位置”。经过三轮迭代,NDCG@20 从 0.61 提升到 0.68,人均观看时长上涨 11%。

智能客服FAQ匹配

阶段:检索式问答评估

解决的问题:用户问一个问题,只需要返回一个最准确的答案。MRR 直接度量“第一个正确回答出现在第几位”,是问答型系统最直观的体检指标。

具体案例:银行客服机器人上线前,用 1000 条历史问答测试集跑 MRR,从 0.62 提升到 0.75,意味着用户平均能在更靠前的位置获得答案,人工转接率因此下降了 18%。团队还额外监控了“首答满意度”,验证 MRR 的提升确实转化成了用户体验改善。

Python 演示

python75 行
import math  def precision_at_k(ranked_ids, relevant_ids, k):    """前 k 个结果中相关文档占比"""    top_k = set(ranked_ids[:k])    rel = set(relevant_ids)    return len(top_k & rel) / k  def recall_at_k(ranked_ids, relevant_ids, k):    """前 k 个结果覆盖多少相关文档"""    top_k = set(ranked_ids[:k])    rel = set(relevant_ids)    return len(top_k & rel) / len(rel)  def average_precision(ranked_ids, relevant_ids):    """遍历排序列表, 在每个相关文档位置累计精确率"""    hits = 0    ap_sum = 0.0    for i, doc_id in enumerate(ranked_ids, start=1):        if doc_id in relevant_ids:            hits += 1            ap_sum += hits / i    return ap_sum / len(relevant_ids) if relevant_ids else 0.0  def mean_average_precision(query_results, query_relevants):    """MAP = 所有查询 AP 的算术平均"""    return sum(        average_precision(qr, qrel)        for qr, qrel in zip(query_results, query_relevants)    ) / len(query_results)  def dcg_at_k(gains, k):    """增益按位置对数折损后累加"""    return sum(        (2 ** gains[i] - 1) / math.log2(i + 2)        for i in range(min(k, len(gains)))    )  def ndcg_at_k(ranked_ids, relevant_ids, k):    """NDCG = 实际 DCG / 理想 DCG"""    gains = [1 if d in set(relevant_ids) else 0 for d in ranked_ids[:k]]    ideal = sorted(gains, reverse=True)    return dcg_at_k(gains, k) / dcg_at_k(ideal, k)  def mean_reciprocal_rank(query_results, query_relevants):    """MRR = 第一个相关结果位置倒数, 再平均"""    rr_sum = 0.0    for qr, qrel in zip(query_results, query_relevants):        qrel_set = set(qrel)        for i, doc_id in enumerate(qr, start=1):            if doc_id in qrel_set:                rr_sum += 1.0 / i                break    return rr_sum / len(query_results)  if __name__ == '__main__':    result1 = ['doc_a', 'doc_b', 'doc_c', 'doc_d', 'doc_e']    relevant1 = ['doc_b', 'doc_d']    result2 = ['doc_x', 'doc_a', 'doc_b']    relevant2 = ['doc_a']     print('P@3   =', precision_at_k(result1, relevant1, 3))    print('R@3   =', recall_at_k(result1, relevant1, 3))    print('AP    =', average_precision(result1, relevant1))    print('MAP   =', mean_average_precision([result1, result2], [relevant1, relevant2]))    print('NDCG@5=', ndcg_at_k(result1, relevant1, 5))    print('MRR   =', mean_reciprocal_rank([result1, result2], [relevant1, relevant2]))
目的:用两个小查询示例,把 MAP、NDCG、MRR 的计算全过程跑一遍,验证自己对公式的理解。
  1. top_k = set(ranked_ids[:k])取前 k 个结果并转成集合,方便求交集。
  2. len(top_k & rel) / k交集元素数除以 k,得到精确率。
  3. ap_sum += hits / i在命中位置累加当前精确率,这是 AP 的核心动作。
  4. ap_sum / len(relevant_ids) if relevant_ids else 0.0除以相关文档总数做归一化。
  5. (2 ** gains[i] - 1) / math.log2(i + 2)多级增益配合对数折损,DCG 的灵魂。
  6. ideal = sorted(gains, reverse=True)把增益按从大到小排序,得到理想排序的 DCG。
  7. rr_sum += 1.0 / i找到第一个相关文档,取位置倒数计入 RR。

常见误区

误区我觉得 MAP 和 NDCG 都是越大越好,既然这样随便用哪个都行,反正都是衡量排序效果,报告里换着写也没人发现。

正解MAP 只吃二元相关,把所有相关文档命中位置处的精确率做平均,惩罚“相关文档排得靠后”;NDCG 吃多级相关,用对数折损描述“越靠后收益越减”,还要除以理想排序做归一化。好比钓鱼裁判:MAP 是“每条好鱼出现时回头算一次纯度”,NDCG 是“鱼的等级乘位置折扣”,两者视角完全不同。

为何常见:两种指标的数值范围都在 0 到 1 之间,且都对位置敏感,初看非常像,很容易混为一谈。

误区既然 NDCG 是归一化后的,那我直接用 DCG 比较不同查询的排序质量不就行了?反正都是累加分数,数值大的自然更好。

正解DCG 没有归一化,不同查询的相关文档数量、等级分布差异很大,绝对值完全不可比。必须先让每个查询的 DCG 除以它自己的 IDCG,得到 NDCG 后再做平均。就像不同池塘的鱼总数不一样,不能比谁捞了 30 条就是赢家,要比“占这个池塘好鱼总量的比例”。

为何常见:学习路线通常是先记 DCG 公式,再学 IDCG 归一化,很多人在第一步就把 DCG 当成了最终答案。

误区MRR 算起来最简单,我把它用在所有搜索场景里,包括一篇论文有多个相关结果的学术搜索。反正它也是衡量排序效果的指标。

正解MRR 只关注第一个正确答案的位置。系统只要第一个位置对了就满分,其余 9 个相关结果的排序质量完全丢失。多答案场景应该用 MAP 或 NDCG 覆盖全局排序;MRR 只适合问答、导航、FAQ 这类“只想要一个答案”的任务。

为何常见:MRR 公式是三兄弟里最简单的,容易让人贪图方便,忽略它“只见第一”的强假设。

误区我把前 10 条结果的精确率调到了 90%,感觉模型已经非常好了,还要看什么召回率?用户只看前几页,后面的根本无所谓。

正解P@K 只评估前 K 条的纯度,完全不看剩下多少相关文档被埋在了后面。一个只返回 1 条相关文档但排第一的系统 P@1=1.0,可能漏掉了另外 99 条相关文档。只优化精确率会把系统推向“少报但报得准”的极端,因此工程中必须联合 P、R、AP 一起看。

为何常见:精确率的数值直观、涨起来有成就感,容易让人产生“精确率高就是好”的错觉,忘了它是一个只看局部的分数。

面试题

Q1. 信息检索中“相关性”通常指什么?

单选题 · easy

  • A.文档与查询的匹配程度← 正确答案
  • B.文档与文档的相似程度
  • C.文档自身篇幅的长度
  • D.文档发布时间的早晚

答案:A。相关性衡量的是文档是否满足用户的查询意图,是最核心的判定。就像钓鱼比赛里“什么是好鱼”是后续一切评分的前提。B 是文档相似度,C、D 与查询意图无关。

Q2. 精确率 P@K 的计算方式是?

单选题 · easy

  • A.前 K 位中相关文档数除以 K← 正确答案
  • B.前 K 位中相关文档数除以总数
  • C.相关文档总数的算术平方根
  • D.前 K 位中不相关文档数除以 K

答案:A。P@K 的分子是前 K 条结果中相关文档的个数,分母是固定的 K,衡量“这一网捞得多纯”。B 缺少“前 K 位”范围约束,C、D 没有意义。类比钓鱼:前 10 个钓点里几条是好鱼。

Q3. MRR 最适合衡量哪类任务?

单选题 · easy

  • A.只有一个标准答案的问答← 正确答案
  • B.多级相关性的商品排序
  • C.大规模无标注文档聚类
  • D.长文本摘要的多样性

答案:A。MRR 只关心第一个正确答案的位置,适合问答、导航、FAQ 这类“只有一个标准答案”的任务。多级相关商品排序用 NDCG 更合适,聚类和摘要不属于排序评价范畴。

Q4. 若某查询唯一的相关文档排在结果第 3 位,则该查询的 RR 值是多少?

单选题 · mid

  • A.0.333← 正确答案
  • B.3.000
  • C.1.000
  • D.0.500

答案:A。RR 是第一个相关结果位置的倒数,rank = 3,所以 RR = 1/3 ≈ 0.333。第 1 位才是 1.0,第 2 位是 0.5。就像寻宝赛里第三个钓点挖到宝,得分为三分之一。

Q5. 关于 NDCG 指标,下列说法正确的是?

多选题 · mid

  • A.支持多级相关性标注← 正确答案
  • B.需要理想排序 IDCG 作分母← 正确答案
  • C.可直接跨查询比较 DCG
  • D.折损系数随位置增大而变大

答案:AB。NDCG 支持多级等级分(A 对),并且用实际 DCG 除以理想排序 IDCG 完成归一化(B 对)。C 错在 DCG 未归一化不可跨查询比较;D 错在折损系数 1/log2(i+1) 随位置增大而变小,折扣越来越大。

Q6. Average Precision(AP)的正确含义是?

单选题 · mid

  • A.每个相关文档处精确率的均值← 正确答案
  • B.每个不相关文档处召回率的均值
  • C.第一个相关文档位置的倒数
  • D.全部文档 DCG 的累加和

答案:A。AP 遍历排序列表,在每个相关文档命中位置计算一次 P@k,最后对所有相关文档取平均。B、C、D 分别混淆了召回率、MRR 和 DCG 的概念。

Q7. 关于 MAP 指标,下面说法正确的有?

多选题 · mid

  • A.对位置靠前的相关文档更敏感← 正确答案
  • B.是各查询 AP 的平均值← 正确答案
  • C.只适用于多级相关性
  • D.可直接比较不同长度的列表

答案:AB。相关文档排得越靠前,回望时的 P@k 越高,AP 越高,所以 MAP 对头部位置敏感(A 对);MAP 对所有查询的 AP 取算术平均(B 对)。MAP 通常基于二元相关性(C 错);它本身不解决列表长度差异问题,一般截断到固定长度再比(D 错)。

Q8. NDCG 中位置 i=3(从 1 开始计数)的折损权重是多少?

单选题 · hard

  • A.1/log2(4)=0.5← 正确答案
  • B.1/log2(3)=0.631
  • C.1/log2(2)=1.0
  • D.1/log2(5)=0.431

答案:A。折损权重为 1/log2(i+1),i=3 时分母是 log2(4)=2,权重为 0.5。这体现了“越靠后的结果价值衰减越狠”的设计,位置 2 的权重是 1/log2(3)≈0.631。

Q9. 实际工程中评价排序模型时,合理的做法是?

多选题 · hard

  • A.电商推荐常用 NDCG 建模多级偏好← 正确答案
  • B.问答系统常用 MRR 衡量首答效果← 正确答案
  • C.学术检索只看 P@K 不看召回率
  • D.MAP 与 NDCG 在任何场景等价

答案:AB。电商推荐有多级行为信号,适合 NDCG(A 对);问答系统只需一个答案,适合 MRR(B 对)。只盯 P@K 会忽略漏检问题(C 错);MAP 和 NDCG 假设不同,绝非处处等价(D 错)。

Q10. 某查询有 3 个相关文档,排序结果为 [相关,不相关,相关,不相关,相关],其 AP 为多少?

单选题 · extreme

  • A.0.56
  • B.0.76← 正确答案
  • C.0.96
  • D.0.26

答案:B。三位相关文档位置分别是 1、3、5,对应 P@1=1、P@3=2/3、P@5=3/5=0.6,AP=(1+0.667+0.6)/3=0.756≈0.76。B 正确。这道题考察 AP“每命中一次就回望一次精度再取平均”的本质。