想象一家大型超市里,有位金牌导购员叫“小索”。每当顾客问“有什么值得买的零食?”,她会快速从货架上取下一排商品,从最推荐到最不推荐依次摆好。老板想给她发年终奖,可怎么判断她真的摆得好?只问“第一件顾客满不满意”太片面——顾客可能一路看完五件才找到想要的,也可能想要的被漏掉了。于是老板设计了三个打分办法:第一件好货排得多靠前(MRR)、整面货架的满意程度(NDCG)、有没有把所有好货都找齐(MAP)。光在库房彩排还不够,还得真上柜台分组试岗(在线 A/B 测试),再配合顾客问卷(满意度调查)。这套组合拳,就是“搜索效果评估”。搜索系统不是冰冷的代码,它像一个每天都在面对无数顾客的导购员;而评估,就是给这个导购员立一把公正的尺子。

岗位关联

学完本节能为搜索排序、推荐系统搭建“离线指标 + 在线实验 + 用户反馈”的三层评估框架,让产品迭代有据可依,是 AI 工程师落地项目时的核心基本功之一。

目录
  1. 可视化演示
  2. 评测体系总览:老板的考核三问
  3. 离线评估基础:库房里的固定剧本彩排
  4. MRR指标:第一件好货排在第几位
  5. NDCG指标:整面货架的分级满意度
  6. MAP指标:别漏掉任何一件好货
  7. 在线A/B测试:让真顾客分组试岗
  8. 满意度调查:倾听顾客的真实心声
  9. 迭代决策闭环:从彩排到开业的持续优化
  10. AI 应用场景
  11. Python 演示
  12. 常见误区
  13. 面试题

可视化演示

展示搜索引擎MRR/NDCG/MAP排序质量指标的计算过程、NDCG位置折扣机制与A/B测试流程,交互切换排序结果查看指标变化。

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

排序质量指标计算 MRR: 首个相关结果的倒数排名 1/rank NDCG: 位置折扣增益 DCG/IDCG DCG = Σ rel_i / log2(i+1) | NDCG = DCG / IDCG 不同指标侧重不同维度:MRR关注首个命中,NDCG衡量整体排序质量,MAP适用于二值相关

评测体系总览:老板的考核三问

老板想把“小索”培养成年度最佳导购员,首先要回答三个问题:顾客要的东西她找得准不准?摆出来的货架整体顺不顺眼?有没有把好东西偷偷藏起来没拿给顾客?这三个问题,对应的正是搜索系统的三大评估目标:相关性(结果和需求是否匹配)、排序质量(好东西是否排在前面)、查全能力(相关结果是否都出现)。任何一个目标单独考核都会偏科——只问准确性,导购可能只敢拿最稳妥的一件货;只问全面性,货架上又堆满凑数商品。

于是,搜索团队把评估拆成两条路:离线评估(在实验室里用固定数据排练)和在线评估(在真实用户面前试岗)。离线评估像按剧本彩排,速度快、成本低,但剧本终归是预设的;在线评估像真实开业,能看到用户真正的点击、停留与下单行为,但干扰因素多、周期长。两条路指标各有侧重,就像彩排看“动作标准”,开业看“顾客掏钱”。

多维评估体系的价值,在于用不同的尺子量同一把排序的“质量”。离线指标负责快速筛选候选方案,在线实验负责验证真实效果,满意度调查负责倾听主观体验,三者加权融合,才能形成一条可靠的数据反馈链。

回到小索的故事:老板给她的考核表上,清清楚楚写着“准确率、货架美观度、顾客回头率”三栏。单看一栏永远有盲区,三栏一起看,才敢放心把新货架交给她。

Score=w1⋅NDCG+w2⋅CTR+w3⋅CSAT,∑wi=1\displaystyle \mathrm{Score} = w_1 \cdot \mathrm{NDCG} + w_2 \cdot \mathrm{CTR} + w_3 \cdot \mathrm{CSAT}, \quad \sum w_i = 1
综合评分 = 离线排序分 + 在线点击率 + 满意度分数的加权和,权重和为 1。用多维指标构建一张公平的“考核表”。
  1. 标准化各指标NDCG、CTR(点击率)、CSAT(满意度)量纲不同,先各自缩放到统一分值区间。
    NDCG,CTR,CSAT∈[0,1]\mathrm{NDCG}, \mathrm{CTR}, \mathrm{CSAT} \in [0, 1]
  2. 分配权重根据业务重点,给每个指标设定权重系数 $w_i$,权重之和必须等于 1。
    w1+w2+w3=1w_1 + w_2 + w_3 = 1
  3. 加权求和三项加权相加得到综合评分,分数越高代表整体效果越好。
    w1⋅NDCG+w2⋅CTR+w3⋅CSATw_1 \cdot \mathrm{NDCG} + w_2 \cdot \mathrm{CTR} + w_3 \cdot \mathrm{CSAT}

离线评估基础:库房里的固定剧本彩排

小索正式上岗前,老板递给她一本厚厚的“剧本”:上面写着一百个顾客问题,以及每个问题对应的“标准答案清单”。这就是标注数据集——由一群裁判(标注人员)提前收集真实查询,并把每条文档和查询的相关程度打好分。注意,相关程度不是简单的“对或错”,而是一把分级标尺:0 分完全无关、1 分有点相关、2 分高度相关。就像导购摆货,有的商品顾客一看就买(2 分),有的勉强凑合(1 分),有的完全不想看(0 分)。

相关性分级是整个评估体系的地基。有了这本剧本,搜索系统就可以在实验室里反复“彩排”:把查询喂给排序模型,让它输出一份结果列表,再用离线的指标公式去打分。彩排的好处是快速、便宜、可重复——任何新想法都能在几分钟内得到量化反馈,不需要打扰真实顾客。

但老板也清楚,剧本再厚,也无法覆盖真实世界的千变万化——顾客可能问出剧本里从没出现过的刁钻问题,可能今天的心情就和昨天不一样。所以离线评估只能作为第一道关:它是“初筛漏斗”,筛掉明显不合格的方案,把有潜力的方案送进下一轮真实试岗。

离线评估就像用小索在库房里对着剧本练动作,练得又快又省。可剧本终归是死的,真正的考验,永远在开业之后的真实柜台。

rel(q,d)∈{0,1,2}\mathrm{rel}(q, d) \in \{0, 1, 2\}
离线评估的核心是对每个“查询-文档”对打上 0、1、2 三级相关性标签,所有后续指标都建立在这套分级之上。
  1. 无关文档与查询完全不搭边,顾客不会多看一眼。
    rel(q,d)=0\mathrm{rel}(q, d) = 0
  2. 部分相关文档沾点边,顾客可能勉强接受。
    rel(q,d)=1\mathrm{rel}(q, d) = 1
  3. 高度相关文档正是顾客想要的,直接命中需求。
    rel(q,d)=2\mathrm{rel}(q, d) = 2

MRR指标:第一件好货排在第几位

顾客问“能去屑的洗发水有哪款?”,小索哗啦啦摆出十瓶。顾客性子急,一瓶瓶扫过去,看到第一瓶满意的就掏钱走人。这时老板关心的只有一件事:那瓶让顾客满意的洗发水,到底排在第几位? 如果排第一,皆大欢喜;如果排在第八,顾客可能早就失去耐心走了。MRR(Mean Reciprocal Rank,平均倒数排名)衡量的正是这件事。

MRR 的计算分成三步:先看每次查询中第一个相关结果出现在第几位(记为 rank),再求它的倒数(1/rank),最后把所有查询的倒数做平均。倒数有个巧妙性质:排第一名得满分 1,排第二名得 0.5,排第五名只剩 0.2——排名越靠后,分数衰减得越狠,正好模拟了“顾客耐心有限”的现实。

MRR 适合那种“用户只想找一个答案”的场景,典型如:天气查询、百科问答、导航直达、语音助手。在这些场景里,用户找到第一个满意结果就不再往下看,后面的排序再好也无意义。反过来,如果用户的意图是“想多看看再挑”,MRR 就会严重局限——它完全无视第一个相关结果之后的所有信息,哪怕后面全是好东西,或者全是一堆垃圾,它都视而不见。

老板点点头:MRR 就是考核“第一眼命中率”的尺子。对急性子顾客居多的快问快答场景,这把尺子简单又锋利;但它看不见货架深处,所以还得配别的尺子。

MRR=1∣Q∣∑q∈Q1rankq\displaystyle \mathrm{MRR} = \frac{1}{|Q|} \sum_{q \in Q} \frac{1}{\mathrm{rank}_q}
MRR = 每个查询的“首个相关结果排名倒数”的平均值。它只奖励“第一眼就命中”,容忍不了顾客的耐心。
  1. 定位首中对每个查询结果列表,从第 1 位开始逐条检查,找到第一个相关结果并记下位置。
    rankq=min⁡{i∣rel(q,di)≥1}\mathrm{rank}_q = \min\{i \mid \mathrm{rel}(q, d_i) \geq 1\}
  2. 取倒数排名越靠前,倒数越接近 1;排名越靠后,倒数急速衰减。
    1rankq\frac{1}{\mathrm{rank}_q}
  3. 跨查询平均把 |Q| 次查询的倒数加总后除以 |Q|,得到整体平均水平。
    1∣Q∣∑q∈Q1rankq\frac{1}{|Q|} \sum_{q \in Q} \frac{1}{\mathrm{rank}_q}

NDCG指标:整面货架的分级满意度

多数时候,顾客不是只买一件就走——用户逛搜索结果,可能点开三四条都觉不错,也可能前两条失望后第三条惊艳。此时老板要看的不再是“第一件”,而是整面货架的综合体验。NDCG(Normalized Discounted Cumulative Gain,归一化折损累计增益)就是给整面货架打分的尺子。

它首先给每条结果按相关性分级赋分(0/1/2),来自我们离线标注的那把标尺;然后引入位置折扣:好东西越靠前,贡献越大,越靠后,价值衰减越多。直觉上,排第三的相关结果比排第一的同样结果“更难得”——用户需要多翻两下才能发现它,所以它的分数要打个折扣。折扣用的是对数函数 $\log_2(i+1)$,温和地衰减。

接着,把打折后的分数从第 1 位一路累加到第 k 位,得到 DCG@k(折损累计增益)。但 DCG 的值受结果数量影响,不方便横向比较,于是再除以一个“神仙排序”的 DCG——假设我们事先知道所有相关性的真实分布,把结果按分数从高到低排出来的完美列表——这个理想值叫 IDCG。DCG 除以 IDCG,就得到 0 到 1 之间的 NDCG 分数。1 意味着货架和神仙排序一样完美,0.6 意味着还有不少优化空间。

NDCG 是搜索引擎里使用最频繁的离线指标之一,因为它同时照顾了“相关性”和“位置”。回到超市:它考核的是“整面货架的综合品质”——既希望每件货都让顾客满意,又希望满意的货尽量摆在显眼位置。

DCG@k=∑i=1krelilog⁡2(i+1)NDCG@k=DCG@kIDCG@k\displaystyle \mathrm{DCG}@k = \sum_{i=1}^{k} \frac{\mathrm{rel}_i}{\log_2(i+1)}\qquad\mathrm{NDCG}@k = \frac{\mathrm{DCG}@k}{\mathrm{IDCG}@k}
DCG 把每条结果的相关性分数按位置打折后累加;NDCG 再把 DCG 除以理想排序的 DCG,压缩到 0 到 1 之间,方便跨查询比较。
  1. 逐位加权的打折第 $i$ 位的结果按 $1/\log_2(i+1)$ 打折,位置越靠后,打折越狠。
    relilog⁡2(i+1)\frac{\mathrm{rel}_i}{\log_2(i+1)}
  2. 累加得 DCG把前 $k$ 位打折后的分数全部相加,体现“整面货架的累计价值”。
    DCG@k=∑i=1krelilog⁡2(i+1)\mathrm{DCG}@k = \sum_{i=1}^{k} \frac{\mathrm{rel}_i}{\log_2(i+1)}
  3. 构造理想排序把相关性分数降序排列,重复步骤 1、2 得到最大可能的累计增益。
    IDCG@k=∑i=1kreliideallog⁡2(i+1)\mathrm{IDCG}@k = \sum_{i=1}^{k} \frac{\mathrm{rel}_i^{\text{ideal}}}{\log_2(i+1)}
  4. 归一化比较实际 DCG 除以理想 DCG,比值接近 1 说明排序接近完美。
    NDCG@k=DCG@kIDCG@k\mathrm{NDCG}@k = \frac{\mathrm{DCG}@k}{\mathrm{IDCG}@k}

MAP指标:别漏掉任何一件好货

有一种顾客最让导购头疼:她说“我要买野餐用的零食,辣的、独立包装的、不贵的都要看看”。这时小索光有“第一件命中”不够,还得保证所有符合条件的好货都被找出来。MAP(Mean Average Precision,平均精确率均值)衡量的正是这种“查全”能力。

它的思想很朴素:从第 1 位往下扫描结果列表,每遇到一个相关结果,就算一次“扫描到当前位置为止的精确率”——即当前已扫过的结果里,相关结果占多大比例。把这些精确率全部加起来,除以相关结果的总数 $m$,得到 AP(Average Precision,平均精确率)。如果一个系统的相关结果全部排在最前面,AP 就会非常接近 1;要是好货稀稀拉拉散落在后排,AP 就会明显缩水。

最后,把多个查询的 AP 再取平均,就得到 MAP。MRR 只盯“第一件”,NDCG 看重“分级和位置”,MAP 则执着于“每一个相关结果是否都被公平对待”。它特别适合召回类、资料检索类场景,比如学术文献检索、专利查重、舆情监控——这类场景用户希望“一个都不能少”,漏掉关键文档比多排几条无关结果更致命。

老板记下第三条:MRR 看“首中”,NDCG 看“货架”,MAP 看“查全”。小索要想拿满分,三把尺子都得经得起量。

AP=1m∑k=1NP(k)⋅rel(k)MAP=1∣Q∣∑q∈QAPq\displaystyle \mathrm{AP} = \frac{1}{m} \sum_{k=1}^{N} P(k) \cdot \mathrm{rel}(k)\qquad\mathrm{MAP} = \frac{1}{|Q|} \sum_{q \in Q} \mathrm{AP}_q
AP 是“只在遇到相关结果的位置上统计精确率,再取平均”;MAP 则是所有查询 AP 的总体平均。
  1. 逐位计算精确率扫描到第 $k$ 位时,统计前 $k$ 位里相关结果占的比例。
    P(k)=#relevant in first kkP(k) = \frac{\#\text{relevant in first } k}{k}
  2. 仅在相关处取值$\mathrm{rel}(k)$ 是指示函数,第 $k$ 位相关取 1,不相关取 0,这样无关位置不拖后腿也不算贡献。
    P(k)⋅rel(k)P(k) \cdot \mathrm{rel}(k)
  3. 平均所有相关位把所有相关位置上的精确率累加,除以相关结果总数 $m$。
    AP=1m∑k=1NP(k)⋅rel(k)\mathrm{AP} = \frac{1}{m} \sum_{k=1}^{N} P(k) \cdot \mathrm{rel}(k)
  4. 跨查询取均值不同查询的 AP 相加后除以查询数 $|Q|$。
    MAP=1∣Q∣∑q∈QAPq\mathrm{MAP} = \frac{1}{|Q|} \sum_{q \in Q} \mathrm{AP}_q

在线A/B测试:让真顾客分组试岗

彩排再完美,也怕真实顾客不买账。老板决定玩真的:把开业日的顾客随机分成两组,一组由小索的“旧版导购流程”接待,另一组由“新版导购流程”接待,两组唯一的区别就是流程不同。这就是A/B 测试——把流量随机分组,一半走对照组(旧模型),一半走实验组(新模型),再比较两组在点击率、成交率、人均浏览时长等业务指标上的差异。

A/B 测试的威力在于“同时同地对比”:两组顾客是同一天、同一批人流量,天气、促销、节假日等干扰因素对两组一视同仁,所以指标差异可以归因于流程本身的改变。但它的陷阱也很经典:小样本的随机波动会骗人。新版点击率高了 0.5%,到底是真本事还是运气好?这就要靠统计显著性来判断——通常用 p 值作为门槛,p 值小于 0.05,我们就愿意相信差异是真实存在的。

设计 A/B 测试还有几个关键细节:样本量要足够大(太小则显著性检验没力量);实验时长要覆盖完整周期(工作日和周末用户行为差异巨大);一次只改一个变量(同时改两处,出问题无法归因);还要注意“新奇效应”——新流程刚上线时用户好奇乱点,过几天才会回归真实习惯。A/B 测试是在线评估的黄金标准,也是搜索、推荐系统上线前的最后一道闸门。

两组真实顾客的反馈,比任何彩排都更有说服力。小索的“新流程”到底行不行,老板不再凭感觉,而是让数据开口说话。

z=pA−pBp(1−p)(1nA+1nB)\displaystyle z = \frac{p_A - p_B}{\sqrt{p(1-p)\left(\frac{1}{n_A} + \frac{1}{n_B}\right)}}
这是两组点击率差异的显著性检验公式:分子是两组率之差,分母是合并标准误。z 值越大,说明差异越不可能是随机波动。
  1. 计算两组率差$p_A$、$p_B$ 分别是实验组和对照组的点击率,分子就是它们的差。
    pA−pBp_A - p_B
  2. 合并方差$p$ 是两组合并后的总体点击率,$n_A$、$n_B$ 是两组样本量,分母刻画“差值的随机波动幅度”。
    p(1−p)(1nA+1nB)\sqrt{p(1-p)\left(\frac{1}{n_A} + \frac{1}{n_B}\right)}
  3. 标准化得分差值除以标准误,z 值越大,越说明差值显著。
    z=pA−pBp(1−p)(1nA+1nB)z = \frac{p_A - p_B}{\sqrt{p(1-p)\left(\frac{1}{n_A} + \frac{1}{n_B}\right)}}

满意度调查:倾听顾客的真实心声

指标再漂亮,也替代不了顾客的一句话。有的顾客买了三件商品,临走还是皱着眉:“总感觉差点意思。” 因此老板还在收银台放了一沓调查问卷:您对本次导购服务满意吗?请打 1 到 5 星。这就是用户满意度调查,最简单的量化方式是 CSAT(Customer Satisfaction Score)——满意人数占总调查人数的比例。

满意度调查捕捉的是主观体验,它和离线指标、点击行为互为补充:NDCG 反映排序质量,点击率反映行为偏好,但用户嘴上说的和手上做的可能不一致——有人点了三四次却始终不满意,有人只看不点却心里很满意。满意度调查把“人”的声音请回评估体系,避免团队陷入“指标涨了、用户跑了”的怪圈。

除了问卷,现代搜索引擎还会收集行为信号:点击位置、停留时长、跳出率、二次搜索比例。用户搜了“洗衣机”,点开第一条结果却 3 秒就返回并重新搜索——这强烈暗示第一条结果不相关。把问卷的显性反馈和行为信号的隐性反馈融合进评估体系,就构成了指标融合:离线指标做“快筛”,A/B 测试做“实证”,满意度做“兜底”,三维合力,任何单维度的偏差都能被另外两维拉回来。

问卷就像老板亲自站在超市门口送客时的寒暄:“今天逛得开心吗?” 一句真话,往往比一百个冷冰冰的数字更有洞察力。

CSAT=满意人数调查总人数×100%\displaystyle \mathrm{CSAT} = \frac{\text{满意人数}}{\text{调查总人数}} \times 100\%
CSAT 是满意度调查最简单的统计量:直接计算给出满意评价的人数占比,直观反映用户体验。
  1. 收集评价在用户使用搜索后弹出问卷,让用户给本次体验打“满意/不满意”。
    满意人数\text{满意人数}
  2. 计算占比把满意人数除以参与调查的总人数,得到一个百分比。
    满意人数调查总人数\frac{\text{满意人数}}{\text{调查总人数}}
  3. 乘以百分百换算成百分制,方便和 NDCG、CTR 等其他指标放在同一张看板上。
    CSAT=满意人数调查总人数×100%\mathrm{CSAT} = \frac{\text{满意人数}}{\text{调查总人数}} \times 100\%

迭代决策闭环:从彩排到开业的持续优化

把小索培养成金牌导购员,老板渐渐摸索出一套固定打法——这正是搜索团队迭代的标准闭环。第一步是数据反馈:把用户真实点击、满意度问卷、搜索日志持续回流,形成新的标注数据和特征;第二步是离线初筛:新模型或新排序策略先在标注数据集上刷新 MRR、NDCG、MAP,低于当前线上阈值的直接淘汰;第三步是在线验证:通过初筛的方案进入 A/B 测试,用显著性检验确认真实收益;第四步是持续优化:上线后继续监控满意度与行为指标,发现问题再回到第一步。

这套闭环的关键在于阈值判定——绝不拍脑袋决定“上不上线”。通常设两类门槛:离线指标必须“不倒退”(新版本 NDCG 不能低于旧版本一个容忍区间),在线实验必须“显著提升”(p 值达标且业务指标为正)。两个门槛互为保险:离线过线保证方向没跑偏,在线过线保证用户真买账。曾经有团队只看离线 NDCG 大涨就全量上线,结果点击率暴跌,正是踩了“剧本与真实脱节”的坑。

多维评估的最终目的,是让每一次排序改动都有“据”可依、有“数”可查。MRR、NDCG、MAP 管住排序质量,A/B 测试管住真实效果,满意度调查管住用户情绪——三层防线共同构成搜索系统稳定迭代的决策依据,让 AI 工程师从“玄学调参”走向“科学迭代”。

老板合上考核手册,窗外小索正在给一位顾客耐心地码货。从库房彩排到开业试岗,再到顾客问卷,一套闭环让这位导购员越练越强——搜索系统,也正是在这样的循环里一天天变得更懂用户。

---

Δ=Metricnew−Metricold>ϵ\displaystyle \Delta = \mathrm{Metric}_{\text{new}} - \mathrm{Metric}_{\text{old}} > \epsilon
迭代判定的通用公式:新方案的指标减去旧方案指标,若大于容忍阈值 ε,才具备上线候选资格。
  1. 计算增量分别评测新方案与旧方案在同一指标(如 NDCG)上的值。
    Metricnew−Metricold\mathrm{Metric}_{\text{new}} - \mathrm{Metric}_{\text{old}}
  2. 设定阈值ε 是团队根据业务经验设定的最小可接受提升量,防止噪声导致的误判。
    ϵ=最低可接受提升\epsilon = \text{最低可接受提升}
  3. 比较判定增量大于 ε 才进入下一轮 A/B 验证,否则打回重做。
    Δ>ϵ\Delta > \epsilon

AI 应用场景

电商搜索排序策略迭代

阶段:模型评估与迭代优化

解决的问题:电商平台修改排序规则时,传统做法是“经验上线、出事回滚”,既冒险又低效。AI 工程师用离线指标快速筛选候选排序模型,再用 A/B 测试做最终验证,把风险挡在上线之前。

具体案例:某电商把“按销量排序”改为“相关性 + 转化倾向混合排序”。离线阶段先对比新旧方案的 NDCG,新版提升 0.05 后进入 A/B 测试;实验组点击率提升 2.3%、人均成交额提升 1.1%,p 值小于 0.01,才正式全量上线。

企业知识库检索质量体检

阶段:系统性能评估

解决的问题:企业内部知识库检索经常出现“搜不到、搜不准”的抱怨,但缺少量化证据。团队用 MAP 评估“查全”能力、用 MRR 评估“首中”能力,并结合员工满意度问卷,定位是召回环节还是排序环节出了问题。

具体案例:某公司知识库 MAP 长期低于 0.4,经诊断发现召回阶段漏掉大量相关文档。优化后 MAP 提升至 0.62,员工问卷满意度从 52% 升至 74%,内部搜索使用率翻倍。

Python 演示

python56 行
#!/usr/bin/env python3# -*- coding: utf-8 -*-"""离线搜索效果评估:MRR / NDCG / MAP 计算演示""" import math  def dcg(rels, k=None):    """计算 DCG@k,使用 log2(i+1) 做位置折扣。"""    if k is None:        k = len(rels)    return sum(rel / math.log2(i + 2) for i, rel in enumerate(rels[:k]))  def ndcg(rels, k=None):    """归一化折损累计增益:实际 DCG 除以理想排序的 DCG。"""    ideal = sorted(rels, reverse=True)    return dcg(rels, k) / dcg(ideal, k)  def mrr(ranks):    """MRR:各查询首个相关结果排名的倒数取平均。"""    return sum(1.0 / r for r in ranks) / len(ranks)  def average_precision(rels):    """AP:在每个相关位置统计精确率,再对所有相关结果取平均。"""    hits = 0    total = 0.0    for i, rel in enumerate(rels, start=1):        if rel >= 1:            hits += 1            total += hits / i    return total / hits if hits else 0.0  def map_score(queries):    """MAP:所有查询 AP 的均值。"""    return sum(average_precision(q) for q in queries) / len(queries)  if __name__ == "__main__":    # 每个查询的 10 条结果,相关性分级:0 无关 / 1 相关 / 2 高度相关    queries = [        [0, 2, 1, 0, 2, 1, 0, 2, 1, 0],        [2, 0, 0, 1, 0, 2, 1, 0, 0, 1],        [1, 2, 0, 0, 1, 0, 2, 2, 0, 0],    ]    ranks = []    for q in queries:        ranks.append(next(i for i, rel in enumerate(q, start=1) if rel >= 1))    print("首个相关结果排名:", ranks)    print("MRR = %.3f" % mrr(ranks))    for i, q in enumerate(queries, start=1):        print("Query%d NDCG@10 = %.3f | AP = %.3f" % (i, ndcg(q), average_precision(q)))    print("MAP = %.3f" % map_score(queries))
目的:实现排序质量三大离线指标——MRR、NDCG、MAP 的完整计算,可直接用于评估搜索引擎或推荐系统的排序结果。
  1. def dcg(rels, k=None):用列表切片 rels[:k] 支持只算前 k 位,math.log2(i + 2) 对应公式中的 $\log_2(i+1)$ 折扣。
  2. ideal = sorted(rels, reverse=True)把相关性分数降序排列,构造“神仙排序”,用于归一化。
  3. return sum(1.0 / r for r in ranks) / len(ranks)对首个相关结果的排名取倒数后求平均,正是 MRR 的定义。
  4. hits += 1; total += hits / i每遇到相关结果就累加当前精确率,最后除以总命中数得到 AP。
  5. ranks.append(next(i for i, rel in enumerate(q, start=1) if rel >= 1))高效查找每个查询首个相关结果的排名位置。
  6. print("MRR = %.3f" % mrr(ranks))用 %.3f 保留三位小数打印,方便把指标贴进实验报告。

常见误区

误区很多人刚入门时认为 MRR 就是搜索评估的全部——看第一个相关结果排在哪就行,后面的根本不用管。

正解MRR 只照顾“首中”场景,对浏览型、对比型用户毫无区分度。就像考核导购只问“顾客第一眼看中的货卖出去没”,完全不关心顾客挑了五件才满意的情况。综合搜索、商品推荐等场景必须配合 NDCG、MAP 才能看清全貌。

为何常见:因为 MRR 最简单、最容易讲给人听,学习者容易把“上手最快”误当成“覆盖最全”。

误区有些人把相关性和“是否点击”混为一谈,只用 0/1 二分法给结果打分,还觉得 NDCG 已经算得很准。

正解NDCG 的价值恰恰建立在多级相关性之上。一个 2 分的“高度相关”结果和一个 1 分的“勉强相关”结果,在折扣累加中贡献完全不同。全用 0/1 会丢掉大量排序质量信息,相当于老板只问顾客“买没买”,不问“满不满意”。

为何常见:二分法标注成本低、看起来“够用”,初学者容易忽略分级标注对指标敏感度的影响。

误区不少团队在离线数据集上看到 NDCG 大涨,就迫不及待全量上线,结果真实点击率反而下降。

正解离线剧本是标注人员预设的,无法覆盖真实用户的多样性和环境变化。离线指标只适合当“初筛漏斗”,上线前必须经过 A/B 测试验证显著性。就像彩排动作再标准,开业时顾客不买账也是白搭。

为何常见:离线评估快、成本低、数字漂亮,容易让人产生“可控的才是真实的”错觉。

误区有人把新版本上线跑了两天,看到点击率提升 0.5% 就激动地宣布实验成功。

正解小样本下的波动极具欺骗性,必须检查统计显著性(p 值)、样本量、实验周期是否覆盖完整业务周期。还要警惕“新奇效应”——用户一时好奇点得多,不代表长期习惯。真正可靠的结论需要足够的样本和预先设定的显著水平来支撑。

为何常见:人们天然倾向于快速得出“有效”的结论,统计检验的等待过程让人焦虑,于是有意识忽略随机波动。

面试题

Q1. MRR 的核心计算对象是什么?

单选题 · easy

  • A.所有相关结果的平均排名位置
  • B.首个相关结果的排名倒数← 正确答案
  • C.相关结果按位置的加权累计
  • D.理想排序与实际排序的比值

答案:B。MRR 只关心每个查询中第一个相关结果的排名倒数,排第 2 就得 1/2。选项 A 混淆了 AP,选项 C 更像 DCG 的思想,选项 D 是 NDCG 的归一化思路。就像老板只看“顾客第一眼相中的货在第几排”。

Q2. NDCG 中“归一化”指的是什么操作?

单选题 · easy

  • A.把所有分数缩放到零到一区间
  • B.除以理想排序下的 DCG 值← 正确答案
  • C.除以查询总数得到平均值
  • D.用 Sigmoid 函数压缩分数

答案:B。NDCG 的归一化是指把实际 DCG 除以 IDCG(理想排序的 DCG),从而让不同查询的结果可比较。选项 A 是广义概念但不够准确,选项 C 是 MAP 的做法,选项 D 与 NDCG 无关。

Q3. 用户只想快速获得“一个正确答案”(如天气查询),应优先关注哪个指标?

单选题 · mid

  • A.MAP
  • B.CSAT
  • C.MRR← 正确答案
  • D.NDCG

答案:C。问答式场景下用户找到第一个满意答案就离开,MRR 专门衡量“首中”能力。MAP 关心查全,NDCG 关心整体货架质量,CSAT 是满意度调查,都不是首中场景的第一优先级。

Q4. NDCG 的位置折扣采用哪种衰减形式?

单选题 · mid

  • A.线性线性衰减不衰减
  • B.指数衰减每后一位减半
  • C.对数衰减按 log2(i+1)← 正确答案
  • D.完全不考虑位置差异

答案:C。NDCG 的折扣项是 $1/\log_2(i+1)$,属于温和的对数衰减:第 2 位折损到 0.63、第 3 位到 0.5。它不像指数衰减那么激进,符合“用户愿意多翻几页但耐心有限”的真实行为。

Q5. 计算 AP 时,分母中的 m 表示什么?

单选题 · mid

  • A.查询结果的总条数
  • B.该查询中相关结果的总数← 正确答案
  • C.参与评估的用户数量
  • D.点击事件的累计次数

答案:B。AP 的分母 m 是该查询里所有相关结果的数量。它把每个相关位置上的精确率加总后除以 m,衡量系统是否把所有相关结果都排得靠前。选项 A 描述列表长度,C 是 A/B 测试概念,D 是行为信号概念。

Q6. 离线评估与在线测试的正确关系是?

单选题 · mid

  • A.离线通过即可直接上线
  • B.离线负责初筛在线最终验证← 正确答案
  • C.在线测试不如离线评估重要
  • D.两种方式只需选择其一

答案:B。离线评估快而廉价,适合大批量筛选候选方案;A/B 测试真实但昂贵,适合对少数优胜方案做最终裁决。两者是“漏斗”的上下游关系,不能互相替代。选项 A 忽略了真实用户与标注数据的差异。

Q7. A/B 测试中“统计显著性”主要用来判断什么?

单选题 · hard

  • A.新版本运行时间是否足够长
  • B.指标差异是真实还是随机波动← 正确答案
  • C.参与实验的用户数是否够多
  • D.新版本代码是否存在语法错误

答案:B。显著性检验回答“这个差值有多大概率是运气”——p 值小于阈值(通常 0.05)时,我们才愿意相信差异是方案带来的真实效果。样本量和实验时长只是影响显著性的因素,代码正确性则与统计推断无关。

Q8. 下列哪些属于排序质量的离线评估指标?

多选题 · easy

  • A.MRR 指标← 正确答案
  • B.NDCG 指标← 正确答案
  • C.顾客满意度问卷
  • D.MAP 指标← 正确答案

答案:ABD。MRR、NDCG、MAP 都是基于标注数据集计算的离线排序指标,分别侧重首中、全局折损、查全。满意度问卷属于在线用户反馈,不属于离线指标。

Q9. 完整的多维评估体系通常包含哪些层面?

多选题 · mid

  • A.离线排序指标评测← 正确答案
  • B.在线 A/B 实验验证← 正确答案
  • C.用户满意度调查← 正确答案
  • D.服务器硬件温度监控

答案:ABC。三层评估体系=离线快筛(MRR/NDCG/MAP)+ 在线实证(A/B 测试)+ 主观反馈(满意度问卷),三者互相校验。服务器温度属于运维范畴,与搜索效果评估无关。

Q10. 离线 NDCG 显著提升,但 A/B 测试不显著,可能的原因有哪些?

多选题 · hard

  • A.实验样本量不足← 正确答案
  • B.标注与真实偏好不一致← 正确答案
  • C.新版本代码存在缺陷
  • D.线上流量波动等干扰← 正确答案

答案:ABD。样本量不足会让显著性检验失去力量;离线标注代表“裁判的偏好”,可能与真实用户不一致;线上环境的流量波动、季节性因素也会干扰结论。选项 C 若成立会直接在线上反映为更差,而不是“不显著”。