FM实现和实践的感想
- 特征工程对FM很重要,所有特征都要0到1之间,否则很容易梯度爆炸
因为FM梯度的公式中,有v和x相乘的项,如果x比1大,v减去梯度后绝对值也大于了1,在接下去不断迭代中,梯度会越来越大就会爆炸到NaN(注意:这里说的梯度公式有v和x相乘只是强调非线性的,梯度公式实际是\(x_i\sum^n_{j=1}v_{j,f}x_j - v_{i,f}x_i^2\);另外,这里说的x比1大,实际情况中x要比1大比较多才会爆炸,因为还要乘上学习率)
- 为什么在实际使用中,使用业务上的数据集(非广告点击的),FM并没有比逻辑回归或者线性回归好很多,是不是代码写错了?
很多业务数据集可能交叉特征起的作用较小,另外FM也只有2阶的交叉
也有可能是超参没调好,因为使用SGD时超参很难调
也可以看看这个数据集是不是数据量较少,FM的参数较多,需要更多的数据集去训练(不过我个人觉得,主要还是数据集2阶交叉作用小)
- 怎么知道是不是代码写错了?
针对回归问题可以生成一个数据集:随机生成FM的参数\(b, W, V\),随机生成几列特征,根据FM公式算出y(注意查看交叉项在y中起到的作用,不能太小,如果太小的话就调整参数\(V\)),然后跑FM,看看FM能不能你和这个数据集,然后跑线性回归会发现无法拟合,说明FM是起作用了的
观察过拟合后的FM参数,会发现\(b, W\)和前面生成的几乎一样,不过\(V\)跟生成的不一致,这一点我还没有想通为什么\(V\)不一致
(分类问题怎么生成数据集我还没想到)
- 使用论文的SGD进行梯度下降,超参很难调(学习率、衰减)
可以尝试使用Adma等优化方法
初始化值的影响
交叉项的初始值不能初始化为0
这个是显而易见的,可以用公式解释,因为根据梯度的公式\(x_i\sum^n_{j=1}v_{j,f}x_j - v_{i,f}x_i^2\),所以梯度会一直为0
一般使用高斯分布随机生成,标准差是一个超参
线性项和bias的初始值最好是0
如果线性项也是用高斯分布随机生成,那么进行梯度下降的时候,损失期初会很大,而且震荡的很厉害,过了很多epoch才开始持续下降,例如下面的样子;如果初始值是0,就会稳定很多,刚开始的损失就是小于1的,而且很快就能稳定下降
猜测可能是因为初始化为0更接近局部最优解?
1.740649101566134 7.497113213794938 23.470090105163354 33.14111546385315 23.64511919004669 6.267136596203574 2.578806955609892 0.8825661954724465 1.7365348114229828 1.402942023240411 3.2613090844310455 1.99784127432739 0.576489521298484 0.626364890834019 0.8571547081514205 0.694086822224672 1.0119341925383027 0.5176361858707219 0.566816029669394 0.5218835304759538 0.5742864521338142 0.48195460860116923 0.4986442936522203 0.4416475534933967 0.43817710178437264 0.40896395200093033 0.39986457681211457 0.3857665226355063 0.37796208753335386 0.3705438278410384
FM的性质
生成模拟交叉特征的数据集,让FM完全拟合(回归)
预先定义好FM的V、W、b,然后随机生成X,根据公式得到y,生成10000个数据,使用FM训练让其完全过拟合(即损失几乎为0)
最开始设置了k=2,特征数3个,FM的确会完全拟合数据集,但是V跟预先定义的值不同,而W、b跟预先定义的值几乎一致。进一步观察,V虽然不同,但是\(<v_i, v_j>\)是跟预先的值完全一致的,每次跑都能出现完全不同的V,也就是FM可能会有无数多个最优解?从数学上怎么证明呢?在逻辑回归上也会出现这种现象么?
我也猜测过是不是因为特征数太少,导致了过拟合,尝试了k=2,特征数10个,现象是一样的