参考文档:
From RankNet to LambdaRank to LambdaMART: An Overview(简写文章DocF)
Learning to Rank using Gradient Descent (简写为DocL)
简单描述一下思想:
论文(
Learning to Rank using Gradient Descent):
1.第三节,提出模型,对P ij建模;
2.3.1节提出一致性要求,并推导出hat Pik ,hat Pik ,hat Pkj之间的关系
3.3.1节证明一个很重要的东西:
Then specifying any set of adjacency
posteriors is necessary and sufficient to uniquely
identify a target posterior 0 ≤ Pij ≤ 1 for every pair of
samples xi , xj .
根据前面的模型,给定任意排列,相邻元素之间的后验概率是任意xi,xj的Pij唯一的充分必要条件。
4.3.1节简化模型,将任意序列之间的相邻元素之间的后验概率统一设置为P 。
5.第4节,由普通的二层网络扩展到相邻相关素之差的二层网络。
对这部分的个人想法:
1.训练集中已经包含了相邻元素的rate值,那么f(0i-0j)要么是1(正确),要么是-1(错误)。
2.通过训练二层网络O,通过比较f(0i-0j,1)获取O的最佳参数。(所有的输入i的排名要比j高)
3.预测,直接通过O给出评分即可
w32:隐藏层到输出层的w参数
w12:输入层到输出层的w参数
具体实现分析(ciir.umass.edu.learning.neuralnet.RankNet):
参数解释:
//Parameters
public static int nIteration = 100; //迭代的次数
public static int nHiddenLayer = 1; //隐藏变量的层数
public static int nHiddenNodePerLayer = 10; //每个隐藏层的节点个数
public static double learningRate = 0.00005; //梯度下降的步长
//Variables
protected List<Layer> layers = new ArrayList<Layer>(); //层列表
protected Layer inputLayer = null; //输入层
protected Layer outputLayer = null; //输出层
//to store the best model on validation data (if specified)
protected List<List<Double>> bestModelOnValidation = new ArrayList<List<Double>>();
protected int totalPairs = 0; //NetList为pairtwise,总pairs数
protected int misorderedPairs = 0; //pair错误的数目
protected double error = 0.0;
protected double lastError = Double.MAX_VALUE;
protected int straightLoss = 0;
1.init方法
初始化神经网络
a.inputLayer(输入层,维度数目为feature数目+1,1为b),outputLayer(输出层,维度为1)
b.增加隐藏层(这里只增加一层)
c.连接网络,组网
d.计算totalPairs
2.learn方法
a.对训练集的query做神经网络的"前向--后向"训练
b.pairMap[i][] : 比指定query的第i个文档小的文档集合
关于如何训练
参考
From RankNet to LambdaRank to LambdaMART: An Overview
Learning to Rank using Gradient Descent
简单说一下思路:
a.评分socre(x) = o(x), o 为二层神经网络的函数,其参数为我们训练的目标。
b.Cost函数为:f(o(x1,x2),y) ,其中 y为{1,0)。
通过pairMap[i]得到一个集合,o(i,j) = 1,表示i的评分比j大,因此其相应的y为1.
C=f(o(xi,xj),y)(训练数据的形式为:xi>xj)的具体形式为,
对于神经网络的最外层w,C对于w32参数的求导结果为: DocF的公式(3)上面的公式。
其中Pij的形式为:
Learning to Rank using Gradient Descent(4)
c.更新参数:
更新w32的参数:
delta_i:(1-Pij)*(o在xi点对w32的导数值)
,注意:o在隐藏层和输出层,其为logistic形式,这个是由神经网络的结构决定的。
deltas_j:(
1-Pij)*(o在xj点对w32的导数值),注意:o在隐藏层和输出层,其为logistic形式,这个是由神经网络的结构决定的。
这里:
delta_i就是DocF定义的lambda的负数,DocF的公式(3),就是针对w32求导的梯度,
也是DocL的公式(8),DocL的公式(12)(下面有备注)的delta
lambda为delta_i的原因:
根据DocF的公式(3),C对w(这里为w32)的求导结果为
lamda*((o在xi点对w的导数值)-(o在xj点对w的导数值))。
1-Pij 的结果为公式(3)也就是lambda的负数,σ determines the shape of the sigmoid
,确保大于0为正无穷大,小于0为负无穷大。
更新参数的时候:
for(int l=0;l<deltas_j.length;l++)
sum_j += deltas_j[l] * s.getSource().getOutput(param.pairMap[param.current][l]);
double dw = learningRate * (delta_i * s.getSource().getOutput(param.current) - sum_j);
在调整的时候,this.weight += dw,原因在于这里的
delta_i其实为-lamda.
更新w21的参数:
隐藏层的更新与output层有不同的地方,可以参考具体的公式。
DocL的公式(10),(11),(14),(15)
本质同w32,参考相关文档即可。
训练的时候,用crossEntropy来评估训练的结果,并保留最佳的参数。
3.eval 方法
各个feature作为不同的输入到网络中,最后得出output值。