我一开始接触FM算法,看的是文章:
https://www.cnblogs.com/wkang/p/9588360.html
这篇文章,已经写的接近完美,我感觉已经没有必要把别人写的很完美的东西,再重新整理一遍,我现在做的工作,是把某些点写的更细致一些,便于我下次瞬间看明白它,同时再加上我自己的一点感悟
1、我自己理解的,FM算法的核心如下:
假如一个样本有n个特征,那么针对任意两个特征生成一个交叉项,将会出现个参数,参数复杂度就是,但是如果只是针对每一个特征,存在一个隐向量v,每个隐向量的维度是k,我们用隐向量的乘积作为交叉项的参数,可以将向量的每一个维度作为参数,那么参数的个数就是k*n,复杂度就是o(n),特别对于样本的特征很多,再加之特征进行离散化和one-hot编码处理,特征就更多了,那么参数复杂度就非常高了啊,所以FM算法,一下子就把参数复杂度降下来了,使基于交叉项的这种算法,变得可行。
2、这篇文章一开始并没有说,一个特征对应一个隐向量,所以乍一看,会有些费劲,我是看了文章
https://blog.csdn.net/g11d111/article/details/77430095 才知道的。
3、5.1 寻找交叉项是整个FM算法的核心,虽然只看结论,后面的也都能看懂
3、对于5.4,我觉得有几处不对:
a、iter_2不用再平方了
b、对于python 代码 np.multiply(i),实际是会报错的,应该是 np.multiply(i, i),表示i矩阵和i矩阵对应位相乘
我知道作者只是笔误,因为后面作者贴出来的源代码已经证明了这一切,我写出来,是怕时间长了,忘记,然后在这里耗时间,现在粘贴出来作者的这部分源码:
# xi·vi,xi与vi的矩阵点积
inter_1 = dataMatrix[x] * v
# xi与xi的对应位置乘积 与 xi^2与vi^2对应位置的乘积 的点积
inter_2 = multiply(dataMatrix[x], dataMatrix[x]) * multiply(v, v) # multiply对应元素相乘
# 完成交叉项,xi*vi*xi*vi - xi^2*vi^2
interaction = sum(multiply(inter_1, inter_1) - inter_2) / 2
我自己写的伪代码如下,比较简洁
import numpy as np
#类似于神经网络的正向传播
iter_1=i.V
result_1=np.multiply(iter_1, iter_1)
iter_2=np.multiply(i, i).np.multiply(V, V)
1/2(np.sum(result_1-iter_2))
注意,这里面i是单样本,是行向量,扩展成多样本,只需要对i进行竖向堆叠就可以了
4、坦白的讲,第6节,二分类那里,的取值应该是取+1和-1吧,但我一般不习惯这么写,所以我按照自己的习惯写交叉熵损失,其中x和i是一样的,都表示单个样本,是行向量,关于导数的一些符号是按照吴恩达老师,深度学习里面的符号格式写的
这个是单个样本的FM算法的正向传播,而且只需要将x样本竖向堆叠,就可以一次性,算出一批样本的值,因为文中已经给出了对单个的梯度下降,然后我试图给出所有的的梯度下降,然后再进一步写多样本的,多样本的,我放弃了,感觉写不出来矩阵形式,下面是对单个样本的的梯度下降的矩阵形式
是按位相乘,可能会用到python广播,然后重点解释下,我以每个样本3个特征为例:
以上就是,对单个样本梯度下降 矩阵化的全过程,这个都是我看完文章之后,延伸出来的一些东西,或许还有更好的矩阵化方法,甚至可以实现多样本的梯度下降,就像逻辑回归一样,现在先这样了,有空了再把作者写的FM源码看一下,哈哈