「搜味斋」是城里生意最红火的一家餐厅。老板苏索有个习惯:每天打烊后,他都要把当天的问题记在本子上——新推的招牌菜客人点得多不多?服务员传菜快不快?客人吃完是笑着走还是皱着眉走? 可有一天,主厨老周端出一道「清蒸榴莲」,苏索觉得自己尝了一口味道还不错,于是信心满满写上菜单。结果一周后,这道菜几乎无人问津,甚至有客人给了差评,说「厨房是不是把垃圾倒进了锅里」。 苏索这才意识到一个问题:「我觉得好」和「客人觉得好」是两回事;而「客人嘴上说好」和「客人真的再来」更是两回事。 他需要一个科学的评鉴体系,来回答三个层层递进的问题:这道菜本身做得对不对?端上桌客人买不买单?客人吃完愿不愿意再来? 搜索引擎的世界里,同样的问题每天都在发生。算法工程师改了一版排序代码,在本地试了试觉得「很不错」,可一上线用户却纷纷流失。怎么科学地衡量一套搜索系统到底好不好?答案,就藏在一套从「离线指标」到「在线 AB 测试」再到「用户满意度」的完整评估体系里。今天,我们就跟着「搜味斋」的评鉴之路,把搜索评估体系彻底弄明白。
对于搜索产品经理、算法评估工程师和数据科学家而言,评估体系是「度量决策依据」的核心能力——掌握它,你才能用数据说服团队、用指标驱动搜索体验持续进化。
可视化演示
展示FCFS与SSTF磁盘调度算法的磁头移动过程:逐步处理I/O请求队列,观察磁头寻道轨迹与总移动距离。
本节配有交互动效(进入视口后自动加载,约 3KB)。
FCFS磁盘调度 先来先服务:按请求队列顺序依次寻道,简单但效率低 seek = |head - request| 青色圆点为磁头位置,线段为移动轨迹
评估体系总览
苏索痛定思痛,给自己搭了一套「三层评鉴楼」。一楼是后厨自检:每道菜出锅前,大厨按菜谱标准抽样试吃,调料比例对不对、火候到不到位,这叫「离线评估」——菜还没端出去,先在厨房把关。二楼是试营业盲测:新菜先不给所有人吃,随机挑几桌客人尝尝,和招牌老菜暗中比一比,这叫「在线评估」。三楼是老顾客回访:问他们最近还来不来、愿不愿意推荐给朋友,这叫「用户满意度」。
技术世界里,这套三层楼分别对应搜索评估体系的三个层次:离线评估(离线指标)、在线评估(在线 AB 测试)、满意度评估(用户满意度度量)。离线评估在系统上线前运行,用历史评测集计算相关性和覆盖率;在线评估在真实流量中运行,用实验对比新旧算法的效果;满意度评估则持续追踪用户的长期行为与主观反馈。
三层楼的逻辑关系可以用一个加权公式表达——综合体验由多个维度共同决定:
回到搜味斋——苏索发现,只在一楼试菜远远不够。「清蒸榴莲」后厨试吃明明达标了,客人就是不买账。于是他决定上二楼:把新菜端给一部分客人试吃,用数据说话。
- 权重 $w_i$$w_1$ 到 $w_4$ 是各维度的权重系数,由产品目标决定,比如购物搜索会给相关性更高的权重。
- 相关性衡量搜索结果与查询词的匹配程度,是「菜对不对味」的核心指标。
- 覆盖率衡量搜索系统能回答多少类型的查询,是「菜单全不全」的体现。
- 效率与满意度效率指响应速度,满意度是用户主观好恶的综合体现,两者共同构成体验闭环。
评测集构建
二楼实验需要一套「品鉴工具」。搜味斋专门成立了一个品鉴委员会:先列出顾客最常点的 200 道菜(高频查询),再补充一些偏门菜(长尾查询),形成一份标准菜单;每道菜对应 3 份不同来源的备选食材(文档池);每位品鉴员按「非常好吃、还行、一般、难吃」四个等级独立打分。
搜索领域的「品鉴工具」就是评测集(Evaluation Set)。构建评测集有四个关键步骤:Query 采样、文档池构建、相关性标注、标注质量控制。Query 采样要求既覆盖高频头部查询,也覆盖长尾查询,否则评测集会有偏;文档池需要从多个来源汇总候选文档,保证每个查询都有充分的候选项;标注则由人工根据规范打分。
人工标注最大的风险是「同一道菜,两个人说两个味」。品鉴委员会需要量化标注者之间的一致性——这就是 Kappa 系数:
苏索规定:品鉴员的 $\kappa$ 系数低于 0.6 就必须重新培训。评测集打磨好了,下一步就是用这套「标准菜单」给每道菜打分——这就是相关性评估。
- 观察一致率 $P_o$两位标注员对同一批样本给出相同评分的比例,数值越大说明实际越一致。
- 随机一致率 $P_e$假设两人完全随机打分时会碰巧一致的概率,由各类别占比计算得出。
- Kappa 计算用实际一致率减去随机一致率,再除以「除随机外可能达到的最大一致率」,得到剔除运气后的真实一致性。
相关性评估
品鉴委员会拿到标准菜单后,开始系统性试菜。他们不看摆盘不看价格,只盯一个核心问题:这道菜和菜单描述的匹配度如何?每位品鉴员给出 0 到 3 的等级分——3 分是「惊艳,完全就是顾客想要的味道」,0 分是「完全跑题,甚至让人反胃」。
搜索引擎中的相关性评估正是如此。标注员对「查询-文档」对打分级分,常见尺度是 0-3 四级。但光有分级分还不够——同样的 3 分文档,排在第一位和排在第十位,对用户体验的影响天差地别。于是需要 DCG(折损累积增益) 来量化「好的结果越靠前越好」:
其中 $rel_i$ 是第 $i$ 条结果的相关等级分。但 DCG 的绝对值没有统一的「及格线」,不同查询的结果数量不同,没法直接横向比较。于是引入「理想排序」作为参照系,得到 NDCG(归一化折损累积增益):
除了排序质量,评估者还关心另一个问题:相关的文档到底找回来几条? 有的系统排得准但漏得多——就像菜单上写着「红烧肉」,后厨实际只有一道不地道的替代品,这就要用 MAP(平均精确率均值) 来度量:
品鉴委员会忙了一个月,终于用 NDCG 和 MAP 给每道菜打完了分。可苏索翻着报告,又发现一个新问题:「有些菜咱们做得挺好,但菜单上根本没有——客人想点的时候,搜都搜不到!」
- 精确率 $P_q(i)$第 $i$ 个位置前的搜索结果中,相关结果所占的比例——你捞上来的鱼里,真鱼占几成。
- 相关标记 $rel_{q,i}$第 $q$ 个查询的第 $i$ 条结果是否相关(1 表示相关,0 表示不相关),只累加相关位置的精确率。
- AP 平均对单个查询把所有相关位置的精确率取平均,$R_q$ 是该查询的相关文档总数。
- MAP 全查询平均把所有查询的 AP 再做一次平均,得到系统全局的查全与查准综合分。
覆盖率评估
苏索让服务员统计了三天内顾客的「点菜失败」记录:有 8 位客人想点「椒盐皮皮虾」,菜单上没有;有 5 位客人问「有没有低脂甜品」,后厨一头雾水。这些菜做得好不好暂且不论,连上菜单的机会都没有,再好吃也白搭。这个「菜单会不会漏掉客人想点的菜」的问题,就是搜索里的覆盖率评估。
覆盖率衡量搜索系统「搜得到」的能力,是相关性的前提。常见指标有三类:搜索覆盖率——有多少比例的查询能返回非空结果;集合覆盖率——返回的结果文档在整个文档库中占多大比例;点击覆盖率——有多少查询的搜索结果被用户真正点击过。两类核心公式如下:
苏索拿着覆盖率报告开会:「咱们菜单覆盖面太窄,长尾需求全漏掉了。」于是厨师团队开始丰富菜品线。可就在这个节骨眼上,主厨老周端来一道改进版「清蒸榴莲」,拍胸脯保证这次一定行。苏索吸取教训:不上全菜单,先搞一场盲测对比实验。
- 分子非空结果查询数:统计评测集中返回了至少一条结果的查询数量——「菜单上能找到的菜」的数目。
- 分母查询总数:评测集中全部查询的数量,包括高频和长尾。
- 集合覆盖率的并集把所有查询返回的结果文档合并去重,除以文档库总量 $|D|$,衡量系统能触达多大范围的资源。
在线AB测试
「清蒸榴莲 2.0」要上场了。苏索安排店里的迎宾员把客人随机分成两组:A 组客人拿到的新菜单上印着这道菜,B 组客人拿到的是老菜单。一周下来,对比两组的「点单率」和「退菜率」,看看新菜到底行不行。这就好比搜索引擎的 AB 测试:把线上流量随机切分为实验组和对照组,一组用新算法,一组用旧算法,在真实用户行为中验证效果差异。
AB 测试的核心不是「看谁数字大」,而是「数字差异是否可信」。A 组点单率 12%,B 组点单率 10%,这 2% 的差距是真实差异,还是随机波动?这要用假设检验来回答——先假设「新菜没有更好」(零假设),再计算当前数据与这个假设的冲突程度。常用的检验统计量是 z 值:
盲测实验跑了两周,数据出来了:A 组点单率显著更高,z = 2.3,p = 0.021,「清蒸榴莲 2.0」终于获得转正资格。但苏索没有被短期数据冲昏头脑——他掏出会员系统的记录,开始查一个更关键的指标:吃过新菜的客人,一个月后还来不来?
- 组间均值差 $\bar{x}_A - \bar{x}_B$两组指标的平均值之差,比如 A 组点单率 12%,B 组 10%,差值为 2%。
- 方差 $s_A^2, s_B^2$各组内部的方差,反映组内用户的个体差异——客人口味越杂,方差越大。
- 样本量 $n_A, n_B$两组的人数。样本量越大,均值估计越稳定,分母越小,z 值越大。
- 标准误分母将两组的方差按样本量加权合并再开方,得到「均值差异的波动幅度」,作为差异的标尺。
用户满意度
任何餐厅的终极考卷,不是开业第一周的热闹,而是三个月后的上座率。「清蒸榴莲 2.0」上线一个月,点单率确实不低,但苏索发现一个奇怪的现象:复购率在悄悄下滑。有些客人尝鲜之后,就再也不点这道菜了。这说明短期行为指标好,不代表长期体验满意——搜索引擎也是如此。
用户满意度评估是评估体系的最高层,常用的度量方式包括:满意度调研(直接问用户「这次搜索满意吗」)、行为信号度量(通过点击时长、跳出率、二次搜索率等行为推断满意程度)、留存率指标(用户是否持续回访)。综合这些信号,可以构建一个加权满意度指标 SUP(Satisfaction of User Product):
三个月后,搜味斋的复盘报告出炉:相关性、覆盖率、AB 实验、满意度四个维度的数据终于对上了。苏索把这份「评鉴体系」写进了餐厅章程——从今往后,每一道新菜都必须过五关斩六将:评测集打分、覆盖率检查、AB 盲测、留存验证,全部通过才能上菜单。搜索引擎的评估体系,亦是如此。
- 留存 $留存_u$用户 $u$ 在一段时间后仍回来使用搜索的比率,是「回头客」的数字化表达。
- 好评 $好评_u$用户主动给出的满意度评价,来自问卷或 App 内的评价入口,代表「嘴上说好」。
- 良好交互 $良好交互_u$由搜索行为推断的隐性满意度,比如无跳出、点击后停留时间长、无快速返修。
- 加权求和与平均$\alpha, \beta, \gamma$ 是权重,对全体用户 $U$ 求平均,得到系统级满意度分。
AI 应用场景
电商搜索排序模型上线评估
阶段:离线评估阶段
解决的问题:电商平台每天有数亿次搜索,排序模型迭代频繁。传统方式是「上新之后看销量」,但销量受价格、促销、季节多重干扰,无法反映排序本身的好坏。AI 评估方式是在评测集上离线计算 NDCG@10,模型分数不达标直接不放入候选,避免劣质模型浪费线上流量。
具体案例:某电商平台构建了 20 万条「查询-商品」评测集,三级标注(相关/弱相关/不相关)。新模型在评测集上 NDCG@10 从 0.62 提升到 0.65 才获准进入 AB 测试,上线后点击率提升 3.2%,退货率下降 1.1%。
新闻资讯搜索的在线 AB 实验
阶段:在线评估阶段
解决的问题:新闻搜索需要实时适应热点,离线评测集滞后于真实热点。传统方式是只凭感觉上线新模型,结果难以归因。AI 方式是将流量按用户 ID 哈希随机切分,实验组使用新排序模型,对照组使用旧模型,用 z 检验判断点击率、阅读时长的差异显著性,并设置最短实验时长与异常监控。
具体案例:某新闻 App 对「热点召回增强」策略做 AB 实验,分配 10% 流量跑 7 天,样本量 n=50 万,点击率提升 0.8%,z=2.1,p=0.035,确认显著后全量上线。
企业知识库搜索满意度监控
阶段:满意度评估阶段
解决的问题:企业内部知识库搜索「搜得到但没人用」,传统评估只关注功能使用量,忽略了体验。AI 方式构建 SUP 满意度指标,融合次日留存、主动好评、零二次搜索比例三个信号,形成每日监控看板,异常波动自动告警。
具体案例:某公司知识库搜索上线 SUP 看板后,发现某次升级后「零二次搜索比例」从 0.7 暴跌至 0.45,定位到相关性 bug,回滚后三天内指标恢复——如果没有满意度监控,这个 bug 可能潜伏一个月。
Python 演示
import math def dcg(relevance, k): """计算 DCG@k:位置越靠前,增益折损越小。""" score = 0.0 for i in range(min(k, len(relevance))): gain = (2 ** relevance[i] - 1) / math.log2(i + 2) score += gain return score def ndcg(relevance, k): """计算 NDCG@k:实际排序增益 / 理想排序增益。""" ideal = sorted(relevance, reverse=True) idcg = dcg(ideal, k) if idcg == 0: return 0.0 return dcg(relevance, k) / idcg def average_precision(relevance): """计算单个查询的 AP:只累加相关位置的精确率。""" hit = 0 sum_prec = 0.0 for idx, rel in enumerate(relevance, 1): if rel > 0: hit += 1 sum_prec += hit / idx return sum_prec / hit if hit > 0 else 0.0 def map_score(query_results): """计算 MAP:所有查询 AP 的平均值。""" return sum(average_precision(r) for r in query_results) / len(query_results) def main(): query1 = [3, 2, 0, 1, 2] query2 = [2, 3, 1, 0, 2] for k in (1, 3, 5): print("query1 NDCG@{} = {:.4f}".format(k, ndcg(query1, k))) print("query1 AP = {:.4f}".format(average_precision(query1))) print("query2 AP = {:.4f}".format(average_precision(query2))) print("MAP = {:.4f}".format(map_score([query1, query2]))) if __name__ == "__main__": main()
gain = (2 ** relevance[i] - 1) / math.log2(i + 2)每一条结果的增益按指数映射,再除以位置折扣;位置从 1 开始,所以分母用 i+2。ideal = sorted(relevance, reverse=True)把相关性等级降序排列,得到「理想排序」,作为归一化的满分参考答案。return dcg(relevance, k) / idcg实际增益除以理想增益,得到 0 到 1 的 NDCG 值,1 表示排序完美。if rel > 0: hit += 1; sum_prec += hit / idx每次遇到相关文档,就记录当前位置的精确率;hit 是已见相关文档数。sum_prec / hit if hit > 0 else 0.0用相关文档总数做平均,得到 AP;如果没有相关文档,AP 记 0 避免除零。
常见误区
误区「NDCG 是评估搜索最重要的指标,只要把 NDCG 刷高,搜索质量就上去了。」
正解这就像只考核菜做得好不好吃,却不管菜单上有没有客人想点的菜。NDCG 衡量的前提是「结果已经返回」,如果系统对 40% 的查询直接返回空结果,那 NDCG 再高也毫无意义。真实评估必须把覆盖率当作前置门槛:先保证「搜得到」,再优化「排得好」。
为何常见:NDCG 有明确公式、可复现、好汇报,而覆盖率听起来「不那么技术」,容易被汇报导向的团队忽略。
误区「离线评测集上 NDCG 提升了 0.05,上线肯定能涨点击率。」
正解离线评测集是「后厨试菜」,在线流量是「真实客人用餐」。评测集标注与真实用户兴趣存在偏差,且离线无法捕捉位置偏差、审美偏好、时效性等因素。历史上多次出现离线涨、在线跌的案例。正确做法是离线筛选 + AB 测试验证双保险。
为何常见:离线计算成本低、速度快,人们天然倾向于相信「可复现的胜利」,忽略了评测集与真实分布的鸿沟。
误区「实验组 CTR 比对照组高了 0.5%,统计显著,立刻全量上线!」
正解这就像餐厅盲测只做了一个午餐时段就宣布新菜获胜。一天的数据存在星期效应、时段波动、新客老客比例失衡。正确的 AB 测试要覆盖至少一个完整业务周期(如 7 天),同时监控 p 值之外的「新奇效应」——用户可能只是因为新鲜感才多点了两下。
为何常见:等待是对耐心的考验,而「快速出结果」在汇报文化中极具诱惑力,导致实验时长被人为压缩。
误区「评测集标注了几十万条,数据量大就是权威。」
正解如果标注员之间一致性差,数据量再大也是一堆噪声。就像品鉴团 20 个人对同一道菜打出 20 种分数,这份「权威测评」毫无参考价值。正确做法是先小批量试标,用 Kappa 系数验证一致性,低于阈值就重新对齐标注规范,再大规模铺开。
为何常见:数据量是显性资产,标注质量是隐性资产——汇报 PPT 上「50 万条标注」比「kappa=0.83」好看得多。
误区「新算法模型在离线评测集上表现优秀,直接全量上线,让所有用户体验新版本。」
正解这等于不盲测就把「清蒸榴莲」印在全城菜单上。没有对照组的全量上线,任何指标波动都无法归因,出了问题连回滚参照都没有。科学的做法是 5%-10% 小流量实验,验证显著后再逐步放量,全程保留对照组和回滚通道。
为何常见:对新模型的「自信」和对上线速度的追求,让团队跳过了风险控制步骤。
面试题
Q1. 在 NDCG 指标中,IDCG 代表什么?
- A.理想排序下的 DCG 值← 正确答案
- B.实际排序下的 DCG 值
- C.随机排序下的 DCG 值
- D.平均排序下的 DCG 值
答案:A。IDCG 是 Ideal DCG 的缩写,指把文档按相关度从高到低排序后计算出的理想 DCG 值,作为归一化的满分参照。实际 DCG 除以 IDCG 才得到 0 到 1 的 NDCG。其他选项描述的都是非理想状态下的 DCG,不符合 IDCG 定义。
Q2. 以下哪项属于离线评估指标?
- A.线上流量 A/B 实验
- B.评测集上的 NDCG← 正确答案
- C.用户次日留存率
- D.搜索点击热力图
答案:B。离线评估是指系统上线前在固定评测集上计算的指标,NDCG、MAP、覆盖率都属于离线指标。A/B 实验是在线评估,留存率和点击热力图属于真实用户行为,均依赖线上环境,不属于离线范畴。
Q3. DCG 公式中分母 log2(i+1) 的语义是什么?
- A.放大靠后结果位置的贡献
- B.降低靠后结果位置的贡献← 正确答案
- C.消除搜索词长度的影响
- D.消除标注者风格的影响
答案:B。log2(i+1) 是位置折扣项,位置 i 越靠后,对数值越大,增益被削得越多。它模拟用户「只看前几屏」的行为:排第三的结果比排第一的结果价值低得多。它对所有位置一律按秩折损,与搜索词长度、标注者风格无关,因此 C、D 错误,A 与折扣方向相反。
Q4. 关于 MAP 与 NDCG 的说法,正确的是哪项?
- A.MAP 不依赖查询集合
- B.NDCG 需要理想排序做归一化← 正确答案
- C.MAP 完全忽略相关文档数
- D.两种指标考察同一个维度
答案:B。NDCG 的核心是用理想排序的 DCG 做分母归一化,因此 B 正确。MAP 依赖于查询集合中相关文档的数量,A、C 错误。MAP 侧重查全与查准的综合,NDCG 侧重排序位置的加权质量,两者维度不同,D 错误。
Q5. 覆盖率指标主要回答以下哪个问题?
- A.单一查询的结果质量如何
- B.系统能覆盖多大范围的查询和文档← 正确答案
- C.搜索结果排序是否完全正确
- D.标注者之间的意见是否一致
答案:B。覆盖率衡量「搜得到」的能力,包括搜索覆盖率(多少查询有结果)和集合覆盖率(返回的文档覆盖库中多大比例)。A 是相关性的问题,C 是排序质量的问题,D 是标注一致性的问题,均不属于覆盖率的研究范畴。
Q6. Kappa 系数的取值接近 1 时,说明什么?
- A.标注者意见完全对立
- B.标注者一致性显著高于随机水平← 正确答案
- C.标注样本数量一定非常大
- D.标注任务的难度极大
答案:B。Kappa 系数的计算方式是 (Po - Pe)/(1 - Pe),它剔除了随机一致性 Pe。当值接近 1 时,意味着标注者的实际一致率远高于碰巧一致的概率,说明标注规范清晰、执行到位。它不反映样本量或任务难度,A 的方向完全相反。
Q7. 在线 AB 测试中,p 值小于 0.05 通常意味着什么?
- A.实验组指标必定远远优于对照组
- B.差异由偶然因素导致的概率不足 5%← 正确答案
- C.实验组样本量一定大于对照组
- D.实验可以立刻全量上线无需复测
答案:B。p 值指在原假设为真的前提下,观察到当前差异的概率。p < 0.05 表明差异很可能是真实效应而非随机波动,但并不意味着「必定远远优于」或可以跳过复测。样本量大小与 p 值无必然因果关系,因此 A、C、D 错误。
Q8. 以下哪些属于 AB 测试上线前的合理防护机制?
- A.预留部分流量作为对照组← 正确答案
- B.设定最短实验观测时长← 正确答案
- C.出现显著立即全量上线
- D.监控异常指标并准备回滚← 正确答案
答案:ABD。AB 测试必须保留对照组(A),设定足够长的观测周期以消除时段效应(B),同时建立异常监控和回滚机制(D)。C 是典型错误操作——即使在统计上显著,也需要观察新奇效应衰减和长周期稳定性,不能立即全量。
Q9. 构建搜索评测集时,合理的做法包括哪些?
- A.均匀覆盖高频查询与长尾查询← 正确答案
- B.只挑选容易标注的查询
- C.多轮标注并计算一致性← 正确答案
- D.文档池覆盖多种来源← 正确答案
答案:ACD。评测集要有代表性,需均衡覆盖高频和长尾查询(A),文档池要多样以确保候选充分(D),并通过多轮标注计算 Kappa 控制质量(C)。B 是错误做法——只选容易标注的查询会让评测集失真,低估真实线上的长尾难度。
Q10. 以下哪些信号可纳入用户满意度综合指标?
- A.用户次日留存比率← 正确答案
- B.用户主动好评比率← 正确答案
- C.点击后停留时长信号← 正确答案
- D.服务器平均响应延迟
答案:ABC。SUP 综合指标融合留存(A)、好评(B)、良好交互(C)三类证据,分别代表「离不开」「说你好」「用得好」。服务器响应延迟属于效率指标而非满意度信号,在综合评估体系中一般单独建模,因此 D 不属于满意度度量的范畴。