7.4 分解机的工程实现

前面几节讲解了FM的原理、参数估计方法以及与其他模型之间的关系,我们知道FM是一个表达能力很强的模型,并且在线性时间复杂度下可求解,那么具体在工程上怎么训练FM模型呢?本节试图讲解一般训练的方法,其思路来源于本章参考文献[1]。FM的提出者Rendle给出了FM的工程实现,并且基于该论文的思路,Rendle开源了一个求解FM的高效C++库:libFM,读者可以参考http://www.libfm.org/。另外,本章参考文献[12]提供了FM的一种实现,可以利用分解机解决各类回归、分类、排序问题,本章参考文献[14][17]讲解了怎么分布式训练FM模型。

libFM通过SGD、ALS、MCMC三种方法来训练FM模型,下面介绍利用SGD来求解FM模型的方法,其他算法可以参考该论文,这里不再讲解。在讲解具体的方法之前,我们先统一符号化FM模型,将该模型的求解转化为求极值的最优化问题,方便后面讲解怎么迭代训练。

通过定义训练集S的损失函数l,一般优化问题可以转化为求所有损失的和的最小值问题,定义如下:

对于回归问题,一般用最小平方损失,对应的损失函数为

对于二分类问题,损失函数可以定义为,其中是logistic函数。

直接学习上述最优化问题容易产生过拟合,一般会加入L2正则项,增加了正则化的最优化问题转化为

上面增加的正则项的函数就是我们优化的目标函数,下面的讲解都基于该目标函数。为了方便后面的算法讲解,先求目标函数的导数,对于回归问题(最小平方损失)来说,导数为

对于分类问题(logit损失),导数为

有了导数,下面我们讲解怎么用SGD优化方法来求解FM模型。随机梯度下降(SGD)算法是分解类模型的常用迭代求解算法,该方法简单易懂,对各种损失函数的效果都不错,并且计算和存储成本相对较低。如下就是优化FM模型的SGD算法。

FM迭代算法:用SGD来求解FM模型

在上述算法中,可以针对不同的参数设置不同的正则化因子。对于一个训练样本,SGD算法的时间复杂度是

其中Nz(x)是特征向量x中非零元素个数。

从应用的角度来说,读者没必要对求解FM的原理非常清楚,只要会用就可以了。libFM库是一个方便的求解FM的工具,该库在单机下运行,对于数据量大,一次无法放入内存的情况,可以利用libFM二进制的数据格式,它可以更快地读取数据,并且一次迭代只放一批数据到内存中进行训练。

如果数据量非常大,那么我们就需要采用分布式FM模型了。业界有很多这样的开源工具,这里推荐腾讯的Angel框架,它内置了很多FM算法(及该算法的变种)的实现,并且可以跟Spark配合使用,非常适合工业级FM模型的训练。2019年8月22日Angel发布了全新的3.0版本,整合了PyTorch,它在PyTorch On Angel上实现了许多算法,包括推荐领域常见的算法FM、DeepFM、Wide & Deep、xDeepFM、AttentionFM、DCN和PNN等,Angel擅长推荐模型和图网络模型相关领域(如社交网络分析)。在腾讯内部,如腾讯视频、腾讯新闻和微信等都在使用Angel。