O2O场景下的推荐排序模型:
推荐系统遇上深度学习(五)--Deep&Cross Network模型理论和实践
推荐系统遇上深度学习系列:
推荐系统遇上深度学习(一)--FM模型理论和实践:https://www.jianshu.com/p/152ae633fb00
推荐系统遇上深度学习(二)--FFM模型理论和实践:https://www.jianshu.com/p/781cde3d5f3d
推荐系统遇上深度学习(三)--DeepFM模型理论和实践:
https://www.jianshu.com/p/6f1c2643d31b
推荐系统遇上深度学习(四)--多值离散特征的embedding解决方案:https://www.jianshu.com/p/4a7525c018b2
1、原理
Deep&Cross Network模型我们下面将简称DCN模型:
一个DCN模型从嵌入和堆积层开始,接着是一个交叉网络和一个与之平行的深度网络,之后是最后的组合层,它结合了两个网络的输出。完整的网络模型如图:
嵌入和堆叠层
我们考虑具有离散和连续特征的输入数据。在网络规模推荐系统中,如CTR预测,输入主要是分类特征,如“country=usa”。这些特征通常是编码为独热向量如“[ 0,1,0 ]”;然而,这往往导致过度的高维特征空间大的词汇。
为了减少维数,我们采用嵌入过程将这些离散特征转换成实数值的稠密向量(通常称为嵌入向量):
然后,我们将嵌入向量与连续特征向量叠加起来形成一个向量:
拼接起来的向量X0将作为我们Cross Network和Deep Network的输入
Cross Network
交叉网络的核心思想是以有效的方式应用显式特征交叉。交叉网络由交叉层组成,每个层具有以下公式:
一个交叉层的可视化如图所示:
可以看到,交叉网络的特殊结构使交叉特征的程度随着层深度的增加而增大。多项式的最高程度(就输入X0而言)为L层交叉网络L + 1。如果用Lc表示交叉层数,d表示输入维度。然后,参数的数量参与跨网络参数为:d * Lc * 2 (w和b)
交叉网络的少数参数限制了模型容量。为了捕捉高度非线性的相互作用,模型并行地引入了一个深度网络。
Deep Network
深度网络就是一个全连接的前馈神经网络,每个深度层具有如下公式:
Combination Layer
链接层将两个并行网络的输出连接起来,经过一层全链接层得到输出:
如果采用的是对数损失函数,那么损失函数形式如下:
总结
DCN能够有效地捕获有限度的有效特征的相互作用,学会高度非线性的相互作用,不需要人工特征工程或遍历搜索,并具有较低的计算成本。
论文的主要贡献包括:
1)提出了一种新的交叉网络,在每个层上明确地应用特征交叉,有效地学习有界度的预测交叉特征,并且不需要手工特征工程或穷举搜索。
2)跨网络简单而有效。通过设计,各层的多项式级数最高,并由层深度决定。网络由所有的交叉项组成,它们的系数各不相同。
3)跨网络内存高效,易于实现。
4)实验结果表明,交叉网络(DCN)在LogLoss上与DNN相比少了近一个量级的参数量。
这个是从论文中翻译过来的,哈哈。
2、实现解析
本文的代码根据之前DeepFM的代码进行改进,我们只介绍模型的实现部分,其他数据处理的细节大家可以参考我的github上的代码:
https://github.com/princewen/tensorflow_practice/tree/master/Basic-DCN-Demo
数据下载地址:https://www.kaggle.com/c/porto-seguro-safe-driver-prediction
不去下载也没关系,我在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.numeric_value = tf.placeholder(tf.float32,[None,None],name='num_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')
可以看到,这里与DeepFM相比,一个明显的变化是将离散特征和连续特征分开,连续特征不在转换成embedding进行输入,所以我们的输入共有五部分。
feat_index是离散特征的一个序号,主要用于通过embedding_lookup选择我们的embedding。feat_value是对应离散特征的特征值。numeric_value是我们的连续特征值。label是实际值。还定义了两个dropout来防止过拟合。
权重构建
权重主要包含四部分,embedding层的权重,cross network中的权重,deep network中的权重以及最后链接层的权重,我们使用一个字典来表示:
def _initialize_weights(self):
weights = dict()#embeddings
weights['feature_embeddings'] = tf.Variable(
tf.random_normal([self.cate_feature_size,self.embedding_size],0.0,0.01),
name='feature_embeddings')
weights['feature_bias'] = tf.Variable(tf.random_normal([self.cate_feature_size,1],0.0,1.0),name='feature_bias')#deep layers
num_layer = len(self.deep_layers)
glorot = np.sqrt(2.0/(self.total_size + self.deep_layers[0]))weights['deep_layer_0'] = tf.Variable(
np.random.normal(loc=0,scale=glorot,size=(self.total_size,self.deep_layers[0])),dtype=np.float32
)
weights['deep_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["deep_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["deep_bias_%d" % i] = tf.Variable(
np.random.normal(loc=0, scale=glorot, size=(1, self.deep_layers[i])),
dtype=np.float32) # 1 * layer[i]for i in range(self.cross_layer_num):
weights["cross_layer_%d" % i] = tf.Variable(
np.random.normal(loc=0, scale=glorot, size=(self.total_size,1)),
dtype=np.float32)
weights["cross_bias_%d" % i] = tf.Variable(
np.random.normal(loc=0, scale=glorot, size=(self.total_size,1)),
dtype=np.float32) # 1 * layer[i]# final concat projection layer
input_size = self.total_size + self.deep_layers[-1]
glorot = np.sqrt(2.0/(input_size + 1))
weights['concat_projection'] = tf.Variable(np.random.normal(loc=0,scale=glorot,size=(input_size,1)),dtype=np.float32)
weights['concat_bias'] = tf.Variable(tf.constant(0.01),dtype=np.float32)return weights
计算网络输入
这一块我们要计算两个并行网络的输入X0,我们需要将离散特征转换成embedding,同时拼接上连续特征:
# model
self.embeddings = tf.nn.embedding_lookup(self.weights['feature_embeddings'],self.feat_index) # N * F * K
feat_value = tf.reshape(self.feat_value,shape=[-1,self.field_size,1])
self.embeddings = tf.multiply(self.embeddings,feat_value)self.x0 = tf.concat([self.numeric_value,
tf.reshape(self.embeddings,shape=[-1,self.field_size * self.embedding_size])]
,axis=1)
Cross Network
根据论文中的计算公式,一步步计算得到cross network的输出:
# cross_part
self._x0 = tf.reshape(self.x0, (-1, self.total_size, 1))
x_l = self._x0
for l in range(self.cross_layer_num):
x_l = tf.tensordot(tf.matmul(self._x0, x_l, transpose_b=True),
self.weights["cross_layer_%d" % l],1) + self.weights["cross_bias_%d" % l] + x_lself.cross_network_out = tf.reshape(x_l, (-1, self.total_size))
Deep Network
这一块就是一个多层全链接神经网络:
self.y_deep = tf.nn.dropout(self.x0,self.dropout_keep_deep[0])
for i in range(0,len(self.deep_layers)):
self.y_deep = tf.add(tf.matmul(self.y_deep,self.weights["deep_layer_%d" %i]), self.weights["deep_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])
Combination Layer
最后将两个网络的输出拼接起来,经过一层全链接得到最终的输出:
# concat_part
concat_input = tf.concat([self.cross_network_out, self.y_deep], axis=1)self.out = tf.add(tf.matmul(concat_input,self.weights['concat_projection']),self.weights['concat_bias'])
定义损失
这里我们可以选择logloss或者mse,并加上L2正则项:
# loss
if self.loss_type == "logloss":
self.out = tf.nn.sigmoid(self.out)
self.loss = tf.losses.log_loss(self.label, self.out)
elif self.loss_type == "mse":
self.loss = tf.nn.l2_loss(tf.subtract(self.label, self.out))
# l2 regularization on weights
if self.l2_reg > 0:
self.loss += tf.contrib.layers.l2_regularizer(
self.l2_reg)(self.weights["concat_projection"])
for i in range(len(self.deep_layers)):
self.loss += tf.contrib.layers.l2_regularizer(
self.l2_reg)(self.weights["deep_layer_%d" % i])
for i in range(self.cross_layer_num):
self.loss += tf.contrib.layers.l2_regularizer(
self.l2_reg)(self.weights["cross_layer_%d" % i])
剩下的代码就不介绍啦!
好啦,本文只是提供一个引子,有关DCN的知识大家可以更多的进行学习呦。
参考文章:
1、https://blog.csdn.net/roguesir/article/details/79763204
2、论文:https://arxiv.org/abs/1708.05123
O2O场景下的推荐排序模型:的更多相关文章
- 美团在O2O场景下的广告营销
美团作为中国最大的在线本地生活服务平台,覆盖了餐饮.酒店.旅行.休闲娱乐.外卖配送等方方面面生活场景,连接了数亿用户和数百万商户.如何帮助本地商户开展在线营销,使得他们能快速有效地触达目标用户群体提升 ...
- Entity Framework:如果允许模型处于非法状态,在某些场景下,记得清空DbContext
Entity Framework:如果允许模型处于非法状态,在某些场景下,记得清空DbContext 背景 之前写过两篇文章介绍模型的合法性: DDD:关于模型的合法性,Entity.IsValid( ...
- 深度排序模型概述(一)Wide&Deep/xDeepFM
本文记录几个在广告和推荐里面rank阶段常用的模型.广告领域机器学习问题的输入其实很大程度了影响了模型的选择,因为输入一般维度非常高,稀疏,同时包含连续性特征和离散型特征.模型即使到现在DeepFM类 ...
- 大厂技术实现 | 腾讯信息流推荐排序中的并联双塔CTR结构 @推荐与计算广告系列
作者:韩信子@ShowMeAI,Joan@腾讯 地址:http://www.showmeai.tech/article-detail/tencent-ctr 声明:版权所有,转载请联系平台与作者并注明 ...
- CI Weekly #11 | 微服务场景下的自动化测试与持续部署
又一周过去了,最近我们的工程师正在搞一个"大事情" --「[flow.ci](http://flow.ci/?utm_source=bokeyuan&utm_medium= ...
- 亿级流量场景下,大型缓存架构设计实现【1】---redis篇
*****************开篇介绍**************** -------------------------------------------------------------- ...
- 10.多shard场景下relevence score可能不准确
主要知识点 多shard场景下relevence score可能不准确的原因 多shard场景下relevence score可能不准确解决方式 一.多shard场景下relevance sc ...
- 难道主键除了自增就是GUID?支持k8s等分布式场景下的id生成器了解下
背景 主键(Primary Key),用于唯一标识表中的每一条数据.所以,一个合格的主键的最基本要求应该是唯一性. 那怎么保证唯一呢?相信绝大部分开发者在刚入行的时候选择的都是数据库的自增id,因为这 ...
- 硬核测试:Pulsar 与 Kafka 在金融场景下的性能分析
背景 Apache Pulsar 是下一代分布式消息流平台,采用计算存储分层架构,具备多租户.高一致.高性能.百万 topic.数据平滑迁移等诸多优势.越来越多的企业正在使用 Pulsar 或者尝试将 ...
随机推荐
- goroutine使用
Goroutine是建立在线程之上的轻量级的抽象.它允许我们以非常低的代价在同一个地址空间中并行地执行多个函数或者方法.相比于线程,它的创建和销毁的代价要小很多,并且它的调度是独立于线程的.在gola ...
- wcf callback在主线程被调用
记得当时往wcf迁移了部分service以后,tester发现有时候系统会没有任何反应,cpu占用倒是没有问题,可就是做不了事情. 感觉是哪里死锁了,但也不是每次都能再现,后来发现如果把callbac ...
- Fink| CEP
什么是复杂事件CEP? 一个或多个由简单事件构成的事件流通过一定的规则匹配,然后输出用户想得到的数据,满足规则的复杂事件. 特征: 目标:从有序的简单事件流中发现一些高阶特征 输入:一个或多个由简单事 ...
- CF-1238 C.Standard Free2play
题目大意: 有一个墙,高度为h,在每一个高度处都有一个踏板,有的踏板是隐藏着的,有的是伸出来的,小人站在h高度处(题目保证h高度处的踏板一定是伸出来的),这个小人每站到一个踏板上,就可以点一个开关,将 ...
- 【2019.8.7 慈溪模拟赛 T2】环上随机点(ran)(自然算法)
简单声明 我是蒟蒻不会推式子... 所以我用的是乱搞做法... 大自然的选择 这里我用的乱搞做法被闪指导赐名为"自然算法",对于这种输入信息很少的概率题一般都很适用. 比如此题,对 ...
- Paper | Making a "Completely Blind" Image Quality Analyzer
目录 1. 技术细节 1.1 NSS特征 1.2 选择锐利块来计算NSS 1.3 一张图像得到36个特征 1.4 用MVG建模这36个特征 1.5 NIQE指标 2. 实验 质量评估大佬AC Bovi ...
- Paper | Deep Residual Learning for Image Recognition
目录 1. 故事 2. 残差学习网络 2.1 残差块 2.2 ResNet 2.3 细节 3. 实验 3.1 短连接网络与plain网络 3.2 Projection解决短连接维度不匹配问题 3.3 ...
- AChartEngine折线图实例
最近做项目要用到图表,在网上找相关的解决方案找了很久,搜到最多的就是这个框架,所以就开始研究下怎么使用,首先研究的就是折线图,如是做了一个实例. AChartEngine下载地址:http://cod ...
- JAVA基础系列:Object类
1. 万物皆对象 1. JVM在编译源代码时,在遇到没有继承Object的对象的时候,编译器会默认指定一个默认的父类Object 2. Object 和接口的关系,接口是否继承Object?接口没有继 ...
- Ubuntu安装有道词典
dpkg -i youdao-dict.deb正常安装 会报一堆依赖关系的错误, 1.更新系统 #更新系统 apt-get update apt-get dist-upgrade 2.对每一个未安装的 ...