基于Tensorflow实现DeepFM
前言
DeepFM,Ctr预估中的大杀器,哈工大与华为诺亚方舟实验室荣耀出品,算法工程师面试高频考题,有效的结合了神经网络与因子分解机在特征学习中的优点:同时提取到低阶组合特征与高阶组合特征,这样的称号我可以写几十条出来,这也说明了DeepFM确实是一个非常值得手动撸一边的算法。
当然,早就有一票人写了一车封装好的deepFM的模型,大家随便搜搜肯定也能搜到,既然这样,我就不再搞这些东西了,今天主要和大家过一遍,deepFM的代码是咋写的,手把手入门一下,说一些我觉得比较重要的地方,方便大家按需修改。(只列举了一部分,更多的解释参见GitHub代码中的注释)
本文的数据和部分代码构造参考了nzc大神的deepfm的Pytorch版本的写法,改成tensorflow的形式,需要看原版的自取。
网络结构
DeepFM包含两部分:神经网络部分与因子分解机部分,分别负责低阶特征的提取和高阶特征的提取,两部分权重共享。
DeepFM的预测结果可以写为:y = sigmoid(y(fm)+y(DNN))
FM部分
我很久之前一篇文章细节讲过,这边就不多扯了,更多详见FM理论解析及应用。
DNN部分
这边其实和我上篇文章说的MLPS差距不大,也就是简单的全链接,差就差在input的构造,这边采取了embedding的思想,将每个feature转化成了embedded vector作为input,同时此处的input也是上面计算FM中的V,更多的大家看代码就完全了解了。
代码部分
我一共写了两个script,build_data.py和deepfm.py,也很好理解。build_data.py用来预处理数据,deepfm.py用来跑模型。
build_data.py
| |
核心部分如上,重要的是做了两件事情,生成了feature_index和feature_value。
feature_index是把所有特征进行了标序,feature1,feature2……featurem,分别对应0,1,2,3,…m,但是,请注意分类变量需要拆分!就是说如果有性别:男|女|未知,三个选项。需要构造feature男,feature女,feature未知三个变量,而连续变量就不需要这样。
feature_value就是特征的值,连续变量按真实值填写,分类变量全部填写1。
deepfm.py
特征向量化
| |
deep网络部分的weight
| |
input的地方需要注意一下,这边用了个技巧,直接把把向量化后的特征进行拉伸拼接后带入模型,原来的v是batch*n个特征*embedding的长度
,直接改成了batch*(n个特征*embedding的长度)
,这样的好处就是全值共享,又快又有效。
网络传递部分
都是一些正常的操作,稍微要注意一下的是交互项的计算:
| |
loss部分
我个人重写了一下我认为需要正则的地方,和一些loss的计算方式:
| |
大家也可以直接按照我注释掉的部分简单操作,看个人的理解了。
梯度正则
| |
很多网上的代码跑着跑着就NAN了,建议加一下梯度的正则,反正也没多复杂。
执行结果
| |
看了下没啥大问题。
还有一些要说的
- build_data.py中我为了省事,只做了标准化,没有进行其他数据预处理的步骤,这个是错误的,大家在实际使用中请按照我在公众号里面给大家进行的数据预处理步骤进行,这个非常重要!
- learing_rate是我随便设置的,在实际大家跑模型的时候,请务必按照1.0,1e-3,1e-6,三个节点进行二分调优。
- 如果你直接搬上面代码,妥妥过拟合,请在真实使用过程中,务必根据数据量调整batch的大小,epoch的大小,建议在每次传递完成后加上
tf.nn.dropout
进行dropout。 - 如果数据量连10万量级都不到,我还是建议用机器学习的方法,xgboost+lr,mixed logistics regression等等都是不错的方法。
好了,最后附上全量代码的地址Github,希望对大家有所帮助。