预计阅读时间10分钟

引言

在CTR预估中,为了解决稀疏特征的问题,学者们提出了FM模型来建模特征之间的交互关系。但是FM模型只能表达特征之间两两组合之间的关系,无法建模两个特征之间深层次的关系或者说多个特征之间的交互关系,因此学者们通过Deep Network来建模更高阶的特征之间的关系。

因此 FM和深度网络DNN的结合也就成为了CTR预估问题中主流的方法。有关FM和DNN的结合有两种主流的方法,并行结构和串行结构。两种结构的理解以及实现如下表所示:

今天介绍的NFM模型(Neural Factorization Machine),便是串行结构中一种较为简单的网络模型。

NFM模型介绍

我们首先来回顾一下FM模型,FM模型用n个隐变量来刻画特征之间的交互关系。这里要强调的一点是,n是特征的总数,是one-hot展开之后的,比如有三组特征,两个连续特征,一个离散特征有5个取值,那么n=7而不是n=3.

顺便回顾一下化简过程:

可以看到,不考虑最外层的求和,我们可以得到一个K维的向量。

对于NFM模型,目标值的预测公式变为:

其中,f(x)是用来建模特征之间交互关系的多层前馈神经网络模块,架构图如下所示:

Embedding Layer和我们之间几个网络是一样的,embedding 得到的vector其实就是我们在FM中要学习的隐变量v。

Bi-Interaction Layer名字挺高大上的,其实它就是计算FM中的二次项的过程,因此得到的向量维度就是我们的Embedding的维度。最终的结果是:

Hidden Layers就是我们的DNN部分,将Bi-Interaction Layer得到的结果接入多层的神经网络进行训练,从而捕捉到特征之间复杂的非线性关系。

在进行多层训练之后,将最后一层的输出求和同时加上一次项和偏置项,就得到了我们的预测输出:

是不是很简单呢,哈哈。

代码实战

终于到了激动人心的代码实战环节了,本文的代码有不对的的地方或者改进之处还望大家多多指正。

本文的github地址为:
https://github.com/princewen/tensorflow_practice/tree/master/recommendation/Basic-NFM-Demo

本文的代码根据之前DeepFM的代码进行改进,我们只介绍模型的实现部分,其他数据处理的细节大家可以参考我的github上的代码.

模型输入

模型的输入主要有下面几个部分:

self.feat_index = tf.placeholder(tf.int32,                         shape=[None,None],                         name='feat_index')self.feat_value = tf.placeholder(tf.float32,                       shape=[None,None],                       name='feat_value')

self.label = tf.placeholder(tf.float32,shape=[None,1],name='label')self.dropout_keep_deep = tf.placeholder(tf.float32,shape=[None],name='dropout_deep_deep')

feat_index是特征的一个序号,主要用于通过embedding_lookup选择我们的embedding。feat_value是对应的特征值,如果是离散特征的话,就是1,如果不是离散特征的话,就保留原来的特征值。label是实际值。还定义了dropout来防止过拟合。

权重构建

权重主要分以下几部分,偏置项,一次项权重,embeddings,以及DNN的权重

def _initialize_weights(self):weights = dict()

#embeddingsweights['feature_embeddings'] = tf.Variable(tf.random_normal([self.feature_size,self.embedding_size],0.0,0.01),name='feature_embeddings')weights['feature_bias'] = tf.Variable(tf.random_normal([self.feature_size,1],0.0,1.0),name='feature_bias')weights['bias'] = tf.Variable(tf.constant(0.1),name='bias')

#deep layersnum_layer = len(self.deep_layers)input_size = self.embedding_sizeglorot = np.sqrt(2.0/(input_size + self.deep_layers[0]))

weights['layer_0'] = tf.Variable(np.random.normal(loc=0,scale=glorot,size=(input_size,self.deep_layers[0])),dtype=np.float32)weights['bias_0'] = tf.Variable(np.random.normal(loc=0,scale=glorot,size=(1,self.deep_layers[0])),dtype=np.float32)

for i in range(1,num_layer):glorot = np.sqrt(2.0 / (self.deep_layers[i - 1] + self.deep_layers[i]))weights["layer_%d" % i] = tf.Variable(    np.random.normal(loc=0, scale=glorot, size=(self.deep_layers[i - 1], self.deep_layers[i])),    dtype=np.float32)  # layers[i-1] * layers[i]weights["bias_%d" % i] = tf.Variable(    np.random.normal(loc=0, scale=glorot, size=(1, self.deep_layers[i])),    dtype=np.float32)  # 1 * layer[i]

return weights

Embedding Layer这个部分很简单啦,是根据feat_index选择对应的weights['feature_embeddings']中的embedding值,然后再与对应的feat_value相乘就可以了:

# Embeddingsself.embeddings = tf.nn.embedding_lookup(self.weights['feature_embeddings'],self.feat_index) # N * F * Kfeat_value = tf.reshape(self.feat_value,shape=[-1,self.field_size,1])self.embeddings = tf.multiply(self.embeddings,feat_value) # N * F * K

Bi-Interaction Layer我们直接根据化简后的结果进行计算,得到一个K维的向量:

# sum-square-partself.summed_features_emb = tf.reduce_sum(self.embeddings, 1)  # None * kself.summed_features_emb_square = tf.square(self.summed_features_emb)  # None * K

# squre-sum-partself.squared_features_emb = tf.square(self.embeddings)self.squared_sum_features_emb = tf.reduce_sum(self.squared_features_emb, 1)  # None * K

# second orderself.y_second_order = 0.5 * tf.subtract(self.summed_features_emb_square, self.squared_sum_features_emb)

Deep Part将Bi-Interaction Layer层得到的结果经过一个多层的神经网络,得到交互项的输出:

self.y_deep = self.y_second_orderfor i in range(0, len(self.deep_layers)):self.y_deep = tf.add(tf.matmul(self.y_deep, self.weights["layer_%d" % i]), self.weights["bias_%d" % i])self.y_deep = self.deep_layers_activation(self.y_deep)self.y_deep = tf.nn.dropout(self.y_deep,    self.dropout_keep_deep[i + 1])

得到预测输出为了得到预测输出,我们还需要两部分,分别是偏置项和一次项:

# first order termself.y_first_order = tf.nn.embedding_lookup(self.weights['feature_bias'], self.feat_index)self.y_first_order = tf.reduce_sum(tf.multiply(self.y_first_order, feat_value), 2)

# biasself.y_bias = self.weights['bias'] * tf.ones_like(self.label)

而我们的最终输出如下:

# outself.out = tf.add_n([tf.reduce_sum(self.y_first_order,axis=1,keep_dims=True),             tf.reduce_sum(self.y_deep,axis=1,keep_dims=True),             self.y_bias])

剩下的代码就不介绍啦!
好啦,本文只是提供一个引子,有关NFM的知识大家可以更多的进行学习呦。

小结

NFM模型将FM与神经网络结合以提升FM捕捉特征间多阶交互信息的能力。根据论文中实验结果,NFM的预测准确度相较FM有明显提升,并且与现有的并行神经网络模型相比,复杂度更低。

NFM本质上还是基于FM,FM会让一个特征固定一个特定的向量,当这个特征与其他特征做交叉时,都是用同样的向量去做计算。这个是很不合理的,因为不同的特征之间的交叉,重要程度是不一样的。因此,学者们提出了AFM模型(Attentional factorization machines),将attention机制加入到我们的模型中,关于AFM的知识,我们下一篇来一探究竟。

原文链接:https://mp.weixin.qq.com/s/4hOHyDN-fDVXi3KV8UX2Cw

查阅更为简洁方便的分类文章以及最新的课程、产品信息,请移步至全新呈现的“LeadAI学院官网”:

www.leadai.org

请关注人工智能LeadAI公众号,查看更多专业文章

大家都在看

LSTM模型在问答系统中的应用

基于TensorFlow的神经网络解决用户流失概览问题

最全常见算法工程师面试题目整理(一)

最全常见算法工程师面试题目整理(二)

TensorFlow从1到2 | 第三章 深度学习革命的开端:卷积神经网络

装饰器 | Python高级编程

今天不如来复习下Python基础

推荐系统遇上深度学习(七)--NFM模型理论和实践相关推荐

  1. 推荐系统遇上深度学习(一)--FM模型理论和实践

    全文共2503字,15张图,预计阅读时间15分钟. FM背景 在计算广告和推荐系统中,CTR预估(click-through rate)是非常重要的一个环节,判断一个商品的是否进行推荐需要根据CTR预 ...

  2. 推荐系统遇上深度学习(八)--AFM模型理论和实践

    预计阅读时间10分钟. 引言 在CTR预估中,为了解决稀疏特征的问题,学者们提出了FM模型来建模特征之间的交互关系.但是FM模型只能表达特征之间两两组合之间的关系,无法建模两个特征之间深层次的关系或者 ...

  3. 推荐系统遇上深度学习(六)--PNN模型理论和实践

    全文共2621字,21张图,预计阅读时间15分钟. 原理 PNN,全称为Product-based Neural Network,认为在embedding输入到MLP之后学习的交叉特征表达并不充分,提 ...

  4. 推荐系统遇上深度学习(二)--FFM模型理论和实践

    全文共1979字,6张图,预计阅读时间12分钟. FFM理论 在CTR预估中,经常会遇到one-hot类型的变量,one-hot类型变量会导致严重的数据特征稀疏的情况,为了解决这一问题,在上一讲中,我 ...

  5. 推荐系统遇上深度学习,9篇阿里推荐论文汇总!

    作者 | 石晓文 转载自小小挖掘机(ID: wAIsjwj) 业界常用的推荐系统主要分为两个阶段,召回阶段和精排阶段,当然有时候在最后还会接一些打散或者探索的规则,这点咱们就不考虑了. 前面九篇文章中 ...

  6. 推荐系统遇上深度学习(三十九)-推荐系统中召回策略演进!

    推荐系统中的核心是从海量的商品库挑选合适商品最终展示给用户.由于商品库数量巨大,因此常见的推荐系统一般分为两个阶段,即召回阶段和排序阶段.召回阶段主要是从全量的商品库中得到用户可能感兴趣的一小部分候选 ...

  7. 推荐系统遇上深度学习(八十七)-[阿里]基于搜索的用户终身行为序列建模

    本文介绍的论文是<Search-based User Interest Modeling with Lifelong Sequential Behavior Data for Click-Thr ...

  8. 知识图谱论文阅读(八)【转】推荐系统遇上深度学习(二十六)--知识图谱与推荐系统结合之DKN模型原理及实现

    学习的博客: 推荐系统遇上深度学习(二十六)–知识图谱与推荐系统结合之DKN模型原理及实现 知识图谱特征学习的模型分类汇总 知识图谱嵌入(KGE):方法和应用的综述 论文: Knowledge Gra ...

  9. 推荐系统遇上深度学习(九十二)-[腾讯]RecSys2020最佳长论文-多任务学习模型PLE

    今天介绍的是腾讯提出的一种新的多任务学习个性化推荐模型,该论文荣获了RecSys2020最佳长论文奖,一起来学习下! 1.背景 多任务学习通过在一个模型中同时学习多个不同的目标,如CTR和CVR,最近 ...

最新文章

  1. 白鹭引擎开发飞机大战详尽教程(四控制飞机移动)
  2. 2016\Province_C_C++_C\1 报纸页数
  3. 【2018.5.12】模拟赛之二-ssl2414 简写单词【字符串】
  4. 修改/etc/resolv.conf又恢复到原来的状态?[转]
  5. Unity3D基础8:C#脚本
  6. pdf转txt出现句子异常中断,如何连接被切断的字符串
  7. 【BZOJ1226】学校食堂(动态规划,状态压缩)
  8. [Linux学习]更改默认启动图形界面或命令行
  9. oracle rollup 排序,oracle分组函数之ROLLUP演示
  10. Python + OpenCv实现视频中的车辆检测计数(车流量统计) (2020.7.15已更新源码)
  11. 2017年6月14日中午 java.io.IOException: Premature EOF
  12. 苹果手机如何深度清理_手机深度清理app
  13. 用Java判断ab大小_比例类数据的差异性检验与AB测试的终止点
  14. 2023浙江师范大学计算机考研信息汇总
  15. 运维常用命令大全,从入门到精通就靠它了!
  16. 修复XAMPP安装过程中 因端口80被占用 Apache无法启动的问题
  17. GetSystemInfo系统信息
  18. BBS论坛项目相关-4:发帖模块
  19. OSError: pydot failed to call GraphViz.Please install GraphViz (https://www.graphviz.org/) and ensur
  20. 【Linux环境搭建】六、Linux(CentOS7)Maven私服搭建Nexus

热门文章

  1. html select设置不选中的值,如何定义 select 默认不选中任何值
  2. 克罗地亚第二狂想曲难度_黄海保级难度增加,将送强力前锋去富力,与建业竞争半个降级名额...
  3. php学生分班,学生分班工具下载
  4. unity shader入门精要_Unity Shader 入门(一):渲染流水线
  5. python输出函数使用_python基本输入输出函数
  6. 计算机原理语言方框图,计算机原理整理原版1.10.docx
  7. Python-接口自动化(七)
  8. Win10 取消桌面快捷键图标
  9. fastJson null字符串转空 null数字转0
  10. Oracle中的单行函数