FM算法效率
FM被广泛采用的一个关键是:通过数学公式改写,将 复杂度降低到
,其中 n 是特征数量,k 是特征的embedding size(隐向量的长度1*k),这样就将FM模型改成了和LR类似和特征数量n成线性规模的时间复杂度了。
FM公式概览
step1->step2
step2->step3
如果把k维特征向量内积求和公式抽到最外边后,公式就转成了上图这个公式了(不考虑最外边k维求和过程的情况下)。它有两层循环,内循环其实就是指定某个特征的第f位(这个f是由最外层那个k指定的)后,和其它任意特征对应向量的第f位值相乘求和;而外循环则是遍历每个的第f位做循环求和。这样就完成了指定某个特征位f后的特征组合计算过程。最外层的k维循环则依此轮循第f位,于是就算完了步骤三的特征组合。
step3->step4
通过上述四步的公式改写,可以看出在实现FM模型时,时间复杂度就降低到了 了,而虽说看上去n还有点大,但是其实真实的推荐数据的特征值是极为稀疏的,就是说大量xi其实取值是0,意味着真正需要计算的特征数n是远远小于总特征数目n的,无疑这会进一步极大加快FM的运算效率。
这里需要强调下改写之后的FM公式的第一个平方项,怎么理解这个平方项的含义呢?这里其实蕴含了后面要讲的使用FM模型统一多路召回的基本思想,所以这里特殊提示一下。
怎么理解这个平方项?
这个平方项,它等价于将FM的所有特征项的embedding向量累加,之后求内积。
可能一些需要的铺垫
隐向量(我一次看的时候没理解)
-
矩阵分解 @基于隐变量的推荐模型
协同过滤重点是在人-物品矩阵上,其中心思想是去对人或者物品进行聚类,从而找到相似人或者相似物品,用群体的智慧为个人进行推荐,但是,这种近邻模型也存在好多问题:
- 随着人和物品的增加,系统的推荐效果并不是线性增加的
- 矩阵中元素稀疏,在计算过程中,随机的增减一个维度,对结果影响很大
为了解决上面的问题,于是就有人发明了矩阵分解的方法,矩阵分解简单讲看下面图:
假设用户物品的评分矩阵 A 是 m 乘以 n 维,即一共有 m 个用户,n 个物品。我们选一个相对 m 和 n 很小的数 k,通过一套算法得到两个矩阵 U 和 V,矩阵 U 的维度是 m 乘以 k,矩阵 V 的维度是 n 乘以 k。
我们现在对上面的整个过程进行解释。
刚开始我们有用户-物品的矩阵,但是呢,整个矩阵中元素非常稀疏,也就是说我们所能得到的有效信息非常少,现在我们希望通过一定的方法来补全信息。
补全的方法呢就是模拟矩阵中元素的生成过程(由2个矩阵到1个矩阵,上图逆向的),此处我们假设矩阵中 i,j 位置处的元素是由一个用户向量 和物品向量
相乘得到,此处
和
有相同的维度, 我们称作用户和物品的隐向量,用数学描述就是:
。
隐向量是拥有相同维度的用户向量 和物品向量
相乘得到的。
- 向量和矩阵是什么关系
矩阵是由m×n个数组成的一个m行n列的矩形表格。特别地,一个m×1矩阵也称为一个m维列向量;而一个1×n矩阵,也称为一个n维行向量。
依上定义可以看出:向量可以用矩阵表示,且有时特殊矩阵就是向量。简言之就是矩阵包含向量。
因子机分解模型中,作者通过借鉴了矩阵分解的思想,对权值矩阵进行低秩约束表达: ,将每一维特征分解为k维隐向量,这里的k是超参数,是需要用户自己训练调参的,k<<n。至于隐向量的理解,我认为是不可观测的随机变量构成的向量,通过当前的已有样本进行推断,随着k的设置不同,隐向量也在发生变化,不太好从业务角度解释里面的数值。实践中,也是去看特征隐向量相乘后看交叉项参数的大小,来看交叉项特征对模型的贡献
这样带来的好处有:
1、训练的交叉项参数从n*(n-1)/2降低到了n*k个,提高了模型训练效率;另外,也降低了模型交叉项学习不充分的影响;
2、交叉项的参数将分别通过对应两个特征的隐向量的内积得到,一些在新数据中出现的交叉项特征也能进行预测,提升了模型预测能力。
-
隐向量可以认为就是embedding学习的权重 @程序大猩猩
the latent feature vectors (V ) in FM now server as network weights which are learned and used to compress the input field vectors to the embedding vectors.
就是说,FM层的隐向量现在起将高维稀疏输入向量转换为低维密集的嵌入向量的作用了。
再看了下对应的图。
可以看到,在embedding向FM层前向传播的时候,权重为1。因此,求embedding矩阵中交叉项乘积的和就能够得到成对的交互特征。也就是原FM公式(1)中的第三项。
再根据,2010年FM论文中的公式变换,
class FM(tf.keras.layers.Layer):
def build(self, input_shape):
assert len(input_shape) >= 2
def call(self, inputs):
# x1x2 = ((x1 + x2)^2 - (x1^2 + x2^2)) / 2
# 由此可推论
sum = tf.reduce_sum(inputs, axis=1, keepdims=True)
square_sum = tf.square(sum)
sum_square = tf.reduce_sum(tf.square(inputs), axis=1, keepdims=True)
cross_term = tf.reduce_sum((square_sum - sum_square) / 2, axis=2, keepdims=False)
return cross_term
上面代码依据的公式是这个,代码的输入是拼接好的embedding向量,形如(batchsize, n, embedding_size)。
-
隐向量是什么意思?@dataniu
线代已经多年没有学过了,查了半天也没有看到对隐向量的解释,上述解答不知道是否正确。o( ̄ヘ ̄o#)
🤖:此问题已解决,在【推荐系统】FM因子分解机(上)的个人总结中给出了解释。
参考:
推荐系统召回四模型之:全能的FM模型 - 张俊林的文章 - 知乎
一些问题:
- xdeepfm介绍,与fm/ffm的区别,ffm的field的意思
- fm为什么用隐向量?隐向量可以认为就是embedding学习的权重,为了解决学习特征组合时所面临的权重问题。
- FM 和 LR 最大的差异是什么?
- DeepFM 相比 FM 做了什么样的提升?
- DeepFM 相比 FM 是学到了一些高阶的特征组合,那用LR能不能实现相似的提升?
- fm,ffm模型原理
- fm和ffm谁的参数多,域的划分