FM模型在LTR类问题中的应用

由于工作原因,去年有段时间鼓捣了阵FM在排序类问题的应用。排序和分类、回归一样是机器学习中的基本任务。排序问题在工业界应用场景也非常常见,比如电商网站推荐列表中商品的排序,搜索引擎中网页的排序。虽然不同的业务中排序问题涉及到的实体不同,问题的本质其实都很类似。排序系统一般可分为两个阶段,召回(recall)和排序(rank),有时候也称作粗排和细排。16年Recsys上谷歌发表了篇介绍youtube的视频推荐的文章,里面使用到了深度学习的方法,但深度学习在工业界中落地稍微困难一些,所以本文想介绍下传统机器学习模型在排序问题中的应用。

本文提到模型从思路上来说就是一个进阶版的RankNet。不过。FM模型引入了高阶特征交叉,而且在稀疏场景下模型参数学习更为准确。FM模型由于复杂度原因一般只用二阶,对应的计算公式如下:

\tilde{y}(x)=w_{0}+\sum_{i=1}^{n}{w_ix_i}+\sum_{i=1}^{n}{\sum_{j=i+1}^{n}{<v_i,v_j>x_ix_j}}

上式中的最后一项可以化简成如下式子使得计算复杂度从o(kn^{2}) 降到 o(kn) ,其中k为隐向量长度,  n 为特征数目。值的注意的是,真实业务场景中往往是海量特征,一般只有几十或百量级的特征非空,此时计算特征复杂度时要考虑是非空特征数目,而不再是特征数目。由该式子可以看出,模型参数主要是偏置 w_0,一次项系数 w_i 和隐向量系数 v_{if} ,总共参数规模为1+n+kn个。后续计算梯度的时候是直接基于该式子。

\tilde{y}(x)=w_0+\sum_{i=0}^{n}{w_ix_i}+\frac{1}{2}\sum_{f=1}^{k}{((\sum_{i=1}^{n}{v_{i,f}x_i})^{2}}-\sum_{i=1}^{n}{{v_{i,f}^2{x_i}^2})}

我们知道,pairwise类方法要比pointwise类方法(直接看做分类或者回归)要更适合排序类场景。pairwise loss里构造样本时我们同时考虑两个item比如x^ix^j 。这两个item是有顺序的,比如用户在排序列表里点击了 x^i ,而未点击 x^j ,我们可以看做 x^i 要优于 x^j,这样两者构造的样本其标签为 y_{ij}=1。我们要去拟合 \tilde{y}_{ij} 的表达式为:

\tilde{y}_{ij}=sigmoid(\tilde{y}(x_i)-\tilde{y}(x_j))=\frac{1}{1+exp(-(\tilde{y}(x_i)-\tilde{y}(x_j)))}

类似于逻辑回归,这里使用最大似然进行参数估计。设S为所有有序pair对的集合。针对任一有序对,我们可以调换顺序使得 y_{ij}=1 ,所以可以进一步化简。

argmax \prod_{<i,j>\in S}^{}{\tilde{y}_{ij}}^{y_{ij}}(1-\tilde{y}_{ij})^{1-y_{ij}}=argmin- \prod_{<i,j>\in S}^{}{\tilde{y}_{ij}}^{y_{ij}}(1-\tilde{y}_{ij})^{1-y_{ij}}

= argmin- \prod_{<i,j>\in S}^{}{\tilde{y}_{ij}}

这样考虑这一对pair的话,可以定义损失函数,如下式:

L=-log(\tilde{y}_{ij})=log(1+exp(-(\tilde{y}(x_i)-\tilde{y}(x_j)))

损失函数对参数 \theta 求导的话可得 \frac{\partial L}{\partial \theta}=\frac{\partial L}{\partial (\tilde{y}(x_i)-\tilde{y}(x_j))}(\frac{\partial \tilde{y}(x_i)}{\partial \theta}-\frac{\partial \tilde{y}(x_j)}{\partial \theta})

如果定义 \lambda_{ij}=\frac{\partial L}{\partial(\tilde{y}(x_i)-\tilde{y}(x_j))}=-\frac{1}{1+exp(\tilde{y}(x_i)-\tilde{y}(x_j))},则 \frac{\partial L}{\partial \theta} 可以简化为:

\frac{\partial L}{\partial \theta}=\lambda_{ij}(\frac{\partial \tilde{y}(x_i)}{\partial \theta}-\frac{\partial \tilde{y}(x_j)}{\partial \theta})

前面我们提到,总共有偏置项、一次项系数和隐变量系数三类参数,通过前面 \tilde{y}(x) 的公式可以得到:

1、当 \theta 是偏置项时,相减时消去,故不用考虑;

2、当 \theta 是一次项 w_{i}时, \frac{\partial \tilde{y}(x_i)}{\partial \theta}=x_i

3、当 \theta 是隐变量参数 v_{i,f} 时, \frac{\partial \tilde{y}(x_i)}{\partial \theta}=x_i\sum_{j=1}^{n}{v_{j,f}x_j}-v_{i,f}x_i^2,这里求导涉及求和公式稍微麻烦点。

这样就求出了导数,后面可以直接利用sgd之类的优化算法进行参数的学习。

整个模型我们可以称之为RankFM。在我们的业务场景中,RankFM比直接看做分类问题使用FM模型有一定提升。但RankFM这类pairwise方法也有不足的地方,把列表里不同的item对都平等看待,并没有考虑item的位置信息,比如排在前面的item明显要比排在后面的item重要。一般排序类常见的评价指标有NDCG,使用了一个例子来表明pairwise loss和NDCG的冲突性。在下图中,从图b到图c,错误的item对从8个降到7个,从pairwise loss的角度来看是正向变好的,但是NDCG指标却从0.790降到了0.511是负向变差的。那往RankFM中引入评估指标的因素呢?

在RankFM求解过程中,对参数求导结果如下式子:

\frac{\partial L}{\partial \theta}=\lambda_{ij}(\frac{\partial \tilde{y}(x_i)}{\partial \theta}-\frac{\partial \tilde{y}(x_j)}{\partial \theta})

那怎么做呢?借鉴传统的LTR方法中LambdaRank的做法,就是在上式的右边乘上 \Delta NDCG\Delta NDCG 就是如果将列表中的item i和j顺序调换之后NDCG的变化。设 f(\lambda_{i,j},\zeta u)=\lambda _{ij}|\Delta NDCG| ,用 f(\lambda_{i,j},\zeta u) 去替代 \lambda _{i,j} 即可。其他过程和RankFM一样,这就是所谓的LambdaFM(文献2)。

\Delta NDCG 就相当于在参数学习过程中的权重,就是说如果item对顺序调整之后评估指标NDCG变化很大,则梯度乘上 \Delta NDCG 之后在参数更新的时候变化就会大一些。文献2提到的场景是推荐场景,对于给定用户user和情景context,候选的item可能会很多。如果在学习的过程中如果每次都随机选择一个用户和一个item对,则可能导致学习的效率偏低,收敛很慢。设一个item i是正例,item j和j'是负例,如果 \Delta NDCG_{i,j}>\Delta NDCG_{i,j'} ,则称item j相对item j'更好(informative)。那每次怎么选择informative的负例呢?文献2中提到了可以选择热度更高的item选择排名靠前的item。如果用户不喜欢热度很高的item所能标明的信息要大于用户不喜欢一个不怎么受欢迎的item。

参考文献

1.Exploiting ranking factorization machines for microblog retrieval.

2.LambdaFM: Learning Optimal Ranking with Factorization Machines Using Lambda Surrogates.

编辑于 2019-03-18

文章被以下专栏收录