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模型原理与案例实现相关推荐

  1. 统计学习方法笔记(四)-最大熵模型原理及python实现

    最大熵模型 最大熵模型 最大熵原理 最大熵模型 代码实现 案例地址 最大熵模型 最大熵模型(maximum entropy model)可以用于二分类,也可以用于多分类.其是由最大熵原理推导实现的,所 ...

  2. MVC原理及案例分析

    MVC原理及案例分析 关于MVC MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用一种业务逻辑 ...

  3. 阅读《大型网站技术架构:核心原理与案例分析》第五、六、七章

    阅读<大型网站技术架构:核心原理与案例分析>第五.六.七章,结合我们的系统,分析如何增加相应的功能,提高系统的可用性和易用性. 这三章主要讲述的是网站的可用性.伸缩性和可扩展性. 高可用架 ...

  4. SQL注入基础原理与案例(详细总结)

    SQL注入基础原理与案例 一.前言 二.漏洞概述及危害 1.漏洞概述 2.漏洞危害 3.漏洞防范 三.SQL注入 1.SQL注入方式 (1)信息收集 (2)数据注入 (3)高权限注入 2.判断是否存在 ...

  5. 读书笔记之 大型网站技术架构(核心原理与案例分析)

    前言 坚持看了十几天的书,终于完成了毕业后第一次静下心来,利用业务时间看书并做笔记的成就了.废话不多说,这回看的是一直很膜拜的李智慧大神写的大型网站技术架构-核心原理与案例分析. 简短的读后感 极其推 ...

  6. 分布式计算,大型网站技术架构:核心原理与案例分析

    这个回答,非常详细. 但是,大部分内容,都来自"大型网站技术架构:核心原理与案例分析". 最近,初步看了这本书,觉得写得太好了,比较系统和全面. 不过,我还是不喜欢吹B" ...

  7. 大型网站技术架构:核心原理与案例分析pdf

    下载地址:网盘下载 编辑推荐 编辑 本书作者是阿里巴巴网站构建的亲历者,拥有核心技术部门的一线工作经验,直接体验了大型网站构建与发展过程中的种种生与死,蜕与变,见证了一个网站架构从幼稚走向成熟稳定的历 ...

  8. 大尺度分布式水文模型VIC模型原理与应用

    VIC(Variable Infiltration Capacity)模型是由Washington大学.California大学Berkely分校以及Princeton大学的研究者基于Wood等人的思 ...

  9. 人机交互:虚拟翻书与空中翻书的种类与技术原理及案例展示

    人机交互:虚拟翻书与空中翻书的种类与技术原理及案例展示 对于虚拟翻书与空中翻书,大家如果去过博物馆或展览馆,就对它不陌生了.虚拟翻书系统-虚拟电子超媒体技术书,又叫虚拟翻书.感应翻书.电子翻书.互动翻 ...

最新文章

  1. 变电站越级跳闸的几大原因(转载)
  2. Python操作excel文件创建workbook和批量创建Sheet
  3. [vue] DOM渲染在哪个周期中就已经完成了?
  4. html页面 sql注入,使用html仅阻止SQL注入
  5. docker 保存 环境持久化_为什么 Docker 适合微服务架构?
  6. BZOJ5329:[SDOI2018]战略游戏(圆方树,虚树)
  7. 不会真有人觉得聊天机器人难吧——使用BERT加载预训练模型得到中文句子向量
  8. 自动驾驶 9-4: 改进的 EKF - 错误状态扩展卡尔曼滤波器 An Improved EKF - The Error State Extended Kalman Filter
  9. 计算机2017语言排名,2017计算机编程语言排行榜 java依然独占鳌头
  10. IBM ServerGuide 10.2
  11. 哈希摘要、证书、对称密钥、公私密钥应用场景梳理
  12. [生存志] 第91节 鬼谷捭阖之策
  13. flink sql 报错:FlinkRuntimeException: Exceeded checkpoint tolerable failure threshold
  14. 输出字符串中匹配最多的括号数
  15. 学渣的刷题之旅 leetcode刷题 20.有效的括号
  16. vs2017开发ActiveX(主讲OCX)(七)、方法
  17. 关于对《三只松鼠》网站的诊断报告
  18. 招聘 | 上海交通大学医学院附属精神卫生中心诚招科研助理
  19. matlab变换图片四个角黑色,在Matlab的四个角点之间显示图像
  20. 计算机组成原理 程序计数器和寄存器的长度

热门文章

  1. js中对象、数组的深拷贝
  2. python 爬虫 cookies设置,获取登陆后界面。
  3. 软件测试工程师 面试100题 基础篇
  4. 2023年全国最新二级建造师精选真题及答案9
  5. php查找/过滤一段文字中的违禁词敏感词
  6. 已知液面高度怎么计算圆形管道内液体截面积(圆弧面)的方法成都仪器开发
  7. 208亿背后的“秘密” 1
  8. 火牛单片机rtc时钟配置_RTC硬件时钟设置修改
  9. SEO时关键词应该怎么选
  10. 什么是 RPC?RPC原理是什么?