聊聊推荐系统,FM模型效果好在哪里?

本文始发于公众号:Coder梁

大家好,我们今天继续来聊聊推荐系统。

在上一回当中我们讨论了LR模型对于推荐系统的应用,以及它为什么适合推荐系统,并且对它的优点以及缺点进行了分析。最后我们得出了结论,对于LR模型来说它的作用其实更多的是记住了一些特征的组合,所以在一些样本当中表现非常好,但同样也带来了问题,就是需要人工生产大量的特征,带来的负担非常的大。

特征交叉

在我们讲述解决方案之前,我们还是先来分析一下特征。

分析什么呢,分析我们人工制作的特征的内容。我们都知道无论是item还是user的统计类型的特征都是很容易搞定的,只需要做一些统计分析,有些更是可以直接从数仓当中获取。真正麻烦的是什么呢,真正麻烦的是item和user相关联的特征,在算法领域这种关联称为交叉。

举个简单的例子,比如男士_游戏女士_护肤品这样的特征,就是user和item进行交叉得出的。这里用到的是用户的性别和商品的类别进行的交叉,除此之外我们还可以产生出各种各样其他的交叉特征,本质上来说我们人工做的特征其实都是这些交叉特征。大家也可以想象得到,这些交叉特征对于能够覆盖到的样本表现出来的效果肯定是非常好的,但是对于不能覆盖的样本其实就是完全没有意义了。所以这就带来了另外一个问题,就是泛化能力的问题。

说具体一点就是当我们交叉特征做到后面,能够覆盖的样本的数量会非常非常少,尤其是一些本来就很小众的特征之间的交叉。举个例子,比如说高收入人群_房产这个交叉特征。对于电商平台来说,房产本来就是很小众的领域,只有极少数人才会闲着没事在电商网站看房子。同样高收入人群可能也很小众,毕竟大部分人都是普通打工人,收入有限。这么一来,这样得到的交叉特征能够覆盖的样本就会非常非常稀疏。

大家可以简单计算一下,假设房产在电商平台的商品当中的占比是1%,高收入群体在总用户占比是10%的话,那么两者交叉之后的占比就成了千分之一。那这样稀疏的样本在训练模型的时候,我们是很难保证这个特征对应的权重已经训练到了最佳程度。

如果说只是脏活累活多对于大公司来说倒也不是不可以忍受,大不了多雇一点人手就是了。但现在摆明了做出来的特征很有可能因为覆盖率的问题没有效果,那么这就不是很能接受了。

特征交叉的稀疏性以及大量的人力成本,这两个问题是LR模型绕不开的硬伤,也是它被FM代替的直接原因。

Factorization Machines因子分解机

FM模型的英文全称是Factorization Machine,翻译过来就是因子分解机,一般业内都简称为FM。

FM是非常强大的模型虽然提出至今已经超过10年了,但目前仍然被很多中小型企业广泛使用。它直接针对了LR的问题进行了修正,大大地提升了模型的效果,甚至可以说是推荐领域效果最显著的一次大跃进。

我在之前的时候写过FM这篇paper的完整解析,有感兴趣的小伙伴可以通过下方的传送门回顾一下。

想做推荐算法?先把FM模型搞懂再说

FM的思想很简单,就是强制特征之间做两两交叉。对于每一个交叉项都赋予一个权重,让模型自己来学所有交叉项的权重。相当于把一维的LR拓展到了二维。

把一维拓展成二维和LR后期人们大量制作的手动交叉特征是一样的,虽然是模型自动做了,但同样会有稀疏性的问题。针对这个问题,FM创造性地提出了向量表示法。这个想法非常天才,可以说是划时代的。

向量表示法其实就是现在常说的embedding,也就是把一个标量用一个向量来代替。FM针对每一个特征在交叉之前都会赋予一个向量,这个向量的长度一般不会很长,介于16到256之间。我做过实验,长度16和长度256效果上几乎没有差别。然后对于特征i和j,我们假设它们的向量分别是\(V_i, V_j\)。对于它们交叉项的权重,我们不是直接通过模型来赋予,而是用\(V_i \cdot V_j\)来计算得到。

这样一来,对于特征数量是n的模型来说,它就把原本\(n * n\)的参数数量下降到了\(n * k\),这里的k就是我们刚才提到的向量的长度,这是一个常数。学过算法的同学都应该知道,这样直接就把参数的数量级下降了一维。

我们写出FM的表达式,大家一看就明白了。

\[\hat{y} = w_0 + \sum_{i=1}^nw_ix_i+\sum_{i=1}^{n-1}\sum_{j=1}^nv_i^T v_jx_i, x_j \]

从这个公式当中,我们可以看出来当我们进行预测的时候,我们需要遍历所有的交叉项,最终得到预测值。这里又有了一个很大的问题,就是计算的复杂度。由于我们使用了所有特征的二阶交叉项,那么我们需要累加的项的数量就是\(n^2\)。对于推荐场景来说,n是一个很大的值,动辄好几十万,显然二阶平方是我们无法接受的。

关于这个问题,FM模型有一段非常精彩的数学推导,完美地解决了这个问题。

复杂度优化

我们分析一下\(\hat{y} = w_0 + \sum_{i=1}^nw_ix_i+\sum_{i=1}^{n-1}\sum_{j=1}^nv_i^T v_jx_i, x_j\)这个式子,会发现前两项都是一阶项,复杂度都是\(O(n)\),所以我们先把这两项忽略,单独来看第三项,也就是困扰我们的这一项。

对于这个式子,我们可以进行化简:

\[\begin{aligned}\sum_{i=1}^n\sum_{j=i+1}^n v_i^T v_j x_i x_j &= \frac{1}{2}\sum_{i=1}^n\sum_{j=1}^n v_i^Tv_jx_i x_j - \frac{1}{2}\sum_{i=1}^nv_i^Tv_jx_ix_j\\&=\frac{1}{2}(\sum_{i=1}^n\sum_{j=1}^n\sum_{f=1}^kv_{i, f}v_{j, f}x_ix_j-\sum_{i=1}^n\sum_{f=1}^kv_{i,f}v_{i,f}x_ix_i)\\&=\frac{1}{2}\sum_{f=1}^k((\sum_{i=1}^nv_{i, f}x_i)(\sum_{j=1}^nv_{j, f}x_j)-\sum_{i=1}^nv_{i,f}^2x_i^2)\\&=\frac{1}{2}\sum_{f=1}^k((\sum_{i=1}^nv_{i,f}x_i)^2 - \sum_{i=1}^nv_{i, f}^2 x_i^2)\end{aligned} \]

简单来解释一下这个推导过程,第一行我想大家应该都能看懂,第二行也很好理解,其实就是把\(v_i^Tv_j\)向量内积展开。第二行到第三行的转化也不难理解,这里有三个\(\Sigma\),我们提取出的是最里面的\(\Sigma\),因为是有限项求和,我们调换顺序并不会影响结果。提取出了公因式之后,得到的结果是两个平方项。

这两个平方项是精髓,因为它们都是\(O(n)\)的复杂度。正是因为把复杂的累加转化成了两个平方项的差,我们才完成了复杂度降维的工作。两个平方项的计算复杂度都是\(O(n)\),再加上外面一层\(O(k)\)的复杂度,整体的复杂度是\(O(kn)\)。但由于k是常数,所以可近似看成\(O(n)\)的复杂度。

这样我们就完成了FM模型预测的优化。

FM的优缺点

到这里,我们把FM的原理又过了一遍。

对于FM模型来说,它最大的优点就是拟合能力很强,因为引入了二阶交叉的特征项,所以对于样本的表达能力大大提升。并且由于通过数学公式,我们将\(O(n^2)\)的复杂度降到了\(O(n)\)。它的训练以及预测速度都是非常快的,和LR旗鼓相当。

我们再来回顾一下LR的两个问题,一个是需要人工制作大量的特征,第二个是样本稀疏对于模型的训练会有影响。

第一个问题已经没有了,因为FM引入了自动交叉的机制,相当于默认帮助我们把所有的二阶交叉特征都做了一遍。但对于第二个问题我们还需要分析一下,为什么FM模型可以解决样本稀疏的问题呢?二阶交叉项不还是会面临样本很少的情况吗?

原因很简单,因为FM把特征映射成了向量,在进行特征交叉的时候是通过向量的点乘来计算的交叉项的权重。对于特征i来说,它和其他所有特征交叉时使用的都是同一个向量\(V_i\)。这样即使特征i和j的组合在样本当中非常稀疏,但是由于\(V_i\)\(V_j\)是单独训练的,所以我们仍然可以得到一个相对比较准确的权重。甚至即使i和j的组合在样本当中没有出现过,但是由于有了\(V_i\)\(V_j\)向量,我们一样可以表达i和j的组合特征,这也是正是FM强大的地方。

FM虽然强大但也不是没有缺点,我们随便想想也能找出来不少。比如说虽然模型自动做了二阶交叉,但是二阶交叉真的能表达所有的特征信息吗?会不会有一些三阶交叉的特征,甚至是四阶交叉的特征会更有效果呢?而且所有的特征交叉都进行了学习,会不会当中有很多无用信息被包含进来了呢?再比如FM当中设定了每个特征和其他所有特征交叉的时候使用的向量是同一个,这样一刀切真的效果最好吗?再比如FM模型很难对连续性特征进行交叉,基本上只能交叉01离散型的特征,这样真的不会丢失信息吗?

我想这一系列问题问下来很难心里不大鼓,所以在FM时代的后期,针对FM模型的一些缺陷和不足进行了很多的实验和尝试,因此诞生了一系列各种各样添砖加瓦的模型。FM模型也从单个模型成了一个巨大的家族,下一期我将会来和大家盘点一下FM家族当中的模型,看看它们都有怎样的变化。

今天的文章就到这里,感谢阅读,如果喜欢的话,不要忘了三连。

posted @ 2021-06-17 14:30  Coder梁  阅读(308)  评论(1编辑  收藏  举报