学习Machine Learning,阅读文献,看各种数学公式的推导,其实是一件很枯燥的事情。有的时候即使理解了数学推导过程,也仍然会一知半解,离自己写程序实现,似乎还有一道鸿沟。所幸的是,现在很多主流的Machine Learning方法,网上都有open source的实现,进一步的阅读这些源码,多做一些实验,有助于深入的理解方法。
Ranklib就是一套优秀的Learning to Rank领域的开源实现,其主页在:http://people.cs.umass.edu/~vdang/ranklib.html,从主页中可以看到实现了哪些方法。其中由微软发布的LambdaMART是IR业内常用的Learning to Rank模型,本文介绍RanklibV2.1(当前最新的时RanklibV2.3,应该大同小异)中的LambdaMART实现,用以帮助理解paper中阐述的方法。
LambdaMART.java中的LambdaMART.learn()是学习流程的管控函数,学习过程主要有下面四步构成:
1. 计算deltaNDCG以及lambda;
2. 以lambda作为label训练一棵regression tree;
3. 在tree的每个叶子节点通过预测的regression lambda值还原出gamma,即最终输出得分;
4. 用3的模型预测所有训练集合上的得分(+learningRate*gamma),然后用这个得分对每个query的结果排序,计算新的每个query的base ndcg,以此为基础回到第1步,组成森林。
重复这个步骤,直到满足下列两个收敛条件之一:
1. 树的个数达到训练参数设置;
2. Random Forest在validation集合上没有变好。
下面用一组实际的数据来说明整个计算过程,假设我们有10个query的训练数据,每个query下有10个doc,每个q-d对有10个feature,如下:
为了简便,省略了余下的数据。上面的数据格式是按照Ranklib readme中要求的格式组织(类似于svmlight),除了行号之外,第一列是q-d对的实际label(人标注数据),第二列是qid,后面10列都是feature。
这份数据每组qid中的doc初始顺序可以是随机的,也可以是从实际的系统中获得的当前顺序。总之这个是计算ndcg的初始状态。对于qid=1830,它的10个doc的初始顺序的label序列是:0, 0, 0, 1, 1, 0, 1, 1, 0, 0(虽然这份序列中只有label值为0和1的,实际中也会有2,3等,由自己的标注标准决定)。我们知道dcg的计算公式是:
begin{equation} dcg(i)=frac{2^{label(i)}-1}{log_{2}{(i+1)}} end{equation}
i表示当前doc在这个qid下的位置(从1开始,避免分母为0),label(i)是doc(i)的标注值。而一个query的dcg则是其下所有doc的加和:
begin{equation} dcg(query)=sum_{i}^{ }frac{2^{label(i)}-1}{log_{2}{(i+1)}} end{equation}
根据上式可以计算初始状态下每个qid的dcg:
$ dcg(qid=1830)=frac{2^{0}-1}{log_{2}{(1+1)}}+frac{2^{0}-1}{log_{2}{(2+1)}}+...+frac{2^{0}-1}{log_{2}{(10+1)}} $
$ =0+0+0+0.431+0.387+0+0.333+0.315+0+0=1.466 $
要计算ndcg,还需要计算理想集的dcg,将初始状态按照label排序,qid=1830得到的序列是1,1,1,1,0,0,0,0,0,0,计算dcg:
$ ideal_dcg(qid=1830)=frac{2^{1}-1}{log_{2}{(1+1)}}+frac{2^{1}-1}{log_{2}{(2+1)}}+...+frac{2^{0}-1}{log_{2}{(10+1)}} $
$ =1+0.631+0.5+0.431+0+0+0+0+0+0=2.562 $
两者相除得到初始状态下qid=1830的ndcg:
$ ndcg(qid=1830)=frac{dcg(qid=1830)}{ideal_ndcg(qid=1830)}=frac{1.466}{2.562}=0.572 $
下面要计算每一个doc的deltaNDCG,公式如下:
begin{equation} deltaNDCG(i,j)=left |ndcg(original sequence)-ndcg(swap(i,j) sequence) ight | end{equation}
deltaNDCG(i,j)是将位置i和位置j的位置互换后产生的ndcg变化(其他位置均不变),显然有相同label的deltaNDCG(i,j)=0。
在qid=1830的初始序列0, 0, 0, 1, 1, 0, 1, 1, 0, 0,由于前3的label都一样,所以deltaNDCG(1,2)=deltaNDCG(1,3)=0,不为0的是deltaNDCG(1,4), deltaNDCG(1,5), deltaNDCG(1,7), deltaNDCG(1,8)。
将1,4位置互换,序列变为1, 0, 0, 0, 1, 0, 1, 1, 0, 0,计算得到dcg=2.036,整个deltaNDCG(1,4)的计算过程如下:
$ dcg(qid=1830,swap(1,4))=frac{2^{1}-1}{log_{2}{(1+1)}}+frac{2^{0}-1}{log_{2}{(2+1)}}+...+frac{2^{0}-1}{log_{2}{(10+1)}} $
$ =1+0+0+0+0.387+0+0.333+0.315+0+0=2.036 $
$ ndcg(swap(1,4))=frac{dcg(swap(1,4))}{ideal_dcg}=frac{2.036}{2.562}=0.795 $
$ deltaNDCG(1,4)=detalNDCG(4,1)=left |ndcg(original sequence)-ndcg(swap(1,4)) ight |=left |0.572-0.795 ight |=0.222 $
同样过程可以计算出deltaNDCG(1,5)=0.239, deltaNDCG(1,7)=0.260, deltaNDCG(1,8)=0.267等。
进一步,要计算lambda(i),根据paper,还需要ρ值,ρ可以理解为doci比docj差的概率,其计算公式为:
begin{equation} ho _{ij}=frac{1}{1+e^{sigma (s_i-s_j)}} end{equation}
Ranklib中直接取σ=1(σ的值决定rho的S曲线陡峭程度),如下图,蓝,红,绿三种颜色分别对应σ=1,2,4时ρ函数的曲线情形(横坐标是si-sj):
初始时,模型为空,所有模型预测得分都是0,所以si=sj=0,ρij≡1/2,lambda(i,j)的计算公式为:
begin{equation} lambda _{ij}= ho_{ij}*left |deltaNDCG(i,j) ight | end{equation}
上式为Ranklib中实际使用的公式,而在paper中,还需要再乘以-σ,在σ=1时,就是符号正好相反,这两种方式是等价的,符号并不影响模型训练结果(其实大可以把代码中lambda的值前面加一个负号,只是注意在每轮计算train, valid和最后计算test的ndcg的时候,模型预测的得分modelScores要按升序排列——越负的doc越好,而不是源代码中按降序。最后训练出的模型是一样的,这说明这两种方式完全对称,所以符号的问题可以省略。甚至不乘以-σ,更符合人的习惯——分数越大越好,降序排列结果。):
begin{equation} lambda _{i}=sum_{j(label(i)>label(j))}{lambda_{ij}}-sum_{j(label(i)<label(j))}{lambda_{ij}} end{equation}
计算lambda(1),由于label(1)=0,qid=1830中的其他doc的label都大于或者等于0,所以lamda(1)的计算中所有的lambda(1,j)都为负项。将之前计算的各deltaNDCG(1,j)代入,且初始状态下ρij≡1/2,所以:
$ lambda_1=-0.5*(deltaNDCG(1,3)+deltaNDCG(1,4)+deltaNDCG(1,6)+deltaNDCG(1,7)) $
$ =-0.5*(0.222+ 0.239+ 0.260+ 0.267)=-0.495 $
可以计算出初始状态下qid=1830各个doc的lambda值,如下:
上表中每一列都是考虑了符号的lamda(i,j),即如果label(i)<label(j),则为负值,反之为正值,每行结尾的lamda(i)是前面的加和,即为最终的lambda(i)。
可以看到,lambda(i)在系统中表达了doc(i)上升或者下降的强度,label越高,位置越后,lambda(i)为正值,越大,表示趋向上升的方向,力度也越大;label越小,位置越靠前,lambda(i)为负值,越小,表示趋向下降的方向,力度也大(lambda(i)的绝对值表达了力度。)
然后Regression Tree开始以每个doc的lamda值为目标,训练模型。
版权声明:
本文来源网络,所有图片文章版权属于原作者,如有侵权,联系删除。
本文网址:https://www.bianchenghao6.com/java-jiao-cheng/17791.html