背景
接触FM方法时间也算是很久了,虽然没有持续在上面做非常深入的研究,但是做的几个项目中,多次使用后也算是也算是业余玩家中的高端玩家了。在前期的一个项目中深入的参与了spark中的ALS推荐模型(其实本质是FM,als是指其中最优化的算法),其中主要参与解决的问题就是增量推荐(场景中是解决新用户的推荐问题),其中具体的思路就是固定住物品矩阵单独训练每个用户的评分内容,具体就不赘述。但是该方法效率非常慢~(测试中一秒只能处理10个人左右,亿级别的用户还是太慢了)。而在近期又遇到了类似问题,偶然得到一个解决的办法,做个分享。
解决的办法
之所以增量算法部分很慢,其本质原因是对于每一个新用户的推荐过程仍然是一个小的train过程。只要避开这个过程该算法就会很快了。
俗语约定:
1. 用户评分矩阵 : S 原始的用户信息
2. 用户因子矩阵 : U 压缩的用户信息
3. 解码矩阵 : P 即原本的product矩阵 ,满足 U*P=S
4. 编码矩阵 : E 新引入的矩阵,满足 S * E = U
原有的推荐过程是 U*P 的结果进行排序过滤等操作后直接推荐(U矩阵式和用户有关),而现在是 S* E*P 的结果进行排序过滤等操作后直接推荐。训练完成后E矩阵和P矩阵都是和用户无关的矩阵,因此直接避免了后续的新用户不在U矩阵时需要train的问题,而E 矩阵和 P 矩阵也不需要重新训练。
方法的来源
该方法并不是凭空而来的,一方面是基于之前我对FM一些基础知识的理解,另一方面也是近期又看到深度学习中的自编码器,两者结合起来就想到了该方法(其实在FM的增量算方法之前我就是知道自编码器的,但是在做FM增量算法时却是没有想到这一层,上面之所以重新定义矩阵的名称也是为了和自编码器类比)。
至于怎么去得到这个矩阵E和矩阵P,这里也给个简单易行的思路:
1. 先根据S = U*P 进行训练得到 U 和 P ;
2. 再根据 U = S*E 进行train得到 E;
理论上是最好根据 S = S*E*P来同时求解E,P矩阵(复杂会较之前大大增加),但是考虑到第二个等式中两个未知量不是乘法关系而第一个等式是乘法关系,因此感觉这种粗糙的方法也会有一个很好的近似解。
仔细想过之后发现E矩阵其实就是P矩阵的伪逆。