DeepFM模型原理与案例实现
DeepFM
- 1.模型基本原理
- 1.1 模型结构
- 1.2 模型原理
- 2.Tensorflow实现
- 3.小结
DNN模型和 FM 模型的结合成DeepFM,由wide&deep模型演变而来,FM取代wide的LR模型,解决特征交叉问题。
1.模型基本原理
1.1 模型结构
DeepFM 是由哈工大和华为公司联合提出的深度学习模型,架构示意图:
可以看到,DeepFM 利用了 Wide&Deep 组合模型的思想,用 FM 替换了 Wide&Deep 左边的 Wide 部分,加强了浅层网络部分特征组合的能力,而右边的部分跟 Wide&Deep 的 Deep 部分一样,主要利用多层神经网络进行所有特征的深层处理,最后的输出层是把 FM 部分的输出和 Deep 部分的输出综合起来,产生最后的预估结果。
1.2 模型原理
2.Tensorflow实现
def model_fn(features, labels, mode, params):"""Bulid Model function f(x) for Estimator."""#------超参数的设定----field_size = params["field_size"]feature_size = params["feature_size"]embedding_size = params["embedding_size"]l2_reg = params["l2_reg"]learning_rate = params["learning_rate"]#batch_norm_decay = params["batch_norm_decay"]#optimizer = params["optimizer"]layers = map(int, params["deep_layers"].split(','))dropout = map(float, params["dropout"].split(','))#------权重------FM_B = tf.get_variable(name='fm_bias', shape=[1], initializer=tf.constant_initializer(0.0))FM_W = tf.get_variable(name='fm_w', shape=[feature_size], initializer=tf.glorot_normal_initializer())# FFM_V = tf.get_variable(name='fm_v', shape=[feature_size, embedding_size], initializer=tf.glorot_normal_initializer())# F * E#------build feaure-------feat_ids = features['feat_ids']feat_ids = tf.reshape(feat_ids,shape=[-1,field_size]) # None * f/K * Kfeat_vals = features['feat_vals']feat_vals = tf.reshape(feat_vals,shape=[-1,field_size]) # None * f/K * K#------build f(x)------with tf.variable_scope("First-order"):feat_wgts = tf.nn.embedding_lookup(FM_W, feat_ids) # None * f/K * Ky_w = tf.reduce_sum(tf.multiply(feat_wgts, feat_vals),1) with tf.variable_scope("Second-order"):embeddings = tf.nn.embedding_lookup(FM_V, feat_ids) # None * f/K * K * Efeat_vals = tf.reshape(feat_vals, shape=[-1, field_size, 1]) # None * f/K * K * 1 ?embeddings = tf.multiply(embeddings, feat_vals) #vij*xisum_square = tf.square(tf.reduce_sum(embeddings,1)) # None * K * Esquare_sum = tf.reduce_sum(tf.square(embeddings),1)y_v = 0.5*tf.reduce_sum(tf.subtract(sum_square, square_sum),1) # None * 1with tf.variable_scope("Deep-part"):if FLAGS.batch_norm:#normalizer_fn = tf.contrib.layers.batch_norm#normalizer_fn = tf.layers.batch_normalizationif mode == tf.estimator.ModeKeys.TRAIN:train_phase = True#normalizer_params = {'decay': batch_norm_decay, 'center': True, 'scale': True, 'updates_collections': None, 'is_training': True, 'reuse': None}else:train_phase = False#normalizer_params = {'decay': batch_norm_decay, 'center': True, 'scale': True, 'updates_collections': None, 'is_training': False, 'reuse': True}else:normalizer_fn = Nonenormalizer_params = Nonedeep_inputs = tf.reshape(embeddings,shape=[-1,field_size*embedding_size]) # None * (F*K)for i in range(len(layers)):#if FLAGS.batch_norm:# deep_inputs = batch_norm_layer(deep_inputs, train_phase=train_phase, scope_bn='bn_%d' %i)#normalizer_params.update({'scope': 'bn_%d' %i})deep_inputs = tf.contrib.layers.fully_connected(inputs=deep_inputs, num_outputs=layers[i], \#normalizer_fn=normalizer_fn, normalizer_params=normalizer_params, \weights_regularizer=tf.contrib.layers.l2_regularizer(l2_reg), scope='mlp%d' % i)if FLAGS.batch_norm:deep_inputs = batch_norm_layer(deep_inputs, train_phase=train_phase, scope_bn='bn_%d' %i) #放在RELU之后 https://github.com/ducha-aiki/caffenet-benchmark/blob/master/batchnorm.md#bn----before-or-after-reluif mode == tf.estimator.ModeKeys.TRAIN:deep_inputs = tf.nn.dropout(deep_inputs, keep_prob=dropout[i]) #Apply Dropout after all BN layers and set dropout=0.8(drop_ratio=0.2)#deep_inputs = tf.layers.dropout(inputs=deep_inputs, rate=dropout[i], training=mode == tf.estimator.ModeKeys.TRAIN)y_deep = tf.contrib.layers.fully_connected(inputs=deep_inputs, num_outputs=1, activation_fn=tf.identity, \weights_regularizer=tf.contrib.layers.l2_regularizer(l2_reg), scope='deep_out')y_d = tf.reshape(y_deep,shape=[-1])#sig_wgts = tf.get_variable(name='sigmoid_weights', shape=[layers[-1]], initializer=tf.glorot_normal_initializer())#sig_bias = tf.get_variable(name='sigmoid_bias', shape=[1], initializer=tf.constant_initializer(0.0))#deep_out = tf.nn.xw_plus_b(deep_inputs,sig_wgts,sig_bias,name='deep_out')with tf.variable_scope("DeepFM-out"):#y_bias = FM_B * tf.ones_like(labels, dtype=tf.float32) # None * 1 warning;这里不能用label,否则调用predict/export函数会出错,train/evaluate正常;初步判断estimator做了优化,用不到label时不传y_bias = FM_B * tf.ones_like(y_d, dtype=tf.float32) # None * 1y = y_bias + y_w + y_v + y_dpred = tf.sigmoid(y)predictions={"prob": pred}export_outputs = {tf.saved_model.signature_constants.DEFAULT_SERVING_SIGNATURE_DEF_KEY: tf.estimator.export.PredictOutput(predictions)}# Provide an estimator spec for `ModeKeys.PREDICT`if mode == tf.estimator.ModeKeys.PREDICT:return tf.estimator.EstimatorSpec(mode=mode,predictions=predictions,export_outputs=export_outputs)#------bulid loss------loss = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits=y, labels=labels)) + \l2_reg * tf.nn.l2_loss(FM_W) + \l2_reg * tf.nn.l2_loss(FM_V) #+ \ l2_reg * tf.nn.l2_loss(sig_wgts)# Provide an estimator spec for `ModeKeys.EVAL`eval_metric_ops = {"auc": tf.metrics.auc(labels, pred)}if mode == tf.estimator.ModeKeys.EVAL:return tf.estimator.EstimatorSpec(mode=mode,predictions=predictions,loss=loss,eval_metric_ops=eval_metric_ops)#------bulid optimizer------if FLAGS.optimizer == 'Adam':optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate, beta1=0.9, beta2=0.999, epsilon=1e-8)elif FLAGS.optimizer == 'Adagrad':optimizer = tf.train.AdagradOptimizer(learning_rate=learning_rate, initial_accumulator_value=1e-8)elif FLAGS.optimizer == 'Momentum':optimizer = tf.train.MomentumOptimizer(learning_rate=learning_rate, momentum=0.95)elif FLAGS.optimizer == 'ftrl':optimizer = tf.train.FtrlOptimizer(learning_rate)train_op = optimizer.minimize(loss, global_step=tf.train.get_global_step())# Provide an estimator spec for `ModeKeys.TRAIN` modesif mode == tf.estimator.ModeKeys.TRAIN:return tf.estimator.EstimatorSpec(mode=mode,predictions=predictions,loss=loss,train_op=train_op)
在movie数据集上的模型定义:
item_emb_layer = tf.keras.layers.DenseFeatures([movie_emb_col])(inputs)
user_emb_layer = tf.keras.layers.DenseFeatures([user_emb_col])(inputs)
item_genre_emb_layer = tf.keras.layers.DenseFeatures([item_genre_emb_col])(inputs)
user_genre_emb_layer = tf.keras.layers.DenseFeatures([user_genre_emb_col])(inputs)# FM part, cross different categorical feature embeddings
product_layer_item_user = tf.keras.layers.Dot(axes=1)([item_emb_layer, user_emb_layer])
product_layer_item_genre_user_genre = tf.keras.layers.Dot(axes=1)([item_genre_emb_layer, user_genre_emb_layer])
product_layer_item_genre_user = tf.keras.layers.Dot(axes=1)([item_genre_emb_layer, user_emb_layer])
product_layer_user_genre_item = tf.keras.layers.Dot(axes=1)([item_emb_layer, user_genre_emb_layer])# deep part, MLP to generalize all input features
deep = tf.keras.layers.DenseFeatures(deep_feature_columns)(inputs)
deep = tf.keras.layers.Dense(64, activation='relu')(deep)
deep = tf.keras.layers.Dense(64, activation='relu')(deep)# concatenate fm part and deep part
concat_layer = tf.keras.layers.concatenate([product_layer_item_user, product_layer_item_genre_user_genre,product_layer_item_genre_user, product_layer_user_genre_item, deep], axis=1)
output_layer = tf.keras.layers.Dense(1, activation='sigmoid')(concat_layer)model = tf.keras.Model(inputs, output_lay)
在整个实践的过程中,一个是 FM 部分的构建,另一个是 FM 部分的输出和 Deep 输出的连接。
在构建 FM 部分的时候,先为 FM 部分选择了 4 个用于交叉的类别型特征,分别是用户 ID、电影 ID、用户喜欢的风格和电影自己的风格。接着,使用 Dot layer 把用户特征和电影特征两两交叉,这就完成了 FM 部分的构建。
而 Deep 部分的实现,其实和之前实现过的 Wide&Deep 模型的 Deep 部分完全一样。只不过,最终使用 concatenate 层,去把 FM 部分的输出和 Deep 部分的输出连接起来,输入到输出层的 sigmoid 神经元,从而产生最终的预估分数。
3.小结
DeepFM 模型在解决特征交叉问题上非常有优势,它会使用一个独特的 FM 层来专门处理特征之间的交叉问题。具体来说,就是使用点积、元素积等操作让不同特征之间进行两两组合,再把组合后的结果输入的输出神经元中,这会大大加强模型特征组合的能力。因此,DeepFM 模型相比于 Embedding MLP、Wide&Deep 等模型,往往具有更好的推荐效果。
实现 DeepFM 模型的过程并不困难,我们主要记住三点就可以了:
- 由 FM 和 Deep 两部分组成的;
- 在实现 FM 部分特征交叉层的时候,使用了多个 Dot Product 操作单元完成不同特征的两两交叉;
- Deep 部分则与 Wide&Deep 模型一样,负责所有输入特征的深度拟合,提高模型整体的表达能力
参考:
- DeepFM: A Factorization-Machine based Neural Network for CTR Prediction
- 王喆,深度学习推荐系统
DeepFM模型原理与案例实现相关推荐
- 统计学习方法笔记(四)-最大熵模型原理及python实现
最大熵模型 最大熵模型 最大熵原理 最大熵模型 代码实现 案例地址 最大熵模型 最大熵模型(maximum entropy model)可以用于二分类,也可以用于多分类.其是由最大熵原理推导实现的,所 ...
- MVC原理及案例分析
MVC原理及案例分析 关于MVC MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用一种业务逻辑 ...
- 阅读《大型网站技术架构:核心原理与案例分析》第五、六、七章
阅读<大型网站技术架构:核心原理与案例分析>第五.六.七章,结合我们的系统,分析如何增加相应的功能,提高系统的可用性和易用性. 这三章主要讲述的是网站的可用性.伸缩性和可扩展性. 高可用架 ...
- SQL注入基础原理与案例(详细总结)
SQL注入基础原理与案例 一.前言 二.漏洞概述及危害 1.漏洞概述 2.漏洞危害 3.漏洞防范 三.SQL注入 1.SQL注入方式 (1)信息收集 (2)数据注入 (3)高权限注入 2.判断是否存在 ...
- 读书笔记之 大型网站技术架构(核心原理与案例分析)
前言 坚持看了十几天的书,终于完成了毕业后第一次静下心来,利用业务时间看书并做笔记的成就了.废话不多说,这回看的是一直很膜拜的李智慧大神写的大型网站技术架构-核心原理与案例分析. 简短的读后感 极其推 ...
- 分布式计算,大型网站技术架构:核心原理与案例分析
这个回答,非常详细. 但是,大部分内容,都来自"大型网站技术架构:核心原理与案例分析". 最近,初步看了这本书,觉得写得太好了,比较系统和全面. 不过,我还是不喜欢吹B" ...
- 大型网站技术架构:核心原理与案例分析pdf
下载地址:网盘下载 编辑推荐 编辑 本书作者是阿里巴巴网站构建的亲历者,拥有核心技术部门的一线工作经验,直接体验了大型网站构建与发展过程中的种种生与死,蜕与变,见证了一个网站架构从幼稚走向成熟稳定的历 ...
- 大尺度分布式水文模型VIC模型原理与应用
VIC(Variable Infiltration Capacity)模型是由Washington大学.California大学Berkely分校以及Princeton大学的研究者基于Wood等人的思 ...
- 人机交互:虚拟翻书与空中翻书的种类与技术原理及案例展示
人机交互:虚拟翻书与空中翻书的种类与技术原理及案例展示 对于虚拟翻书与空中翻书,大家如果去过博物馆或展览馆,就对它不陌生了.虚拟翻书系统-虚拟电子超媒体技术书,又叫虚拟翻书.感应翻书.电子翻书.互动翻 ...
最新文章
- 变电站越级跳闸的几大原因(转载)
- Python操作excel文件创建workbook和批量创建Sheet
- [vue] DOM渲染在哪个周期中就已经完成了?
- html页面 sql注入,使用html仅阻止SQL注入
- docker 保存 环境持久化_为什么 Docker 适合微服务架构?
- BZOJ5329:[SDOI2018]战略游戏(圆方树,虚树)
- 不会真有人觉得聊天机器人难吧——使用BERT加载预训练模型得到中文句子向量
- 自动驾驶 9-4: 改进的 EKF - 错误状态扩展卡尔曼滤波器 An Improved EKF - The Error State Extended Kalman Filter
- 计算机2017语言排名,2017计算机编程语言排行榜 java依然独占鳌头
- IBM ServerGuide 10.2
- 哈希摘要、证书、对称密钥、公私密钥应用场景梳理
- [生存志] 第91节 鬼谷捭阖之策
- flink sql 报错:FlinkRuntimeException: Exceeded checkpoint tolerable failure threshold
- 输出字符串中匹配最多的括号数
- 学渣的刷题之旅 leetcode刷题 20.有效的括号
- vs2017开发ActiveX(主讲OCX)(七)、方法
- 关于对《三只松鼠》网站的诊断报告
- 招聘 | 上海交通大学医学院附属精神卫生中心诚招科研助理
- matlab变换图片四个角黑色,在Matlab的四个角点之间显示图像
- 计算机组成原理 程序计数器和寄存器的长度