Learning to Rank:从特征到排序函数的监督学习

FreeGuideOnline 最新 2026-06-24

Learning to Rank:从特征到排序函数的监督学习

在信息检索、推荐系统和搜索引擎中,排序是决定用户体验的核心环节。传统的排序方法依赖人工规则或简单的相关性打分,难以应对复杂的用户意图和海量特征。Learning to Rank (LTR) 将机器学习引入排序问题,通过监督学习自动构建排序函数。本教程将从零开始讲解 LTR 的核心思想、主流方法、常用算法及评估指标,帮助你快速掌握构建智能排序模型的关键技术。


1. 什么是 Learning to Rank?

Learning to Rank 是一类监督学习任务,其目标是根据给定的查询,对一组候选对象进行排序,使得最相关的对象排在前面。与传统分类或回归不同,LTR 不关心每个对象的绝对分数,而只关心它们之间的相对顺序。

典型应用场景:

  • 搜索引擎:对网页结果排序
  • 推荐系统:对商品或内容排序
  • 广告系统:对广告位进行竞价排序

1.1 LTR 的基本学习框架

Learning to Rank 系统通常包含三个环节:

  1. 特征提取:为每个“查询-文档”对提取数值特征。
  2. 排序模型训练:利用带标签的训练数据学习一个排序函数。
  3. 线上排序:对新查询生成文档序列。

训练数据由一系列查询和与每个查询对应的文档列表组成。每个文档带有相关性标签(如完美相关=5、高度相关=4、相关=3、弱相关=2、不相关=1 或 0),模型学习的目标就是让高标签的文档尽可能排在前面。


2. 特征工程:如何表示查询与文档的关系

特征决定了排序模型的上限。LTR 的特征通常可以分为三大类:

  • 相关性特征:文档与查询的文本匹配程度。例如 TF-IDF、BM25、余弦相似度、词共现率。
  • 文档质量特征:文档本身的权威性、可信度。例如 PageRank、文档长度、发布时间、点击率。
  • 用户行为特征:历史点击数据、驻留时长、跳出率、用户评分等。

特征构造时,通常将“查询-文档”对转换为一个固定长度的数值向量。例如:

查询: "机器学习入门"
文档1: TF-IDF=2.4, PageRank=5.2, 新发布=1, 点击率=0.12...
文档2: TF-IDF=1.8, PageRank=7.1, 新发布=0, 点击率=0.31...

所有文档按查询分组后,一并送入排序模型。


3. 三种主要的 LTR 建模方法

根据损失函数定义的方式,LTR 可分为 Pointwise、Pairwise 和 Listwise 三类。

3.1 Pointwise 方法

核心思想:将排序问题简化为对每个“查询-文档”对的回归或分类问题。对于每个文档,模型直接预测其相关性分数或标签类别,然后按照预测分数降序排列。

典型算法:

  • 用线性回归或逻辑回归预测相关性标签
  • 用梯度提升树(如 GBDT)进行回归

优点:模型简单,可直接复用成熟的回归/分类算法。
缺点:没有考虑文档之间的相对顺序,损失函数与排序评价指标(如 NDCG)不完全一致。

损失函数示例(回归):
$$L_{pointwise} = \frac{1}{n} \sum_{i=1}^{n} (y_i - f(x_i))^2$$

3.2 Pairwise 方法

核心思想:将排序问题转化为文档对的二分类问题。对于同一个查询下的任意两个文档,模型判断哪个更相关。如果文档 A 比文档 B 更相关,则对 (A, B) 为正例,反之为负例。最终通过文档对的相对关系推导出整体排序。

代表性算法:

  • Ranking SVM:基于 SVM 的 pairwise 损失
  • RankNet:用神经网络结合交叉熵损失,比较两个文档的概率得分
  • GBRank:基于梯度提升的 pairwise 方法

RankNet 的损失函数基于文档对的交叉熵: $$L = - \sum_{i,j} \left[ \bar{P}{ij} \log P{ij} + (1-\bar{P}{ij}) \log (1-P{ij}) \right]$$ 其中 $P_{ij} = \frac{1}{1 + e^{-\sigma (s_i - s_j)}}$,$\bar{P}_{ij}$ 是由真实标签定义的理想概率(若 $y_i > y_j$ 则为 1,相等为 0.5)。

优点:直接优化相对顺序,更契合排序目标。
缺点:训练复杂度与文档对数量平方相关,且对不可比较的文档对(如标签相同)处理不自然。

3.3 Listwise 方法

核心思想:直接优化整个文档列表的排序评价指标(如 NDCG),或定义列表级别的损失函数,使得整个排序列表接近最优。

代表性算法:

  • ListNet:用 top-one 概率的交叉熵作为损失
  • LambdaRank:不显式定义损失函数,而是定义梯度为 $\lambda$,该梯度与排序指标变化相关
  • LambdaMART:LambdaRank 与梯度提升树(MART)结合,是工业界最常用的 LTR 算法之一

LambdaMART 的关键技巧:梯度定义时考虑交换文档对后评价指标的变化,而不是回归残差。这样模型在训练时直接对排序效果敏感的文档对给予更大的梯度更新力度。

$$\lambda_{ij} = \frac{-\sigma}{1 + e^{\sigma (s_i - s_j)}} |\Delta \text{NDCG}_{ij}|$$

其中 $|\Delta \text{NDCG}_{ij}|$ 表示交换文档 i 和 j 后 NDCG 的绝对变化量。

优点:直接优化排序评价指标,在大多数公开数据集上效果最好。
缺点:实现相对复杂,训练耗时更长。


4. 排序模型的评价指标

排序质量的评估不能简单用准确率。下面是最常用的离线指标:

4.1 Normalized Discounted Cumulative Gain (NDCG)

NDCG 是目前最主流的排序指标,它衡量推荐/搜索结果列表中文档的累计相关性增益,并对排名位置进行折损。

  • CG(Cumulative Gain):简单将前 k 个文档的相关性标签相加 $$CG@k = \sum_{i=1}^{k} rel_i$$

  • DCG(Discounted CG):靠前的位置权重更大,常见折损方式为 $\frac{rel_i}{\log_2(i+1)}$ $$DCG@k = \sum_{i=1}^{k} \frac{rel_i}{\log_2(i+1)}$$

  • NDCG:用理想排序下的 DCG 进行归一化 $$NDCG@k = \frac{DCG@k}{IDCG@k}$$ 其中 IDCG@k 是理想情况下(文档按真实相关性降序排列)的 DCG 值。

NDCG 取值在 0~1 之间,越接近 1 表示排序越优。

4.2 Mean Average Precision (MAP)

主要用于二值相关性(相关或不相关)的场景。

  • 对每个查询,计算 Average Precision(AP):在每个相关文档的位置,计算当前的精确率,然后取平均。
  • 对所有查询的 AP 求均值得到 MAP。

4.3 Mean Reciprocal Rank (MRR)

非常适用于“唯一正确答案”的搜索场景(如问答系统)。它只看第一个相关文档出现的位置的倒数: $$MRR = \frac{1}{|Q|} \sum_{q \in Q} \frac{1}{rank_q}$$ 其中 $rank_q$ 是第一个相关文档的排名。排名越靠前,倒数越大。


5. 动手实践:用 XGBoost 实现 LambdaMART

XGBoost 和 LightGBM 都内置了基于 LambdaMART 的排序学习。下面以 Python 和 XGBoost 为例,快速搭建一个 LTR 排序器。

5.1 数据准备

数据格式为 libsvm 或 CSV,每行表示一个查询-文档对,结构为:<label> <query_id> <feature1>:<value> ...

import xgboost as xgb

# 假设数据已整理为 train.group (每组的文档数量) 和 train.txt (libsvm格式)
dtrain = xgb.DMatrix('train.txt')
# 通过文件读取 group 信息
dtrain.set_group(open('train.group').read().splitlines())

5.2 模型训练

指定目标函数为 rank:ndcgrank:map,并使用 LambdaMART。

params = {
    'booster': 'gbtree',
    'objective': 'rank:ndcg',   # 优化 NDCG
    'eval_metric': 'ndcg@10',
    'eta': 0.1,
    'max_depth': 6,
    'min_child_weight': 1,
    'subsample': 0.8,
    'colsample_bytree': 0.8,
    'num_boost_round': 500
}

model = xgb.train(params, dtrain, num_boost_round=500)

5.3 预测与排序

对于每个查询,模型输出每个文档的得分,然后按得分降序排列即可。

dtest = xgb.DMatrix('test.txt')
scores = model.predict(dtest)

# 实际应用中,需按 query_id 分组,每组内部排序
# 此部分略,可借助 pandas groupby

5.4 模型评估

可利用 sklearn.metrics.ndcg_score 或自己实现 NDCG 计算函数。


6. LTR 在工业界的实用技巧

  • 特征标准化与交叉:对查询-文档对特征做 z-score 标准化,或构造二阶交叉特征(如 TF-IDF * PageRank)提升模型表达能力。
  • 冷启动处理:新查询无历史行为特征时,可降级为相关性特征排序。
  • 位置偏差修正:训练数据中被点击的文档往往受到位置影响,可使用逆倾向加权(IPW)等方法降低位置偏差。
  • 在线学习与 A/B 测试:离线指标(NDCG)提升不一定带来线上点击率增长,务必结合线上实验评估。

7. 总结

Learning to Rank 通过监督学习将排序规则从专家经验中解放出来,成为现代搜索与推荐系统的基石。从简单的 Pointwise 回归,到 Pairwise 的相对顺序学习,再到 Listwise 直接优化排序指标,逐步贴近真实的排序目标。在实际项目中,特征工程的质量往往比模型选择更重要,而 LambdaMART 类算法因其高效和对 NDCG 的直接优化,成为最通用的工业方案。

掌握本教程内容后,你已具备从特征设计到模型部署的基本能力,可开始尝试在真实数据上构建自己的排序模型。

(注:本文为免费在线教程内容,可自由学习与转载。)