DeepCrossing

动机

将深度学习架构应用于推荐系统中的模型2016年由微软提出, 完整的解决了特征工程、稀疏向量稠密化, 多层神经网络进行优化目标拟合等一系列深度学习再推荐系统的应用问题。

  • 应用场景
    微软搜索引擎Bing中的搜索广告推荐(用户输入搜索查询进店之后,搜索引擎返回相关结果还返回与搜索词相关的广告)
  • 优化目标
    预测某一广告,用户是否会点击,依旧是点击率预测的问题。
    点击率预测,即CTR预估。CTR(Click-Through-Rate)即点击通过率,是互联网广告常用的术语,指网络广告(图片广告/文字广告/关键词广告/排名广告/视频广告等)的点击到达率,即该广告的实际点击次数(严格的来说,可以是到达目标页面的数量)除以广告的展现量(Show content)。
  • 输入特征
指标 数据类型 如何处理
广告id 类别型特征 one-hot编码
广告预算 数值型特征 归一化处理(进行简单清洗)
广告id id 数值型特征

这个模型在传统神经网络的基础上加入了embedding残差连接等思想,且结构比较简单。

模型结构


提出了一种深度交叉模型(Deep Crossing),它是一种深度神经网络,可以自动地将特征进行组合,生成更优的模型。
输入
一组个体特征,可以是密集的,也可以是稀疏的。
重要的交叉特征由网络隐式发现,网络由嵌入和叠加层,以及残留单元的级联组成。
输出
对这些特性没有显式表示的模型。

相关研究

CNN

深度cnn使用特定于任务的过滤器捕获的特征之间的深度交互

深度语义相似模型Deep Semantic Similarity Model (DSSM)

深度语义相似模型[10]学习一对文本字符串之间的语义相似度,每个文本字符串都由一种称为三字母克的稀疏表示表示。学习算法通过将三字母克嵌入到两个向量中来优化基于余弦距离的目标函数。学习到的嵌入捕获单词和句子的语义,并已被应用于赞助搜索、问题回答和机器翻译,并获得强大的结果。

因子分解机Factorization Machines (FM)

因式分解机(FM)[15]在其一般形式下模型了个体特征之间的d-way交互作用。在输入非常稀疏的情况下,FM显示出比支持向量机更好的结果,但它在密集特征上的表现尚不清楚。

赞助搜索SPONSORED SEARCH

赞助搜索【5】负责在有机搜索结果旁边显示广告。在这个生态系统中有三种主要的代理:用户、广告商和搜索平台。该平台的目标是向用户展示最符合用户意图的广告,主要通过特定的查询来表达。下面是接下来讨论的关键概念

FEATURE REPRESENTATION

Individual Features

  • text feature
  • category
  • counting feature

    除计数特征外,所有引入的特征都是稀疏特征。

Combinatorial Features

模型结构

  • The objective function
    is log loss for our applications but can be easily cus-
    tomized to soft-max or other functions. Log loss is defined
    as:
  1. where iii indexes to the training samples
  2. NNN is the number of samples
  3. yiy_iyi is the per sample label. The label yiy_iyi in the click prediction problem is a user click.
  4. pip_ipi is the output of the one-node Scoring Layer in Fig. 1, which is a Sigmoid function in this case.
  • The Embedding Layer
    对每个特征进行嵌入来转换输入特征。嵌入层由单个神经网络组成,一般形式为:
  1. jjj indexes the individual feature
  2. Xij∈RnjX_{ij} \in R^{n_j}XijRnj is the input feature
  3. WjW_jWj is an mj×njm_j \times n_jmj×njmatrix

Stacking layer

然后输出特征被堆叠(连接)成一个向量作为下一层的输入:

  • 与Word2Vec等方法仅仅嵌入不同的是
    这种嵌入需要和模型一起训练
    需要训练的参数为{Wj}\{W_j\}{Wj} {bj}\{b_j\}{bj}

Multiple Residual Units Layer

残差单元的唯一特性是通过两层ReLU转换后将原始输入特征重新添加回来。具体地说:

将右边的移到左边来

=
深交叉确实展示了一些可能受益于剩余单位的属性(Deep Crossing did exhibit a few properties that might benefit from the Residual Units)

Scoring Layer

CTR预估二分类,往往采用逻辑回归
看代码用的是sigmoid函数

整体模型架构图

只包含部分特征的模型结构图

代码部分

读取数据

data = pd.read_csv('criteo_sample.txt')

划分dense和sparse特征

columns = data.columns.values
dense_features = [feat for feat in columns if 'I' in feat]
sparse_features = [feat for feat in columns if 'C' in feat]


构造一个

# 简单的数据预处理
from sklearn.preprocessing import   LabelEncoder
def data_process(data_df, dense_features, sparse_features):"""简单处理特征,包括填充缺失值,数值处理,类别编码param data_df: DataFrame格式的数据param dense_features: 数值特征名称列表 param sparse_features: 类别特征名称列表"""data_df[dense_features] = data_df[dense_features].fillna(0.0)#缺失值填充for f in dense_features:#每一列的特征的名字data_df[f] = data_df[f].apply(lambda x: np.log(x+1) if x > -1 else -1)#如果x>-1(因为x+1>0才能计算对数)就计算为log(x+1)转化为对数,否则就等于-1data_df[sparse_features] = data_df[sparse_features].fillna("-1")#缺失值填充for f in sparse_features:lbe = LabelEncoder()data_df[f] = lbe.fit_transform(data_df[f])return data_df[dense_features + sparse_features]train_data = data_process(data, dense_features, sparse_features)
train_data['label'] = data['label']

pandas.DataFrame.fillna
DataFrame.fillna(value=None, method=None, axis=None, inplace=False, limit=None, downcast=None, **kwargs)

功能:使用指定的方法填充NA / NaN值

参数:value : 变量, 字典, Series, or DataFrame
用于填充缺失值(例如0),或者指定为每个索引(对于Series)或列(对于DataFrame)使用哪个字典/Serise/DataFrame的值。(不在字典/Series/DataFrame中的值不会被填充。)这个值不能是一个列表。
LabelEncoder() 参考
Encode labels with value between 0 and n_classes-1
即将离散型的数据转换成000n−1n-1n1 之间的数,这里 nnn 是一个列表的不同取值的个数,可以认为是某个特征的所有不同取值的个数。

LabelEncoder().fit_transform(data_df[f])
将DataFrame中的每一行ID标签分别转换成连续编号


# 将特征做标记
dnn_feature_columns = [SparseFeat(feat, vocabulary_size=data[feat].nunique(),embedding_dim=4)for feat in sparse_features] + [DenseFeat(feat, 1,)for feat in dense_features]
def build_embedding_layers(feature_columns, input_layers_dict, is_linear):# 定义一个embedding层对应的字典embedding_layers_dict = dict()# 将特征中的sparse特征筛选出来sparse_feature_columns = list(filter(lambda x: isinstance(x, SparseFeat), feature_columns)) if feature_columns else []# 如果是用于线性部分的embedding层,其维度为1,否则维度就是自己定义的embedding维度if is_linear:for fc in sparse_feature_columns:embedding_layers_dict[fc.name] = Embedding(fc.vocabulary_size + 1, 1, name='1d_emb_' + fc.name)else:for fc in sparse_feature_columns:embedding_layers_dict[fc.name] = Embedding(fc.vocabulary_size + 1, fc.embedding_dim, name='kd_emb_' + fc.name)return embedding_layers_dict# 将所有的sparse特征embedding拼接
def concat_embedding_list(feature_columns, input_layer_dict, embedding_layer_dict, flatten=False):# 将sparse特征筛选出来sparse_feature_columns = list(filter(lambda x: isinstance(x, SparseFeat), feature_columns))embedding_list = []for fc in sparse_feature_columns:_input = input_layer_dict[fc.name] # 获取输入层 _embed = embedding_layer_dict[fc.name] # B x 1 x dim  获取对应的embedding层embed = _embed(_input) # B x dim  将input层输入到embedding层中# 是否需要flatten, 如果embedding列表最终是直接输入到Dense层中,需要进行Flatten,否则不需要if flatten:embed = Flatten()(embed)embedding_list.append(embed)return embedding_list# DNN残差块的定义
class ResidualBlock(Layer):def __init__(self, units): # units表示的是DNN隐藏层神经元数量super(ResidualBlock, self).__init__()self.units = unitsdef build(self, input_shape):out_dim = input_shape[-1]self.dnn1 = Dense(self.units, activation='relu')self.dnn2 = Dense(out_dim, activation='relu') # 保证输入的维度和输出的维度一致才能进行残差连接def call(self, inputs):x = inputsx = self.dnn1(x)x = self.dnn2(x)x = Activation('relu')(x + inputs) # 残差操作return x
# block_nums表示
DNN残差块的数量
def get_dnn_logits(dnn_inputs, block_nums=3):dnn_out = dnn_inputsfor i in range(block_nums):dnn_out = ResidualBlock(64)(dnn_out)# 将dnn的输出转化成logitsdnn_logits = Dense(1, activation='sigmoid')(dnn_out)return dnn_logits
# 构建DeepCrossing模型
def DeepCrossing(dnn_feature_columns):# 构建输入层,即所有特征对应的Input()层,这里使用字典的形式返回,方便后续构建模型dense_input_dict, sparse_input_dict = build_input_layers(dnn_feature_columns)# 构建模型的输入层,模型的输入层不能是字典的形式,应该将字典的形式转换成列表的形式# 注意:这里实际的输入与Input()层的对应,是通过模型输入时候的字典数据的key与对应name的Input层input_layers = list(dense_input_dict.values()) + list(sparse_input_dict.values())# 构建维度为k的embedding层,这里使用字典的形式返回,方便后面搭建模型embedding_layer_dict = build_embedding_layers(dnn_feature_columns, sparse_input_dict, is_linear=False)#将所有的dense特征拼接到一起dense_dnn_list = list(dense_input_dict.values())dense_dnn_inputs = Concatenate(axis=1)(dense_dnn_list) # B x n (n表示数值特征的数量)# 因为需要将其与dense特征拼接到一起所以需要Flatten,不进行Flatten的Embedding层输出的维度为:Bx1xdimsparse_dnn_list = concat_embedding_list(dnn_feature_columns, sparse_input_dict, embedding_layer_dict, flatten=True) sparse_dnn_inputs = Concatenate(axis=1)(sparse_dnn_list) # B x m*dim (n表示类别特征的数量,dim表示embedding的维度)# 将dense特征和Sparse特征拼接到一起dnn_inputs = Concatenate(axis=1)([dense_dnn_inputs, sparse_dnn_inputs]) # B x (n + m*dim)# 输入到dnn中,需要提前定义需要几个残差块output_layer = get_dnn_logits(dnn_inputs, block_nums=3)model = Model(input_layers, output_layer)return model
history = DeepCrossing(dnn_feature_columns)history.summary()
history.compile(optimizer="adam", loss="binary_crossentropy", metrics=["binary_crossentropy", tf.keras.metrics.AUC(name='auc')])# 将输入数据转化成字典的形式输入
train_model_input = {name: data[name] for name in dense_features + sparse_features}
# 模型训练
history.fit(train_model_input, train_data['label'].values,batch_size=64, epochs=5, validation_split=0.2, )

结果:

参考:
DataWhale深度推荐模型组队学习
Deep Crossing: Web-Scale Modeling without Manually Crafted Combinatorial Features

【深度推荐算法】DataWhale组队学习Task01: DeepCrossing相关推荐

  1. Datawhale组队学习 Task01:数组(1天)

    Task01:数组(1天) 1. 数组的定义 数组是具有一定顺序关系的若干对象组成的集合,组成数组的对象称为数组元素. 例如: 向量对应一维数组 矩阵对应二维数组 数组名表示群体的共性,即具有同一种数 ...

  2. 五、在测试集上评估图像分类算法精度(Datawhale组队学习)

    文章目录 配置环境 准备图像分类数据集和模型文件 测试集图像分类预测结果 表格A-测试集图像路径及标注 表格B-测试集每张图像的图像分类预测结果,以及各类别置信度 可视化测试集中被误判的图像 测试集总 ...

  3. Datawhale组队学习-金融时序数据挖掘实践-Task01数据探索与分析

    Datawhale组队学习-金融时序数据挖掘实践-Task01数据探索与分析   在二手车交易价格预测之后,本菜鸟又加入了金融时序数据挖掘实践的学习.两个项目都是结构化数据,都着重于对数据本身的探索. ...

  4. Datawhale组队学习周报(第041周)

    本周报总结了从 11月22日至11月28日,Datawhale组队学习的运行情况,我们一直秉承"与学习者一起成长的理念",希望这个活动能够让更多的学习者受益. 第 31 期组队学习 ...

  5. Datawhale组队学习周报(第040周)

    本周报总结了从 11月15日至11月21日,Datawhale组队学习的运行情况,我们一直秉承"与学习者一起成长的理念",希望这个活动能够让更多的学习者受益. 第 31 期组队学习 ...

  6. Datawhale组队学习周报(第005周)

    本周(03月15日~03月21日),第 23 期组队学习正在如火如荼的进行中.本期组队学习,一共有 4 门开源课程,共组建了 5 个学习群,参与的学习者有 740 人.另外,第 24 期组队学习也蓄势 ...

  7. Datawhale组队学习周报(第002周)

    Datawhale组队学习周报(第002周) (一)当下 本周(02月22日~02月28日),我们正在进行5门开源内容的组队学习.一共建立了6个学习群,参与人数1080人.到目前为止,有4门课开源内容 ...

  8. Datawhale组队学习之集成学习——Task 6 Boosting

    Datawhale组队学习之集成学习--Task 6 Boosting 一.Boosting方法的基本思路 二.Adaboost算法 1.Adaboost基本原理 2.使用sklearn对Adaboo ...

  9. Datawhale组队学习周报(第047周)

    本周报总结了从 2021年01月03日至2022年01月09日,Datawhale组队学习的运行情况,我们一直秉承"与学习者一起成长的理念",希望这个活动能够让更多的学习者受益. ...

最新文章

  1. pycharm设置编写的脚本页面长行实现自动换行(windows版)
  2. mysql优化 博客园_MySQL优化
  3. 高效搭建Storm全然分布式集群
  4. python dataframe删除某一列_怎样用Python进行数据分析
  5. Addin and Automation Development In VB.NET 2003 (3)
  6. PostgreSQL的核心架构
  7. mysql 事务日志备份_事务日志备份与恢复 5
  8. 戴志坚接替李小加出任职港交所行政总裁 基本年薪700万港元
  9. 【java】java wait 原理 synchronized ReentrantLock 唤醒顺序
  10. 驱动中的资源共享和临界代码保护
  11. 大数据安全分析的特征有哪些
  12. typedef用法(二)
  13. 通用数据库连接工具--DbVisualizer的使用
  14. python写给初学者的一封信
  15. Chinapub 100万会员评选出来的2007年IT图书排行榜
  16. linux 一键安装字体,在deepin中一键安装喜欢的字体,文档气质瞬间提升!
  17. coreldraw怎么打印荣誉证书_使用Word 2010制作并打印荣誉证书的方法
  18. linux实用技巧:ubuntu18.04安装配置ibus中文输入法
  19. phalcon 自动加载_创建 Phalcon7 项目
  20. 在Android中绘制圆角矩形图片

热门文章

  1. 高德、百度地图自定义底图
  2. lqc_shell批量操作linux主机
  3. 马斯克:特斯拉刚成为一家真正的汽车公司
  4. 关于推送消息的简要分析
  5. 鸿蒙系统卸载预装,鸿蒙系统怎么退回安卓 鸿蒙系统怎么卸载
  6. wordpress创建_如何在WordPress中轻松创建工作申请表
  7. 媒体邀约对发布会进行直播提升企业品牌曝光度。媒体直播分流一键云分发
  8. js13位时间戳转换,10位时间戳转换
  9. 内存不能read written常见原因
  10. 神经网络适用于什么问题,神经网络和计算机网络