Skip to content

排序学习

排序学习(Learning to Rank, LTR)是搜索引擎、推荐系统、广告排序的核心技术:它不预测点击与否,而是预测”哪个该排在前面”。本页讲解三大流派——Pointwise、Pairwise、Listwise——以及 LambdaMART、BERT 排序等工业级方法,并补充 2025 年 LLM 驱动的排序新范式。前置阅读:监督学习、梯度提升树详解、推荐系统。

把排序想象成给一筐苹果排队上架:你有三种思路。

  • Pointwise = 给每个苹果单独打分:模型只看单个苹果,预测”这个有多新鲜”(分数 0-100),最后按分数排。简单,但完全忽略了”排序是相对的”这个本质。
  • Pairwise = 两两比较苹果:模型学的是”A 比 B 新鲜还是更旧”。转化为二分类问题(谁在前),对错对的”逆序对”施加损失。RankSVM、RankNet 属于此类。
  • Listwise = 直接对着整个队列优化:模型一次看整排苹果,直接优化像 NDCG 这样的排序指标本身——最贴近最终目标,效果也最好。LambdaMART、ListNet 是代表。

关键洞察:排序的终极目标是把用户最想要的顶到最前面,而不是预测绝对分数。所以评估指标也是位置敏感的(NDCG、MAP),排在前面的错比排在后面的错代价大得多。

Pointwise:把每个文档 (query, doc) 的相关度等级(如 0/1/2/3/4 五档)当作回归或分类目标,逐条学,损失与排序无关。代表方法:线性回归、GBDT 回归、McRank。优点简单,缺点损失函数与排序指标脱节。

Pairwise:构造所有文档对 (doci,docj)(doc_i, doc_j),若 ii 比 jj 更相关,目标就是让 scorei>scorejscore_i > score_j。损失用 hinge(RankSVM)或交叉熵(RankNet)。关键改进是 RankNet 的梯度加权——信息量大的对(即模型预测错得离谱的相关对)获得更大梯度,这就是 LambdaRank 的核心,而 LambdaMART = LambdaRank 的梯度 + GBDT(MART)做基学习器。

Listwise:把一个 query 下整个文档列表当做一个样本,损失直接刻画列表级别的排序质量。两种思路:把真实排序的”排列概率分布”与预测的对比(ListNet、ListMLE),或直接优化 NDCG 的近似梯度(LambdaMART、SoftRank)。

**DCG(Discounted Cumulative Gain)**的核心思想:高相关文档排得越靠前越好,排得越靠后收益被”折扣”。对于位置 kk:

DCG@k=∑i=1k2reli−1log⁡2(i+1)\text{DCG}@k = \sum_{i=1}^{k} \frac{2^{rel_i} - 1}{\log_2(i + 1)}

其中 relirel_i 是位置 ii 上文档的相关度等级(如 0/1/2/3/4)。两项设计都有直觉:

  • 分子 2reli−12^{rel_i} - 1:相关度越高,增益越大,且是指数增长——高度相关文档比一般相关文档重要得多。
  • 分母 log⁡2(i+1)\log_2(i+1):位置折扣——排第 1 位的分母是 log⁡22=1\log_2 2 = 1,排第 2 位是 log⁡23≈1.585\log_2 3 \approx 1.585,第 10 位是 log⁡211≈3.459\log_2 11 \approx 3.459。排得越靠后,贡献衰减。

NDCG(Normalized DCG):不同 query 的文档数和相关度分布差异大,直接比 DCG 不公平。用理想排序(Ideal DCG,即把最相关的排最前面)做归一化:

NDCG@k=DCG@kIDCG@k,IDCG@k=∑i=1k2reli∗−1log⁡2(i+1)\text{NDCG}@k = \frac{\text{DCG}@k}{\text{IDCG}@k}, \quad \text{IDCG}@k = \sum_{i=1}^{k} \frac{2^{rel_i^*} - 1}{\log_2(i+1)}

其中 reli∗rel_i^* 是理想排序(按相关度从高到低)后的第 ii 个相关度。NDCG 取值 [0,1][0, 1],1 表示完美排序。

举例:某 query 有 5 个文档,相关度依次为 [3,2,3,0,1][3, 2, 3, 0, 1](模型排序后的顺序),理想排序为 [3,3,2,1,0][3, 3, 2, 1, 0]。

DCG@5=23−1log⁡22+22−1log⁡23+23−1log⁡24+20−1log⁡25+21−1log⁡26\text{DCG}@5 = \frac{2^3-1}{\log_2 2} + \frac{2^2-1}{\log_2 3} + \frac{2^3-1}{\log_2 4} + \frac{2^0-1}{\log_2 5} + \frac{2^1-1}{\log_2 6} =71+31.585+72+0+12.585≈7+1.89+3.5+0+0.39=12.78= \frac{7}{1} + \frac{3}{1.585} + \frac{7}{2} + 0 + \frac{1}{2.585} \approx 7 + 1.89 + 3.5 + 0 + 0.39 = 12.78 IDCG@5=71+71.585+32+12.322+0≈7+4.42+1.5+0.43+0=13.35\text{IDCG}@5 = \frac{7}{1} + \frac{7}{1.585} + \frac{3}{2} + \frac{1}{2.322} + 0 \approx 7 + 4.42 + 1.5 + 0.43 + 0 = 13.35 NDCG@5=12.78/13.35≈0.957\text{NDCG}@5 = 12.78 / 13.35 \approx 0.957

MAP 适用于二值相关(relevant / not relevant)的场景。先定义 Average Precision(AP):

AP=1∣R∣∑k=1nP@k⋅relk\text{AP} = \frac{1}{|R|} \sum_{k=1}^{n} P@k \cdot rel_k

其中 ∣R∣|R| 是相关文档总数,relk∈0,1rel_k \in {0, 1} 是位置 kk 的文档是否相关,P@kP@k 是前 kk 个位置中相关文档的比例(Precision@k)。AP 只在每个相关文档出现的位置累加——越早出现的相关文档贡献越大。

MAP 是所有 query 的 AP 的平均:MAP=1Q∑q=1QAPq\text{MAP} = \frac{1}{Q}\sum_{q=1}^{Q} \text{AP}_q。

NDCG vs MAP:NDCG 支持多级相关度(0/1/2/3/4),更贴近搜索场景;MAP 只支持二值相关,更简洁。工业搜索推荐主要用 NDCG@k。

LambdaMART 是微软提出的 Listwise 梯度提升树算法,至今仍是工业排序的强基线。其核心创新在于定义了一个特殊的”Lambda 梯度”。

RankNet 的 Pairwise 交叉熵损失:对于文档对 (i,j)(i, j)(ii 比 jj 更相关),定义目标概率 sij=1s_{ij} = 1,预测概率 s^ij=σ(si−sj)\hat{s}_{ij} = \sigma(s_i - s_j)(sis_i 是模型打分,σ\sigma 是 sigmoid)。损失为:

Cij=−sijlog⁡s^ij−(1−sij)log⁡(1−s^ij)C_{ij} = -s_{ij} \log \hat{s}_{ij} - (1 - s_{ij}) \log(1 - \hat{s}_{ij})

对 sis_i 求梯度(注意 ∂s^ij∂si=s^ij(1−s^ij)\frac{\partial \hat{s}_{ij}}{\partial s_i} = \hat{s}_{ij}(1 - \hat{s}_{ij})):

∂Cij∂si=−∣ΔNDCGij∣⋅−11+esi−sj=λij\frac{\partial C_{ij}}{\partial s_i} = -|\Delta \text{NDCG}_{ij}| \cdot \frac{-1}{1 + e^{s_i - s_j}} = \lambda_{ij}

LambdaRank 的关键洞察:直接用 λij=−11+esi−sj\lambda_{ij} = \frac{-1}{1 + e^{s_i - s_j}} 作为梯度不够好。应该在梯度上乘以 |ΔNDCG|——即交换文档 ii 和 jj 的位置带来的 NDCG 变化量。这样,模型自动把更多的优化努力分配给”NDCG 影响大”的文档对。

λij=−∣ΔNDCGij∣1+esi−sj⋅sign(reli−relj)\lambda_{ij} = \frac{-|\Delta \text{NDCG}_{ij}|}{1 + e^{s_i - s_j}} \cdot \text{sign}(rel_i - rel_j)

其中:

  • ∣ΔNDCGij∣=∣NDCGswap(i,j)−NDCGoriginal∣|\Delta \text{NDCG}_{ij}| = |\text{NDCG}_{swap}(i,j) - \text{NDCG}_{original}|,即交换 ii 和 jj 后 NDCG 变化的绝对值。
  • 分母 1+esi−sj1 + e^{s_i - s_j}:模型越确信 ii 排在 jj 前面(si≫sjs_i \gg s_j),λ\lambda 越小——已经排对了就不需要大梯度。
  • sign(reli−relj)\text{sign}(rel_i - rel_j):确保方向正确。

每个文档 ii 的总 Lambda 梯度:λi=∑jλij\lambda_i = \sum_{j} \lambda_{ij}(对同一 query 下所有可交换的对求和)。

LambdaMART 用上述 λi\lambda_i 作为 GBDT 的”伪残差”来拟合回归树。关键点:

  • λi\lambda_i 既不是真正的损失梯度,也不是数学意义的严格导数——而是一个人为设计的、带 NDCG 权重的伪梯度。
  • GBDT 每轮拟合 λi\lambda_i,寻找使 Lambda 下降最快的分裂,等价于间接优化 NDCG。
  • 叶子权重的计算用 Newton 步长(类似 XGBoost 的二阶方法):wj=−∑i∈Ijλi∑i∈Ijhiw_j = -\frac{\sum_{i \in I_j} \lambda_i}{\sum_{i \in I_j} h_i},其中 hi=∣λi∣(1−∣λi∣)h_i = |\lambda_i|(1 - |\lambda_i|) 是近似的 Hessian。

实践证明 LambdaMART 效果极好,曾是 Bing 搜索的当家算法,至今仍是 Kaggle 排序竞赛和工业搜索精排的强基线。

传统 LTR 用手工特征(BM25、TF-IDF、点击率、PageRank)+ GBDT。深度学习带来了两类革新:

  • 基于交互的模型:直接对 query-doc 对做交互(DSSM 用双塔算语义相似度、DeepFM/DCN 做特征交叉),再 Pointwise 或 Pairwise 训练。
  • 基于 BERT 的语义排序:把 query 和 doc 拼成序列喂给 BERT,用 [CLS] 输出做相关性打分,能理解同义词和语义。详见 Transformer 架构。
  • 混合架构:粗排用双塔召回(快)、精排用 BERT 交叉(准)、重排用 Listwise LTR 优化 NDCG——这是 Google、百度、阿里的主流搜索架构。

2023 年以来,大语言模型(LLM)正在深刻改变排序学习的格局。以下是截至 2025 年的主要趋势:

1. LLM 作为排序器(Zero-shot / Few-shot Re-ranking)

Section titled “1. LLM 作为排序器(Zero-shot / Few-shot Re-ranking)”

直接用 LLM 对候选文档做重排序。典型方法:

  • Listwise prompting:把候选文档列表拼进 prompt,让 LLM 输出重排后的顺序(如 RankGPT, 2023)。无需训练,利用 LLM 的语义理解能力。
  • Pairwise prompting:让 LLM 比较两个文档哪个更相关,聚合比较结果得到最终排序。
  • 局限:推理成本高(每条 query 需要多次 LLM 调用),延迟大,适合离线重排或小规模候选集。
  • LLM 生成合成标签:对于缺乏人工标注的 query-doc 对,用 LLM 判断相关度等级,作为弱监督训练数据。
  • Query 扩展与改写:用 LLM 生成同义 query、长尾 query 扩展,丰富训练集覆盖度。
  • 文档摘要增强:用 LLM 生成文档摘要,将摘要作为额外特征或召回源。

3. 稠密检索(Dense Retrieval)的成熟

Section titled “3. 稠密检索(Dense Retrieval)的成熟”
  • 对比学习训练的编码器(如 OpenAI text-embedding-3、Cohere Embed v3、BGE 系列):把 query 和 doc 编码为稠密向量,用向量相似度做召回——与传统倒排索引互补。
  • ColBERT(2020–2024 持续演进):保留 token 级别的向量交互(延迟交互,late interaction),在精度和效率间取得平衡,2024–2025 年在 RAG 场景广泛应用。

检索增强生成(Retrieval-Augmented Generation)流水线中,排序扮演关键角色:

2025 年的 RAG 系统通常采用 混合检索(BM25 + 稠密向量)+ Cross-Encoder 重排(本质是 Pointwise 的 BERT 排序器)的架构。Cross-Encoder 如 bge-reranker-v2-m3(2024)、Cohere Rerank v3.5(2024)在各类基准上表现优异。

  • RankZephyr(2023)、RankGPT-4 等研究表明:GPT-4 级别 LLM 的 Listwise 排序能力接近甚至超越传统监督 LTR 模型。
  • 工业实践中的权衡:LLM 排序效果好但成本高,通常只在重排阶段对少量候选(如 Top-20)使用。
  • 蒸馏方案:用强 LLM 排序结果蒸馏到小模型(如 MiniLM),降低推理成本。
import lightgbm as lgb
import numpy as np
# 模拟数据:5 个 query,每个 query 下若干 doc
# group[i] 表示第 i 个 query 下有多少个 doc
group = [10, 8, 12, 6, 9]
n = sum(group) # 总 doc 数
X_train = np.random.rand(n, 8) # 8 个排序特征
y_train = np.random.randint(0, 5, n) # 相关度 0-4 档
query_ids = np.repeat(range(len(group)), group)
train_set = lgb.Dataset(X_train, y_train, group=group)
params = dict(objective="lambdarank", metric="ndcg",
ndcg_eval_at=[1, 3, 5], learning_rate=0.1)
model = lgb.train(params, train_set, num_boost_round=50)
print("特征重要度:", model.feature_importance())
# 预测:对每个 query 内的 doc 按分数排序
scores = model.predict(X_train)
for qid in range(len(group)):
start = sum(group[:qid])
end = start + group[qid]
q_scores = scores[start:end]
q_rank = np.argsort(-q_scores) # 按分数从高到低排
print(f"Query {qid} 排序: {q_rank.tolist()}")

用 sklearn 做简单 Pairwise(RankSVM 思路)

Section titled “用 sklearn 做简单 Pairwise(RankSVM 思路)”
from sklearn.svm import LinearSVC
import numpy as np
# 假设已有每个 doc 的特征 X 和相关度等级 y(越大越相关)
# 构造文档对:相关度高的应排在前面
pairs_X, pairs_y = [], []
for i in range(len(y)):
for j in range(len(y)):
if y[i] > y[j]: # i 比 j 更相关
pairs_X.append(X[i] - X[j]) # 特征差
pairs_y.append(+1) # i 应在前
# 训练线性 SVM 学一个排序函数 w,使得 w*x_i > w*x_j
clf = LinearSVC().fit(pairs_X, pairs_y)
score = X @ clf.coef_.ravel() # 排序分数
rank = np.argsort(-score) # 由高到低
import numpy as np
def dcg_at_k(rels, k):
"""计算 DCG@k。
rels: 模型排序后前 k 个位置的相关度列表,如 [3, 2, 3, 0, 1]
"""
rels = np.array(rels[:k])
positions = np.arange(1, len(rels) + 1)
gains = (2 ** rels - 1) / np.log2(positions + 1)
return gains.sum()
def ndcg_at_k(rels, k):
"""计算 NDCG@k。rels: 模型排序后的相关度列表。"""
dcg = dcg_at_k(rels, k)
idcg = dcg_at_k(sorted(rels, reverse=True), k) # 理想排序
return dcg / idcg if idcg > 0 else 0.0
# 示例
rels = [3, 2, 3, 0, 1] # 模型排序后的相关度
print(f"NDCG@5 = {ndcg_at_k(rels, 5):.4f}")
# 输出: NDCG@5 = 0.9572

Cross-Encoder 语义重排(RAG 场景)

Section titled “Cross-Encoder 语义重排(RAG 场景)”
from sentence_transformers import CrossEncoder
# 加载预训练 Cross-Encoder(适合 RAG 重排)
reranker = CrossEncoder('BAAI/bge-reranker-v2-m3')
query = "什么是梯度提升树"
documents = [
"梯度提升树是一种集成学习方法,通过逐步拟合残差来提升模型性能。",
"随机森林通过 bagging 降低方差。",
"GBDT 在表格数据上表现优于深度学习。",
"卷积神经网络用于图像识别。"
]
# Cross-Encoder 对每个 (query, doc) 对打分
pairs = [(query, doc) for doc in documents]
scores = reranker.predict(pairs)
# 按分数从高到低重排
ranked_indices = np.argsort(-scores)
print("重排结果:")
for idx in ranked_indices:
print(f" [score={scores[idx]:.4f}] {documents[idx]}")
  • 评估指标用 NDCG@k / MAP,不要用准确率/AUC。排序是位置敏感任务,准确率完全无法反映排序质量。
  • Pointwise 是最弱基线,作为对比可以;正式任务优先 Pairwise 或 Listwise,尤其 LambdaMART。
  • LightGBM / XGBoost 的 lambdarank 目标是工业上性价比最高的强基线,比从头训神经网络更稳更快,先把它做扎实再考虑深度模型。
  • 特征工程仍是核心。LTR 的特征包括文本相关性(BM25、语义相似度)、统计特征(点击率、停留时间)、用户特征、上下文特征——深度模型并不能替代好特征。
  • 数据规模决定分层:候选百万级时必须分层(召回-粗排-精排-重排),单层精排扛不住全量计算。
  • 位置偏差与点击数据:直接用点击当标签有偏(排得越靠前点击越多),要用 IPS(Inverse Propensity Score,逆倾向得分)或对比实验消除位置偏差。
  • 冷启动 query 用语义召回:BERT 双塔对未见过的 query 仍能算语义相似度,弥补传统倒排索引的词面匹配局限。
  • RAG 重排用 Cross-Encoder:向量召回(Bi-Encoder)快但粗,Cross-Encoder 精但慢——标准做法是召回 Top-100 后用 Cross-Encoder 重排到 Top-10。
  • LLM 排序的适用场景:候选量小(<50)、对延迟要求不极端、且需要深度语义理解时,LLM Listwise 重排效果好;大规模在线排序仍用传统 LTR。
  • 搜索引擎:Google、Bing、百度的搜索结果排序采用分层架构——召回用倒排索引 + 语义向量,精排用 BERT 交叉 + LambdaMART,重排用业务规则与多样性策略。
  • 推荐系统精排:抖音、淘宝、美团的首页推荐,粗排召回数千候选后用深度 LTR 精排打分,优化用户的长期停留与转化,详见 推荐系统。
  • 广告竞价排序:eCPM = bid × pCTR,LTR 负责预测 pCTR,按 eCPM 排序决定广告展现顺序,是 Google/Meta 广告系统的核心。
  • 问答系统候选排序:RAG 在召回文档后用 Cross-Encoder 重排提升相关性,Cross-Encoder 本质是 Pointwise 的 BERT 排序器。2025 年主流 RAG 框架(LlamaIndex、LangChain)都内置了重排模块。
  • 应用商店与内容平台:App Store、B 站的搜索和个性化推荐都用 LTR 优化下载率/完播率等业务指标。
类库语言说明
LightGBMPython内置 lambdarank 目标,工业上最常用的 LambdaMART 实现
XGBoostPython内置 rank:pairwise / rank:ndcg / rank:lambda 目标,支持多种排序损失
RankLibJava微软研究院开源的经典 LTR 工具,含 RankNet/LambdaMART/ListNet 等
Sentence-TransformersPython训练 Cross-Encoder / Bi-Encoder 做语义重排,RAG 场景首选
Cohere Rerank APIPython商业 API,2024 年发布 v3.5,高质量多语言重排
BGE RerankerPython智源研究院开源的中文友好 Cross-Encoder,bge-reranker-v2-m3 支持多语言
TensorFlow RankingPythonGoogle 开源的神经排序框架,支持多种 Listwise 损失
术语英文解释
排序学习Learning to Rank (LTR)把文档排序作为监督学习目标的方法统称
PointwisePointwise逐条预测相关度分数,损失与排序无关的最简单范式
PairwisePairwise把文档两两比较转为二分类,最小化逆序对数
ListwiseListwise以整个文档列表为单位,直接优化排序质量指标
LambdaMARTLambdaMARTListwise 梯度提升树,用带 NDCG 权重的伪梯度驱动 GBDT
NDCGNormalized Discounted Cumulative Gain位置折扣累积增益的归一化值,排序的黄金评估指标
DCGDiscounted Cumulative Gain位置折扣累积增益,排得越靠后贡献衰减
MAPMean Average Precision平均精度均值的排序指标,适用于二值相关
召回-排序分层架构Multi-stage Ranking召回-粗排-精排-重排的多漏斗架构,工业搜索推荐标配
双塔模型Two-tower Modelquery 和 doc 各自编码成向量后算相似度,召回阶段的高效模型
Cross-EncoderCross-Encoderquery 和 doc 拼接后联合编码的模型,精度高但慢,用于精排/重排
位置偏差Position Bias排在前面的物品天然获得更多点击,会污染用点击数据训练的排序模型
稠密检索Dense Retrieval用神经网络编码 query/doc 为稠密向量,以向量相似度做检索
延迟交互Late Interaction保留 token 级向量交互的检索方法(如 ColBERT),精度效率兼顾
Lambda 梯度Lambda GradientLambdaMART 中带 NDCG 权重的伪梯度,驱动 GBDT 间接优化排序
  • Liu,「Learning to Rank for Information Retrieval」(Foundations and Trends in IR, 2009):LTR 的权威综述,系统梳理三大流派与代表算法,入门首选。
  • Burges et al.,「Learning to Rank using Gradient Descent」(RankNet, 2005):微软 RankNet 论文,Pairwise 神经排序的起点。
  • Burges et al.,「From RankNet to LambdaRank to LambdaMART: An Overview」(Microsoft Technical Report, 2010):LambdaMART 的权威技术报告,串联了 Pairwise 到 Listwise 的完整演进。
  • Cao et al.,「Learning to Rank: From Pairwise Approach to Listwise Approach」(ListNet, ICML 2007):Listwise 范式的开创性工作。
  • Nogueira & Cho,「Passage Re-ranking with BERT」(2019):用 BERT 做 Cross-Encoder 重排,深度语义排序的标志性工作,RAG 重排的基础。
  • Sun et al.,「Capturing Delayed Context in Session-based Recommendation with Recurrent Neural Networks」:搜索推荐中的会话上下文建模。
  • Khattab & Zaharia,「ColBERT: Efficient and Effective Passage Search via Contextualized Late Interaction over BERT」(SIGIR 2020):延迟交互检索,RAG 场景广泛应用,2024 持续演进。
  • Qin et al.,「Large Language Models are Effective Text Rankers」(2023) / Sun et al.,「Is ChatGPT Good at Search?」(RankGPT, 2023):LLM 驱动的 Listwise 排序开创性研究。
  • Wang et al.,「Overview of the TREC 2013 to 2015 Web Track」:LETOR / TREC 是排序学习最重要的公开基准与数据集来源。