公众号

关注公众号:推荐算法工程师,输入"进群",加入交流群,和小伙伴们一起讨论机器学习,深度学习,推荐算法.

前言

论文地址:https://arxiv.org/pdf/1601.02376.pdf
论文开源代码(基于Theano实现):https://github.com/wnzhang/deep-ctr
参考代码(无FM初始化):https://github.com/Sherryuu/CTR-of-deep-learning
重构代码:https://github.com/wyl6/Recommender-Systems-Samples/tree/master/RecSys%20And%20Deep%20Learning/DNN/fnn

FNN = FM+MLP

FM在到底初始化什么

FNN首先使用FM初始化输入embedding层,然后使用MLP来进行CTR预估,具体怎么做的呢?看论文中的一张图:

单看图来理解的有一定的迷惑性,加上z的输出结公式就更有迷惑性了:

其中wi为第i个field经FM初始化得到的一次项系数,vi就是隐向量,K为隐向量vi的维度.如果初始化的是z,那Dense Real Layer显示的结果显示每个field只有1个wi和vi,这不对啊,之前看FM的时候每个field的每个特征都对应一个wi和vi,这是怎么回事呢?实际上,FM初始化的是系数向量x到dense layer之间的权重矩阵W:

我给大家画张图,假设样本有3个field,3个field维度分别为N1,N2,N3,那我们经过FM初始化可以获得N=N1+N2+N3个隐向量和一次项系数w,用它们组成权重矩阵W0:

但是作者并没有直接将x和权重矩阵相乘来计算z,这样计算出的结果是K+1维,相当于把样本的所有非零特征对应的K+1维向量加起来.降维太过了,数据压缩太厉害总会损失一部分信息,因此作者将每个field分别相乘得到K+1维结果,最后把所有field的结果串联起来:

这样初始化时,由于样本每个field只有一个非零值,第i个field得到的z值就是非零特征对应的w和v:

FNN的流程

了解FM初始化的是权重矩阵W0后,FNN流程就清楚了,从后往前看,一步到位:

代码实战

数据格式

数据共有22个field,各field中属性取值的可枚举个数为:

FIELD_SIZES = [1037, 151, 59, 1603, 4, 333, 77890, 1857, 9, 8, 4, 7, 22, 3, 92, 56, 4, 920, 38176, 240, 2697, 4]

样本x则被划分为:

由于是模拟CTR预估,所以标签y是二分类的,实验中y∈{0,1}.

参数保存与加载

FNN源代码中没有FM初始化这部分,只有MLP,博主自己加上了.

参数保存,常见的就是使用tf.train.Saver.保存所有模型的参数和值,然后加载部分参数或全部参数;或者保存指定参数和参数值,然后加载想要的参数和参数的值.为了和源代码借口保持一致,我们并没有使用tf.train.Saver,而是直接获取参数值,构造一个字典,保存到本地:

def dump(self, model_path):
#        weight = [self.vars['w'], self.vars['v'], self.vars['b']]
#        saver = tf.train.Saver(weight)
#        saver.save(self.sess, model_path)
#        print(self.sess.run(self.vars['w']))
#        print(self.sess.run('w:0'))
#        print(self.vars['w'])
#        for i,j in self.vars.items():
#            print(i, j)
#            print(self.sess.run(j))var_map = {}for name, var in self.vars.items():print('----------------',name, var)var_map[name] = self.sess.run(var)pkl.dump(var_map, open(model_path, 'wb'))print('model dumped at', model_path)load_var_map = pkl.load(open(model_path, 'rb'))print('load_var_map[w]', load_var_map['w'])

pkl.dump可以保存多种类型的数据,用pkl.load加载,下面是加载的部分:

            feature_size = sum(field_sizes)init_vars.append(('w', [feature_size, 1], 'fm', dtype))init_vars.append(('v', [feature_size, embed_size], 'fm', dtype))init_vars.append(('b', [1, ], 'fm', dtype))self.vars = utils.init_var_map(init_vars, init_path)init_w0 = tf.concat([self.vars['w'],self.vars['v']], 1)lower, upper = 0, field_sizes[0]for i in range(num_inputs):if(i != 0):lower, upper = upper, upper+field_sizes[i]self.vars['embed_%d' % i] = init_w0[lower:upper]w0 = [self.vars['embed_%d' % i] for i in range(num_inputs)]

其中的init_var_map函数如下:

def init_var_map(init_vars, init_path=None):if init_path is not None:load_var_map = pkl.load(open(init_path, 'rb'))print('load variable map from', init_path, load_var_map.keys())var_map = {}for var_name, var_shape, init_method, dtype in init_vars:if init_method == 'zero':var_map[var_name] = tf.Variable(tf.zeros(var_shape, dtype=dtype), name=var_name, dtype=dtype)elif init_method == 'one':var_map[var_name] = tf.Variable(tf.ones(var_shape, dtype=dtype), name=var_name, dtype=dtype)elif init_method == 'normal':var_map[var_name] = tf.Variable(tf.random_normal(var_shape, mean=0.0, stddev=STDDEV, dtype=dtype),name=var_name, dtype=dtype)elif init_method == 'tnormal':var_map[var_name] = tf.Variable(tf.truncated_normal(var_shape, mean=0.0, stddev=STDDEV, dtype=dtype),name=var_name, dtype=dtype)elif init_method == 'uniform':var_map[var_name] = tf.Variable(tf.random_uniform(var_shape, minval=MINVAL, maxval=MAXVAL, dtype=dtype),name=var_name, dtype=dtype)elif init_method == 'xavier':maxval = np.sqrt(6. / np.sum(var_shape))minval = -maxvalvalue = tf.random_uniform(var_shape, minval=minval, maxval=maxval, dtype=dtype)var_map[var_name] = tf.Variable(value, name=var_name, dtype=dtype)elif isinstance(init_method, int) or isinstance(init_method, float):var_map[var_name] = tf.Variable(tf.ones(var_shape, dtype=dtype) * init_method, name=var_name, dtype=dtype)elif init_method == 'fm':var_map[var_name] = tf.Variable(load_var_map[var_name], name=var_name, dtype=dtype)else:print('BadParam: init method', init_method)return var_map

模型如何使用

调试的过程如下,首先设置algo='fm',获得一次项系数w和隐向量v,保存参数;然后algo='fnn',进行CTR预测.

# algo = 'fm'
algo = 'fnn'
if algo in {'fnn','anfm','amlp','ccpm','pnn1','pnn2'}:train_data = utils.split_data(train_data)test_data = utils.split_data(test_data)tmp = []for x in field_sizes:if x > 0:tmp.append(x)field_sizes = tmpprint('remove empty fields', field_sizes)if algo == 'fm':fm_params = {'input_dim': input_dim,'factor_order': 128,'opt_algo': 'gd','learning_rate': 0.1,'l2_w': 0,'l2_v': 0,}print(fm_params)model = FM(**fm_params)
elif algo == 'fnn':fnn_params = {'field_sizes': field_sizes,'embed_size': 129,'layer_sizes': [500, 1],'layer_acts': ['relu', None],'drop_out': [0, 0],'opt_algo': 'gd','learning_rate': 0.1,'embed_l2': 0,'layer_l2': [0, 0],'random_seed': 0,'init_path':pkl_path,}print(fnn_params)model = FNN(**fnn_params)

运行结果

FNN使用‘Xavier’初始化时:

        for i in range(num_inputs):init_vars.append(('embed_%d' % i, [field_sizes[i], embed_size], 'xavier', dtype))

运行10次效果为:

[0]     training...
[0]     evaluating...
[0]     loss (with l2 norm):0.358097    train-auc: 0.610657     eval-auc: 0.661392
[1]     training...
[1]     evaluating...
[1]     loss (with l2 norm):0.350506    train-auc: 0.624879     eval-auc: 0.679986
[2]     training...
[2]     evaluating...
[2]     loss (with l2 norm):0.348581    train-auc: 0.631834     eval-auc: 0.688470
[3]     training...
[3]     evaluating...
[3]     loss (with l2 norm):0.347268    train-auc: 0.637031     eval-auc: 0.694607
[4]     training...
[4]     evaluating...
[4]     loss (with l2 norm):0.346279    train-auc: 0.641287     eval-auc: 0.699670
[5]     training...
[5]     evaluating...
[5]     loss (with l2 norm):0.345490    train-auc: 0.644798     eval-auc: 0.703892
[6]     training...
[6]     evaluating...
[6]     loss (with l2 norm):0.344828    train-auc: 0.647727     eval-auc: 0.707407
[7]     training...
[7]     evaluating...
[7]     loss (with l2 norm):0.344262    train-auc: 0.650155     eval-auc: 0.710297
[8]     training...
[8]     evaluating...
[8]     loss (with l2 norm):0.343769    train-auc: 0.652261     eval-auc: 0.712707
[9]     training...
[9]     evaluating...
[9]     loss (with l2 norm):0.343332    train-auc: 0.654116     eval-auc: 0.714787

FM迭代50次后初始化:FNN运行结果为:

[0]     training...
[0]     evaluating...
[0]     loss (with l2 norm):0.361066    train-auc: 0.607293     eval-auc: 0.642668
[1]     training...
[1]     evaluating...
[1]     loss (with l2 norm):0.353281    train-auc: 0.634517     eval-auc: 0.679833
[2]     training...
[2]     evaluating...
[2]     loss (with l2 norm):0.350498    train-auc: 0.640884     eval-auc: 0.688085
[3]     training...
[3]     evaluating...
[3]     loss (with l2 norm):0.347988    train-auc: 0.648423     eval-auc: 0.696806
[4]     training...
[4]     evaluating...
[4]     loss (with l2 norm):0.345739    train-auc: 0.657166     eval-auc: 0.706803
[5]     training...
[5]     evaluating...
[5]     loss (with l2 norm):0.343678    train-auc: 0.665929     eval-auc: 0.716429
[6]     training...
[6]     evaluating...
[6]     loss (with l2 norm):0.341738    train-auc: 0.674693     eval-auc: 0.725318
[7]     training...
[7]     evaluating...
[7]     loss (with l2 norm):0.339869    train-auc: 0.682893     eval-auc: 0.733139
[8]     training...
[8]     evaluating...
[8]     loss (with l2 norm):0.338055    train-auc: 0.690134     eval-auc: 0.739590
[9]     training...
[9]     evaluating...
[9]     loss (with l2 norm):0.336269    train-auc: 0.696557     eval-auc: 0.744801

auc值变大,明显得到改善。

参考代码(无FM初始化):https://github.com/Sherryuu/CTR-of-deep-learning
重构代码:https://github.com/wyl6/Recommender-Systems-Samples/tree/master/RecSys%20And%20Deep%20Learning/DNN/fnn

参考

https://arxiv.org/pdf/1601.02376.pdf

基于深度学习的推荐(二):基于FM初始化的FNN相关推荐

  1. 基于深度学习的推荐系统研究

    基于深度学习的推荐系统研究 论文信息:北京邮电大学   陈达  14年硕毕论 目的:深度网络学习算法应用到推荐系统 . 为此工作: 1)研究分析基于内容的推荐系统和基于协同过滤的推荐系统,包括基于相似 ...

  2. 工业界推荐系统必读论文:基于深度学习的推荐模型——DLRM

    作者丨纪厚业 单位丨北京邮电大学博士生 研究方向丨异质图神经网络及其应用 引言 推荐系统尤其是深度推荐系统已经在工业界得到了广泛应用,尤其是在电商场景下(如淘宝和京东的商品推荐).一个好的工业级推荐系 ...

  3. 基于深度学习的简单二分类(招聘信息的真假)

    招聘数据真假分类 此次机器学习课程大作业-招聘数据真假分类,是一个二分类问题.训练集中共有14304个样本,每个样本有18个特征,目标是判断不含有标签的招聘信息的真假性. 利用Pandas读取训练集和 ...

  4. 基于深度学习的搜索、推荐、广告系统最全最新论文分享

    推荐系统是有效的信息过滤工具,由于互联网接入的增加.个性化趋势和计算机用户习惯的改变,这种工具非常普遍.尽管现有的推荐系统成功地产生了不错的推荐,但是它们仍然面临着诸如准确性.可伸缩性和冷启动等挑战. ...

  5. 推荐算法普查(基于深度学习)

    摘要 深度学习已经成为推荐算法研究者们理想的选择.随着机器学习领域研究兴趣的强力增长,已经很难跟踪谁才是TopN推荐问题的最先进算法.与此同时,最近有几篇文章指出现在机器学习领域实践方面的一些问题,比 ...

  6. 基于深度学习和传统算法的人体姿态估计,技术细节都讲清楚了

    作者 | 站长 pursueYfuture 来源 | AI专栏(ID: pursue-Y-future) 计算机视觉的一大研究热点是人体姿态估计,还有很多问题急需解决,比如遮挡,交互等等.在最近的CV ...

  7. 看完这篇AI算法和笔记,跟面试官扯皮没问题了 | 基于深度学习和传统算法的人体姿态估计

    点击蓝色"AI专栏"关注我哟 重磅干货,第一时间送达 这是站长的第 41 篇原创优质长文 前几天站长写的一篇的文章[基于深度学习算法和传统立体匹配算法的双目立体视觉]大受好评.这次 ...

  8. 基于深度学习的VQA(视觉问答)技术

    深度学习大讲堂致力于推送人工智能,深度学习方面的最新技术,产品以及活动.请关注我们的知乎专栏! 视觉问答导读 视觉问答(Visual Question Answering,VQA),是一种涉及计算机视 ...

  9. 基于深度学习的推荐系统:综述与新视角

    原文:Deep Learning based Recommender System: A Survey and New Perspectives 作者:张帅, 新南威尔士大学 翻译:沈春旭,清华大学 ...

最新文章

  1. keepalived高可用反向代理的nginx
  2. Android开发之浅谈Service的基本概况和常见问题
  3. 洛谷P1102 A-B
  4. JS+CSS实现Dock menu(MacOS菜单导航效果)
  5. 安全测试 - XSS如何防御
  6. 自动控制原理6.3---串联校正
  7. python商品总数抹零_销售发货单
  8. 鼎捷t100架构_鼎捷 T100 ERP 系统.pdf
  9. SEO自动外链工具推荐:站群推广利器SEO,在线批量发外链让新站快速收录
  10. python提取格式化日志
  11. CAD注记转ArcGIS注记并文字内容挂接进属性表(附插件下载)
  12. 2018中国服务器市场出货量年成长23%,华为出货创新高
  13. 将Linux下文件目录使用Nginx代理使浏览器可访问
  14. 人工智能会用绝对的力量,用更高层次的方式直接进入你的工作行业
  15. 如何获取网易云音频地址
  16. java编程实现;猜单词游戏
  17. Web(七)CSS页面布局-网页布局页面的制作
  18. 深度解析Android Q cutout刘海屏
  19. 2020曼彻斯特大学计算机2020,2020年曼彻斯特大学申请要求完整版
  20. springMVC中 Controller层为什么可以用map来传输数据

热门文章

  1. 编码:隐匿在计算机背后的语言(1-3章)
  2. MVP模式在携程酒店的应用和扩展
  3. steam(wallpaperEngine)双屏,比较cool的桌面推荐
  4. 【uniapp】H5扫码方案,解决uni.scanCode不支持H5的问题
  5. 大学物理实验报告4——漫反射物体三维的全息摄影
  6. 车载蓝牙PIN码是什么
  7. doccano 安装部署及其使用
  8. php写入文本乱码,php写入txt乱码
  9. 写出常用的5个linux命令 并解释,Linux系统介绍(五)常用命令
  10. 可扩展性对英特尔®至强处理器意味着什么