想象你走进一家拥有三千道菜的大餐厅,对服务员说:“帮我推荐几道清淡的菜。”合格的服务员绝不会把菜单从头到尾念一遍——那是检索召回;也不会只挑菜名里带“清淡”二字的菜——那是字面匹配,因为“清蒸鱼”里压根没有“清淡”这两个字。她会综合菜名、食材、口碑、顾客历史偏好,在几秒内排出三道最合适的菜,还排好先后顺序。搜索引擎每天都在做同样的事:从海量网页中选出最相关的结果并排好顺序,这门手艺叫相关性排序。本文借用“金牌服务员点菜”的故事,从 BM25 文本匹配、多因子特征、学习排序、NDCG 评估一路讲到语义排序优化,带你理解搜索引擎如何把“猜你心意”变成一门可度量、可迭代的工程学问。

岗位关联

相关性排序是搜索、推荐、广告等一切“排序型”AI 应用的底层必修课。掌握特征设计、学习排序与离线评估方法论,可直接复用到电商、知识库等场景,也是大厂搜索算法岗的核心考点。

目录
  1. 可视化演示
  2. 排序问题本质
  3. BM25文本匹配
  4. 多因子特征工程
  5. 学习排序模型
  6. NDCG离线评估
  7. 语义排序优化
  8. AI 应用场景
  9. Python 演示
  10. 常见误区
  11. 面试题

可视化演示

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

排序问题本质

顾客对服务员说“来点清淡的”,服务员脑子里瞬间闪过几道候选菜,但她不会把候选一股脑端上桌,而是先想清楚每道菜“合不合适”,再排一个先后顺序端出去。这道“想清楚再排序”的动作,正是搜索引擎里最核心的环节——相关性排序。

一次搜索分两步:召回(recall)先从亿级网页中快速筛出几百个“看起来相关”的候选,只求不漏;排序(ranking)再对这几个候选精细打分、排出先后。用户几乎只看前一两页,第 3 名和第 300 名的命运天差地别。可以说,排序质量直接定义了搜索引擎的口碑。

抽象来看,排序系统就是一个打分函数 Score(q,d):给定查询 q 和文档 d,输出一个实数分数,全体文档按分数降序排列得到结果列表。衡量“相关”的高与低,既要看文档是否覆盖了查询主题,也要看它是否满足用户当下的真实意图。

服务员给每道菜打“合适分”再排序,搜索引擎给每个网页打“相关分”再排序。后面的 BM25、多因子特征、学习排序、语义匹配,全都是为了让这个分数打得更准。想清楚“打分”这件事,就抓住了排序的命门。

Score(q,d)∈R,di 排在 dj 前  ⟺  Score(q,di)>Score(q,dj)\displaystyle \text{Score}(q, d) \in \mathbb{R}, \qquad d_i \text{ 排在 } d_j \text{ 前} \iff \text{Score}(q, d_i) > \text{Score}(q, d_j)
这个公式说明:排序的本质不是“算出一个有意义的分值”,而是“保证分数大小能反映相关程度的先后”。分数可以是任意实数,只要相对大小稳定即可。
  1. 打分函数输入是查询与文档的配对,输出一个可以比较的数值,数值越大表示越相关。
    Score(q,d)\text{Score}(q, d)
  2. 实数域取值分数本身不需要绝对意义,只要求大小关系稳定,方便后面各种模型自由输出。
    Score(q,d)∈R\text{Score}(q, d) \in \mathbb{R}
  3. 排序约定所有排序算法共享一条约定——分数降序输出,分数高的文档排在前面。
    di 排在 dj 前  ⟺  Score(q,di)>Score(q,dj)d_i \text{ 排在 } d_j \text{ 前} \iff \text{Score}(q, d_i) > \text{Score}(q, d_j)

BM25文本匹配

最早的排序靠“背菜名”:菜单里出现“清淡”二字的菜就排前面。这套字面匹配虽然笨,在文本检索上却意外地好用,BM25 就是它的集大成者。直到今天,BM25 依然是文本检索和搜索引擎召回阶段的黄金基线,几乎所有新算法都要先跑赢它。

BM25 站在 TF-IDF 的肩膀上:词在文档里出现越多(词频 TF),文档越可能相关;词在全语料里越稀有(逆文档频率 IDF),一旦命中价值越大。它额外做了两个工程优化——用参数 k1 实现“词频饱和”(出现 10 次并不比 5 次好太多),用参数 b 做“文档长度归一化”(长文档的词频要打折,防止内容注水)。

菜名背得再熟,也理解不了“想吃点不油的”和“清蒸鲈鱼”的关系。BM25 在语义上天然“失明”,但这恰恰是它作为基线的价值:简单、快、可解释。任何花哨的新方法都要先问一句——你能稳定跑赢 BM25 吗?

BM25(q,d)=∑t∈qIDF(t)⋅f(t,d)⋅(k1+1)f(t,d)+k1⋅(1−b+b⋅len(d)avgdl)\displaystyle \text{BM25}(q, d) = \sum_{t \in q} \text{IDF}(t) \cdot \frac{f(t, d) \cdot (k_1 + 1)}{f(t, d) + k_1 \cdot \left(1 - b + b \cdot \frac{\text{len}(d)}{\text{avgdl}}\right)}
公式分三层理解:外层对查询里的每个词求和;每个词先乘一个“稀有度权重”IDF;再乘一个“词频饱和 + 长度归一”的比值项。整体就是“越独特、命中越多的词,贡献越大;文档越长,贡献越打折”。
  1. 遍历查询词把查询拆成词,每个词 t 对得分的贡献累加起来,查询里越重要的词贡献越大。
    ∑t∈q\sum_{t \in q}
  2. 词的重要性包含词 t 的文档越少,IDF 越大;命中稀有词时加分更多,像“红烧肉”远比“的”更能定位菜品。
    IDF(t)\text{IDF}(t)
  3. 词频饱和项词频 f(t,d) 升高则得分增加,但 k1 限制增长幅度,避免“出现 10 次就比 3 次好 3 倍”的非线性失真。
    f(t,d)⋅(k1+1)f(t,d)+k1\frac{f(t,d) \cdot (k_1+1)}{f(t,d) + k_1}
  4. 长度归一化文档越长分母越大,词频被打折,防止长文档靠“啰嗦”占便宜;参数 b 控制打折力度,b 越大惩罚越狠。
    1−b+b⋅len(d)avgdl1 - b + b \cdot \frac{\text{len}(d)}{\text{avgdl}}

多因子特征工程

金牌服务员点菜从不只看菜名,她会叠加“口碑怎么样、最近被翻牌多不多、这位顾客上次吃了什么”等信息。搜索引擎也是如此,除了 BM25 文本分,还要为每个查询-文档对抽取几十上百个特征,交给模型综合判断。这就像给“合适分”装上了多只眼睛。

特征大致分三类:文本特征(BM25 分、标题命中、词重叠率)回答“字面像不像”;行为特征(历史点击率 CTR、停留时长、后续点击)回答“别人爱不爱看”;质量特征(页面权威度、时效性、收录时间)回答“这文档靠不靠谱”。三者互补,缺一不可。

最简单的融合方式是线性加权:每个特征乘一个权重再求和。虽然朴素,但可解释性强,也是后续学习排序模型的输入基础。

特征为王。工业界常说:“把特征做扎实,比换一个更复杂的模型收益更大。”就像服务员把口碑、热度、顾客忌口都记在小本本上,排序系统就有了“常识”,不再只是字面匹配的复读机。

Score(q,d)=∑k=1nwk⋅ϕk(q,d)\displaystyle \text{Score}(q, d) = \sum_{k=1}^{n} w_k \cdot \phi_k(q, d)
特征工程的本质是“把经验量化成数字”:权重 w 表示这个维度有多可信,特征值 φ 表示这个维度观测到的证据。权重可以人工调,也可以让模型从数据里学。
  1. 特征函数第 k 个特征,比如 BM25 分、点击率、页面权威度,统一量化成可计算的数值。
    ϕk(q,d)\phi_k(q, d)
  2. 特征权重表示这个维度的可信程度,可以由人工经验设定,也可以由学习排序自动学出。
    wkw_k
  3. 求和融合把各维度得分加权相加,n 通常是几十到几百;复杂系统会用树模型或神经网络替代这个求和。
    ∑k=1n\sum_{k=1}^{n}

学习排序模型

特征太多,权重靠人调不现实。于是有了学习排序(Learning to Rank, LTR):把“特征→得分→顺序”的映射交给模型从数据里自动学。好比新服务员小张把老师傅的每一单记录收集起来,自己琢磨“原来顾客提'清淡'时,娃娃菜比红烧肉更该排前面”。

按训练目标分三类。Pointwise(单文档排序)把排序当回归/分类,对每个文档独立预测相关度,实现简单但不管文档间关系;Pairwise(文档对排序)每次取“一个相关文档 + 一个不相关文档”组成配对,训练目标是让前者的得分高于后者;Listwise(列表级排序)直接优化整个列表的质量,最贴近真实目标但训练开销最大。

Pairwise 的经典做法(RankNet 思路)把“文档 i 排在 j 前”建模为一个概率,再用负对数似然作为损失:

选型就像服务员的成长路径:刚入行先学“两两比较哪道菜更合适”(Pairwise),熟练后再学“整桌怎么统筹出最佳顺序”(Listwise)。数据少、求稳时从 Pointwise/Pairwise 起步,数据充足、追求整页体验时再上 Listwise,循序渐进最稳妥。

Pij=11+e−(si−sj),L=−∑(i,j)∈Plog⁡Pij\displaystyle P_{ij} = \frac{1}{1 + e^{-(s_i - s_j)}}, \qquad L = -\sum_{(i,j) \in \mathcal{P}} \log P_{ij}
通俗地说:模型给相关文档打 s_i、给不相关文档打 s_j,然后计算“相关文档排名更靠前的概率”;训练就是不断调参,让这个概率尽量接近 1。
  1. 文档配对P 是“相关文档 i、不相关文档 j”组成的配对集合,训练时遍历这些配对。
    P\mathcal{P}
  2. 得分差模型给相关文档的得分减去不相关文档的得分,差值越大说明排序越正确。
    si−sjs_i - s_j
  3. 概率化Sigmoid 函数把得分差压到 0 到 1 之间,解释为“文档 i 排在 j 前面的概率”。
    11+e−(si−sj)\frac{1}{1 + e^{-(s_i - s_j)}}
  4. 负对数损失概率越接近 1,损失越小;最小化损失就是逼着模型把相关文档排到不相关文档前面。
    −log⁡Pij-\log P_{ij}

NDCG离线评估

排得好不好,需要有尺子量。餐厅会请美食评委从两个维度打分:相关度(这道菜合不合点单需求)和顺序(最合适的是否在最前面)。搜索引擎离线评估最常用的尺子,就是 NDCG(归一化折损累计增益)。

流程分三步:先让标注员给每条结果分级标注 rel(0 不相关、1 相关、2 强相关);再从前往后累计增益,位置越靠后折损越大;最后除以理想排序的累计增益 IDCG,得到 0 到 1 之间的 NDCG 分数,满分代表排序与标注完全一致。

评委试吃只是离线把关,真实顾客买不买账还要看线上的 A/B 测试。NDCG 高是“这道菜理论上合适”,点击率高才是“顾客真的点了”。业界标准做法是:离线 NDCG 快速筛方案,在线指标做最终决策。

DCGk=∑i=1k2reli−1log⁡2(i+1),NDCGk=DCGkIDCGk\displaystyle \text{DCG}_k = \sum_{i=1}^{k} \frac{2^{\text{rel}_i} - 1}{\log_2(i + 1)}, \qquad \text{NDCG}_k = \frac{\text{DCG}_k}{\text{IDCG}_k}
关键在“折损”二字:排在第 1 位的强相关结果贡献巨大,排到第 8 位贡献就小得多。这契合用户“只盯前排”的真实行为——前面的位置更值钱。
  1. 分级标注第 i 位结果的人工相关度,取 0、1、2 或更细的五档,值越大表示越相关。
    reli\text{rel}_i
  2. 指数增益相关度每升一档,增益近似翻倍,体现“强相关结果的价值远大于一般相关”。
    2reli−12^{\text{rel}_i} - 1
  3. 位置折损第 1 位折损小,第 5 位折损约 2.6 倍,排名越靠后贡献被压缩得越狠。
    log⁡2(i+1)\log_2(i + 1)
  4. 归一化IDCG 是理想排序下的 DCG,相除后 NDCG 恒在 0 到 1 之间,可跨查询、跨列表长度比较。
    DCGkIDCGk\frac{\text{DCG}_k}{\text{IDCG}_k}

语义排序优化

字面匹配的天花板,要靠“理解语义”来突破。顾客说“想吃点爽口解腻的”,金牌服务员知道他要的是清淡酸辣口,而不是字面含“爽口”二字的菜。深度学习要做的,就是让搜索引擎“读懂意思”而不是“对字眼”。

典型方案是双塔模型(如 Sentence-BERT):把查询 q 编码成向量,把文档 d 编码成向量,用余弦相似度衡量语义距离。两个向量夹角越小,语义越接近;即使“清蒸鲈鱼”里没有“不油腻”三个字,模型也能给出高分。

生产环境不会抛弃 BM25,而是采用“混合架构”:向量召回负责语义宽进,把字面不匹配但意思接近的候选捞进来;BM25 负责字面兜底,保证强匹配不漏;两路候选合并后,交给精排(LTR)输出最终顺序。用户的点击日志再回流为训练数据,形成持续优化的数据飞轮。从背菜名到懂口味,排序系统一路进化,但核心不变——理解需求、多维度打分、用真实反馈持续校准。

sim(q,d)=q⃗⋅d⃗∥q⃗∥⋅∥d⃗∥\displaystyle \text{sim}(q, d) = \frac{\vec{q} \cdot \vec{d}}{\lVert \vec{q} \rVert \cdot \lVert \vec{d} \rVert}
向量可以理解为“意思的坐标”:把一句语义投影到几百个隐含维度上。余弦相似度只看方向、不看长短,天然适合文本匹配——一句话长得再啰嗦,只要意思相近,夹角就小。
  1. 向量编码神经网络把查询和文档分别压缩成稠密向量,每个维度代表某种隐含的语义特征。
    q⃗,d⃗\vec{q}, \vec{d}
  2. 点积衡量两个向量方向的一致性,直觉上“两个意思越接近,方向越一致,点积越大”。
    q⃗⋅d⃗\vec{q} \cdot \vec{d}
  3. 模长归一除以各自模长,消除文档长度带来的偏差,余弦值落在 -1 到 1 之间,只看语义方向。
    ∥q⃗∥⋅∥d⃗∥\lVert \vec{q} \rVert \cdot \lVert \vec{d} \rVert

AI 应用场景

电商商品搜索排序

阶段:多因子特征工程 + Pairwise/Listwise 精排

解决的问题:用户搜“通勤连衣裙”可能召回上千件商品,传统文本匹配把“碎花宽松款”排前面,完全忽略用户风格偏好、商品销量与服务体验。AI 排序把标题相关、点击率、转化率、店铺评分等特征送入排序模型,让“用户真正想买”的商品浮到前排。

具体案例:某电商平台在大促前,搜索团队用梯度提升树(LTR 的一种实现)替换原 Pointwise 逻辑回归,点击率提升 18%、下单转化率提升 9%,同时利用用户点击日志每周自动更新训练集,保持了排序模型的时效性。

企业知识库语义检索

阶段:向量召回 + 语义精排

解决的问题:企业内部工单与文档检索中,“服务器 502 怎么排查”和“网关报错处理方案”字面毫无重叠,BM25 完全找不到,员工只能翻群聊记录。引入双塔语义匹配后,语义相似的文档被召回,再经精排输出,检索成功率大幅提升。

具体案例:某互联网公司把 20 万篇故障工单向量化,上线语义检索后,故障处理方案命中率从 31% 提升到 67%,一线运维平均排查时间缩短 40%,知识库从“吃灰资料”变成了真正的生产力。

内容平台“相关推荐”过滤

阶段:相关性打分 + 多因子排序

解决的问题:短视频/资讯平台做个性化推荐前,需要先做一层“相关性过滤”:这篇讲美食的文章,不能因为用户爱看美食就排在“最新发布”前面——还要结合内容质量、时效、与用户兴趣的匹配度综合排序,否则首页全是低质搬运内容。

具体案例:某资讯 App 在推荐管线中加入“相关性粗排”环节,用多因子模型对候选内容打分过滤,次日留存提升 3 个百分点,人均阅读时长提升 12%,广告位点击率也同步受益。

Python 演示

python87 行
import math # 迷你语料: 四道菜的产品介绍corpus = [    "清蒸鲈鱼 清淡 鲜嫩 少油",    "红烧肉 肥而不腻 浓油赤酱",    "麻辣烫 香辣 过瘾 重口味",    "上汤娃娃菜 清淡 鲜甜 爽口",]  def tokenize(text):    return text.lower().split()  def compute_idf(docs):    n = len(docs)    df = {}    for doc in docs:        for w in set(tokenize(doc)):            df[w] = df.get(w, 0) + 1    # 平滑IDF: 词越稀有权重越大    return {w: math.log((n + 1) / (v + 1)) + 1 for w, v in df.items()}  def bm25(query, docs, k1=1.5, b=0.75):    idf = compute_idf(docs)    avgdl = sum(len(tokenize(d)) for d in docs) / len(docs)    scores = []    for doc in docs:        words = tokenize(doc)        dl = len(words)        freq = {}        for w in words:            freq[w] = freq.get(w, 0) + 1        s = 0.0        for q in tokenize(query):            if q not in freq:                continue            tf = freq[q]            # 长度归一化: 长文档的词频要打折            norm = k1 * (1 - b + b * dl / avgdl)            s += idf[q] * tf * (k1 + 1) / (tf + norm)        scores.append(s)    return scores  def train_pairwise(feats, labs, lr=0.1, epochs=200):    n = len(feats)    dim = len(feats[0])    w = [0.0] * dim    for _ in range(epochs):        for i in range(n):            for j in range(n):                # 只处理"相关 vs 不相关"配对                if labs[i] <= labs[j]:                    continue                si = sum(w[k] * feats[i][k] for k in range(dim))                sj = sum(w[k] * feats[j][k] for k in range(dim))                # 不相关文档排前面的概率                p = 1.0 / (1.0 + math.exp(sj - si))                for k in range(dim):                    # 梯度更新: 让相关文档得分比不相关文档高                    w[k] += lr * p * (feats[i][k] - feats[j][k])    return w  if __name__ == "__main__":    print("=== BM25 字面匹配: 查询[清淡 鱼] ===")    scores = bm25("清淡 鱼", corpus)    for doc, sc in sorted(zip(corpus, scores), key=lambda x: -x[1]):        print(f"{sc:.3f}  {doc}")     print("\n=== Pairwise 学习排序 ===")    # 每个候选的特征: [词频相关, 语义相似, 页面质量]    feats = [        [3.0, 0.9, 1.0],        [1.0, 0.2, 0.5],        [0.5, 0.1, 0.3],        [2.0, 0.8, 0.9],    ]    labs = [1, 0, 0, 1]  # 1=相关, 0=不相关    w = train_pairwise(feats, labs)    print("学到的特征权重:", [round(x, 3) for x in w])    for f, lab in zip(feats, labs):        sc = sum(wi * fi for wi, fi in zip(w, f))        print(f"标注={lab} 得分={sc:.3f}")
目的:用迷你“菜品”语料演示 BM25 字面匹配的打分过程,再用一个 Pairwise 学习排序模型从标注中学出特征权重,直观对比“字面匹配”与“学习排序”的差异。
  1. df[w] = df.get(w, 0) + 1统计包含某词的文档数,这是计算 IDF 的前置步骤。
  2. return {w: math.log((n + 1) / (v + 1)) + 1 for w, v in df.items()}带平滑的 IDF:词越稀有值越大,平滑项防止除零和负权重。
  3. norm = k1 * (1 - b + b * dl / avgdl)长度归一化:文档越长分母越大,词频贡献被压得越低。
  4. s += idf[q] * tf * (k1 + 1) / (tf + norm)BM25 核心累加:IDF 加权、词频饱和、长度归一三者合一。
  5. if labs[i] <= labs[j]:只挑“相关 vs 不相关”配对,跳过同类配对,这正是 Pairwise 的核心思路。
  6. p = 1.0 / (1.0 + math.exp(sj - si))计算“不相关文档排前面”的概率,作为梯度更新的信号。
  7. w[k] += lr * p * (feats[i][k] - feats[j][k])沿梯度方向更新特征权重,让相关文档得分逐渐高于不相关文档。

常见误区

误区“写搜索排序,直接按关键词出现次数排序不就行了?词出现越多肯定越相关啊,搞那么复杂干嘛。”

正解词频只是最基础的一维信号。BM25 都引入了 IDF、长度归一化和词频饱和,更别说现代排序还要叠加行为特征、质量特征和语义匹配。只看词频,会把“的、了、在”这类高频词刷屏的低质页面排在前面,用户搜一次就跑了。

为何常见:刚接触搜索时,最自然的直觉就是把“包含关键词”等同于“相关”,因为布尔检索教的正是“有没有”,而不是“好不好”。

误区“深度学习这么强,我直接上最复杂的 Listwise 模型,效果肯定吊打 BM25。”

正解排序效果 = 数据 × 特征 × 模型。没有可靠标注、特征稀疏时,Listwise 训练不稳定且收益有限;工业界通常按“BM25 基线 → 加特征 → Pointwise/Pairwise → Listwise”渐进迭代。复杂模型不是银弹,数据和特征才是地基。

为何常见:公开榜单上复杂模型刷分亮眼,容易让人忽略工程实践中的数据瓶颈和特征短板,误以为“换模型”就能解决一切。

误区“离线实验 NDCG 涨了 0.05,上线后用户肯定更满意。”

正解NDCG 基于人工分级标注,衡量的是“离线理想排序”;而线上满意度还受标题吸引力、页面加载速度、时效性等因素影响,甚至受排序多样性干扰。业界以离线 NDCG 做快速筛选,最终以线上 A/B 测试的点击率、转化率、留存为准,两者经常不一致。

为何常见:NDCG 是教程里讲解最多、最容易跑分的指标,容易让人误以为它就是用户反馈本身,忽略了离线与在线的天然鸿沟。

误区“Pairwise 训练时不就是对每个文档打一个分吗?跟 Pointwise 没啥区别。”

正解Pointwise 是对单个文档独立回归/分类,预测“绝对相关度”;Pairwise 则是取一对文档(一正一负),学习“正文档得分应高于负文档”的相对关系。两者的目标函数完全不同:一个修绝对值,一个修大小关系,Pairwise 更贴近排序本质。

为何常见:两者最终都输出每个文档的分数,从预测形式看很像,初学者容易把“训练目标”和“输出形式”混为一谈。

面试题

Q1. 关于“相关性排序”与“检索召回”,下列说法正确的是?

单选题 · easy

  • A.召回负责把候选排成最终顺序
  • B.排序负责从海量候选中筛出结果
  • C.召回先缩小范围排序再精排← 正确答案
  • D.召回与排序目标完全相同

答案:C。召回负责“宽进”——从海量候选中快速筛出小集合;排序负责“精排”——对候选精细打分定顺序。就像服务员先筛出几道可能合适的菜,再排出上菜顺序,两者目标完全不同,选 C。

Q2. BM25 中 IDF(逆文档频率)的主要作用是?

单选题 · easy

  • A.让出现次数多的词权重更高
  • B.让稀有词匹配时贡献更大← 正确答案
  • C.惩罚文档长度带来的偏差
  • D.把得分归一化到零和一之间

答案:B。IDF 衡量词的区分度:像“的、了”几乎每篇都有,价值低;像“红烧肉”只在少数文档出现,一旦命中就很有辨识度。IDF 恰好让稀有词命中时贡献更大,选 B。

Q3. BM25 中“词频饱和”效果是由哪个参数实现的?

单选题 · mid

  • A.IDF 平滑项让稀有词权重更大
  • B.k1 限制词频增长幅度上限← 正确答案
  • C.b 控制长度归一化的强度
  • D.avgdl 取平均文档长度值

答案:B。k1 出现在词频项的分子分母中,词频再高,得分增长也会被 k1 压住,形成“饱和”,避免词频翻倍得分就翻倍。b 管长度归一化,avgdl 只是统计量,IDF 管词稀有度,均与饱和无关。

Q4. Pointwise、Pairwise、Listwise 三类排序学习的核心区别是?

单选题 · mid

  • A.使用的训练特征数量不同
  • B.训练目标的粒度层次不同← 正确答案
  • C.最终输出的结果格式不同
  • D.是否使用神经网络来实现

答案:B。三者的本质区别是训练目标的粒度:Pointwise 对单文档修绝对分,Pairwise 对文档对修先后关系,Listwise 对整个列表修排序质量。它们可以用相同特征、相同输出形式,但损失函数完全不同,选 B。

Q5. Pairwise 排序学习(如 RankNet)的损失函数本质是?

单选题 · mid

  • A.让相关文档得分等于不相关文档
  • B.让相关文档得分高于不相关文档← 正确答案
  • C.让列表整体 NDCG 达到最高
  • D.让每个文档得分接近人工标注值

答案:B。Pairwise 构造“相关 i + 不相关 j”的配对,损失函数惩罚“j 排在 i 前”的情况,训练目标就是让相关文档得分高于不相关文档。C 是 Listwise 的目标,D 是 Pointwise 的目标,A 方向完全相反。

Q6. NDCG 中的“位置折损”体现了什么思想?

单选题 · easy

  • A.越靠前的结果重要性越高← 正确答案
  • B.越靠后的结果越需要加权
  • C.所有位置的结果同样重要
  • D.只关注最后一名结果的排序

答案:A。NDCG 用 log2(i+1) 做分母,位置越靠后折损越大。这是因为用户基本只看前排:第 1 名被看到的概率远大于第 8 名。这与“重点菜放最前面”的服务员直觉一致,选 A。

Q7. 下列哪些属于排序系统的常用特征?

多选题 · mid

  • A.BM25 文本匹配得分← 正确答案
  • B.用户点击率行为统计← 正确答案
  • C.页面权威度与时效性← 正确答案
  • D.数据库磁盘占用大小

答案:ABC。文本特征(BM25)、行为特征(点击率)、质量特征(权威度、时效性)是排序特征的三大支柱。磁盘占用是系统资源指标,与“文档是否相关”无关,属于无效特征。

Q8. 关于 NDCG 评估,下列说法正确的有?

多选题 · hard

  • A.NDCG 需要人工分级标注← 正确答案
  • B.NDCG 考虑了排序位置的影响← 正确答案
  • C.NDCG 分数高线上必然好
  • D.NDCG 满分对应理想排序结果← 正确答案

答案:ABD。NDCG 依赖人工标注 rel,用位置折损刻画“前排更重要”,除以 IDCG 后满分恒为 1,对应排序与理想完全一致。但它是离线指标,与线上点击、转化并不必然一致,C 错在“必然”。

Q9. 语义排序双塔模型中,余弦相似度为何要除以向量模长?

单选题 · hard

  • A.让得分不受向量长度干扰← 正确答案
  • B.提高模型训练的时间速度
  • C.让向量维度保持一致数值
  • D.避免模型出现梯度爆炸

答案:A。余弦相似度只关心方向,除以模长后,文档写得长不长、向量模值大不大都不影响相似度,避免“长文档天然分高”的偏差。训练速度和梯度问题由学习率、归一化层解决,与模长除法无关。

Q10. 生产环境混合排序架构通常包含哪些环节?

多选题 · hard

  • A.向量召回实现语义宽进← 正确答案
  • B.BM25 保住字面强匹配← 正确答案
  • C.点击日志回流持续训练← 正确答案
  • D.完全抛弃文本匹配信号

答案:ABC。成熟架构是“向量召回 + BM25 兜底 + 精排融合”,并用点击日志回流训练形成数据飞轮。BM25 字面强匹配仍不可替代,D 说“完全抛弃”过于绝对,不符合工程实践。