排序学习(learning to rank)中的ranknet pytorch简单实现

本文介绍了RankNet排序学习的理论基础,包括预测相关性概率、真实相关性概率、代价函数和实际使用中的神经网络模型。接着,文章提供了一个基于PyTorch的RankNet简单实现,并提及RankNet、LambdaRank和LambdaMART的演进关系,以及LambdaRank在计算和评估指标上的改进。
摘要由CSDN通过智能技术生成

一.理论部分

  理论部分网上有许多,自己也简单的整理了一份,这几天会贴在这里,先把代码贴出,后续会优化一些写法,这里将训练数据写成dataset,dataloader样式。

  排序学习所需的训练样本格式如下:

  

  解释:其中第二列是query id,第一列表示此query id与这条样本的相关度(数字越大,表示越相关),从第三列开始是本条样本的特征向量。

  • RankNet:

         RankNet是属于pairwise方法,它是将某个query下的所有文档两两组成文档对,每个文档对作为一个样本:

  A.  预测相关性概率:

        

  解释:对于任一个doc对(Ui,Uj),模型输出的得分为si和sj,那么根据模型预测Ui比Uj与query更相关的概率。RankNet一般采用神经网络,sigmoid能提供一个较好的概率评估。

  B.  真实相关性概率:

        

  解释:真实数据对中的Ui和Uj都包含一个与query相关度的label,比如Ui为3,Uj为1,则Ui比Uj与query更相关,这里是定义Ui比Uj更相关的真实概率。Sij定义为1:Ui比Uj更相关;-1:Uj比Ui更相关;0:Ui与Uj相关度相同。

  C.  代价函数:

        

  解释:这里使用交叉熵来拟合真实概率与预测概率,两个分布越接近,交叉熵越小。

  D.  问题:

  问题一:没有使用排序中的一些评估指标直接作为代价函数,原因是这些指标函数不连续,不好求导,不太好用梯度下降,交叉熵适合梯度下降。

  问题二:在正常训练时,对每个样本对{i,j}都会更新一次参数,采用BP时,更新一次需要先前向预测,再误差后反向传播,会很慢。

  E.在实际使用中,ranknet采用神经网络方法进行学习,一般采用的是带有隐层的神经网络。学习过程一般使用误差反向传播方法来训练。

  如何训练呢?这里提供了两种思路:
1)取一个样本对(Xi, Xj),首先对Xi带入神经网络进行前向反馈,其次将Xj带入神经网络进行前向反馈,
然后计算差分结果并进行误差反向传播,接着取下一个样本对。这种方法很直观,缺点是收敛速度慢。
2)批量训练。我们可以对同一个排序下的所有文档pair全部带入神经网络进行前向反馈,
然后计算总差分并进行误差反向传播,这样将大大减少误差反向传播的次数。

 

  大家可以参考论文《From RankNet to LambdaRank to LambdaMART: An Overview》,这篇论文从RankNet,LambdaRank讲到LambdaMart的这三种排序学习方法,后面的都是在前面的基础上进行改进提出的。基中RankNet来自论文《Learning to Rank using Gradient Descent》,LambdaRank来自论文《Learning to Rank with Non-Smooth Cost Functions》,LambdaMart来自《Selective Gradient Boosting for Effective Learning to Rank》。RankNet与LambdaRank是神经网络模型,LambdaRank加速了计算和引入了排序的评估指标NDCG,提出了lambda概念。而LambdaMart的核心则是利用了GBDT,即MART,这里每棵树拟合的不是残差(平方损失的梯度是残差,其它损失叫负梯度),而是Lambda这个值,这个值代表这篇文档在下次迭代时的方向和强度,lambdamart不需要显式定义损失函数,更加不需要对损失函数求导(因为ndcg非连续),lambda充当了拟合目标,在实际计算时,会为每个文档计算一个lambda值。

  ......

二.pytorch实现RankNet

 1 import torch
 2 import torch.utils.data as data
 3 import numpy as np
 4 
 5 y_train = []
 6 x_train = []
 7 query_id = []
 8 array_train_x1 = []
 9 array_train_x0 = []
10 
11 def extract_features(toks):
12     # 获取features
13     features = []
14     for tok in toks:
15         features.append(float(tok.split(":")[1]))
16     return features
17 
18 def extract_query_data(tok):
19     #获取queryid documentid
20     query_features = [tok.split(":")[1]] #qid
21     return
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值