最后更新于
最后更新于
对于用户输入的一个query , 和是结果中其中两篇待排序的文章, 是模型打给文章的分数, 分数的含义是预测了和之间的相关性, 同理.
我们可以预测将文章排在之前的概率, 从而将排序转化成一个二分类问题. 将排在之前的概率定义如下:
这里的是一个超参数, 并不是sigmoid函数.
用定义排在前面这个论述的真实性, 即二分类的真实标签. 1为论述为真, 0为论述为假, 0.5代表与的位置相同. 做一个简单的数据变换, 用来代表排在前面这个论述的真实性, 从而定义损失函数binary cross entropy loss如下:
其中第一步到第二步的转换是带入了以及.
关于训练集, 也需要进行简化. 由于一对文章和, 排在前和排在后两个论述真实性一定是互斥的, 所以如果把都放入在训练集中, 会出现冗余的情况. 因此在训练集中, 只保留所有的样本.
然后以上面的binary cross entropy loss为损失函数, 对模型中所有的参数求导:
将前面的项用表示, 由于训练样本中的, 可以将简化如下:
总结两点:
binary loss function, 对列表头部的排序正确性
和列表尾部的排序正确性
一视同仁, 实际上是优化AUC
而如果我们要优化NDCG这样重点关注头部位置的指标, 这些指标对单个文档的预测得分的微小变化, 要么无动于衷(预测得分没有引起文档排序变化), 要么反应剧烈(引起了排序变化), 因此在训练的过程中, 无法定义一个连续可导的损失函数.
LambdaRank/LambdaMART的解决思路, 即为既然无法定义一个符合要求的损失函数, 就不再定义损失函数了, 直接定义一个符合我们要求的梯度. 这个不是由损失函数推导出来的, 被人为定义出来的梯度, 就是Lambda梯度.
如果我们现在的目标是优化NDCG指标, 如何定义梯度?
首先, 在上一轮迭代结束后, 将所有的文档(同一个query下的)按照上一轮迭代得到的预测分数从大到小进行排序.
需要特别注意样本的组织方法. 排序只对同一个query下的候选文档/同一个推荐session下的候选商品才有意义, 所以与普通二分类不同, LTR训练集有一个分组的概念, 同一个组内的候选物料才能匹配成对, 相互比较. 这一点在xgboost或lightgbm模型框架中, 对应的数据组成形式, 都有体现.
而和是模型的输出对参数的导数, 这个在不同的模型中有不同的解决方法(NN, GBDT等).
这里我们关心的是和, 且有, 因此计算得到其中的一项即可, 即损失函数对第篇文章的预测得分的导数. 因为这里的导数我们用表示, 这也是LambdaRank, LambdaMART等一系列算法的由来.
是一个梯度
然后对于文本对, 如果使用binary cross entropy loss, 则损失函数对于预测分数的预测仍为:
然后, 将和的排序位置调换, 计算NDCG指标的变化, 然后构造Lambda梯度, 将乘到上一步得到的Lambda梯度之上, 就得到了优化的Lambda梯度. 不同的优化指标, 对应着不同的优化的Lambda梯度.