【王喆-推荐系统】模型篇-(task5)wide&deep模型

简介: Wide&Deep是工业界中有巨大影响力的模型,如果直接翻译成中文是宽和深的模型,其模型结构如下所示:wide和deep让模型兼具逻辑回归和深度神经网络的特点。

一、Wide&Deep 模型的结构

Wide&Deep是工业界中有巨大影响力的模型,如果直接翻译成中文是宽和深的模型,其模型结构如下所示:wide和deep让模型兼具逻辑回归和深度神经网络的特点。

Wide就是将输入层直接连接到输出层(中间没有做任何处理)

——让模型具有较强的记忆力

Deep则其实是上个task的embedding+MLP

——让模型具有较强的泛化性

image.png

二、模型的记忆能力

记忆力:可理解为模型直接学习历史数据中物品或者特征的“共现频率”,并且把它们直接作为推荐依据的能力。

在sparrow项目的电影推荐中有一些规则,如看了A电影的用户经常喜欢看电影B,这是一种类似“因为A所以B”的规则,这类规则有两个特点:

数量特多,模型难记住;

没法推而广之,规则已经比较具体了:没办法或者说也没必要跟其他特征做进一步的组合。就像看了电影 A 的用户 80% 都喜欢看电影 B,这个特征已经非常强了,我们就没必要把它跟其他特征再组合在一起。

结论:wide部分增强模型记忆力,因为单层线性模型“擅长”记住大量且直接的规则。

三、模型的泛化能力

“泛化能力”指的是模型对于新鲜样本、以及从未出现过的特征组合的预测能力。

栗子1:现在如果已知35岁的女性用户和25岁的男性用户都喜欢看电影A,那如果让学习后的模型现在推理:35岁的男性用户是否喜欢看电影A,如果泛化性强一丢丢的模型可能就会回答【喜欢】,基于35女的35和25男的男做出的推理。

栗子2:矩阵分解算法就是为了解决协同过滤“泛化能力”不强而诞生的。因为协同过滤只会“死板”地使用用户的原始行为特征,而矩阵分解因为生成了用户和物品的隐向量,所以就可以计算任意两个用户和物品之间的相似度了。这就是泛化能力强的另一个例子。

结论:通过deep部分可以增强模型的泛化性,因为深度学习模型有很强的数据拟合能力,特征可以充分交叉,这里就沿用了上个task的embedding+MLP。

四、Wide&Deep 模型的应用场景

Wide&Deep 模型是由 Google 的应用商店团队 Google Play 提出的,在 Google Play 为用户推荐 APP 这样的应用场景下。

Wide&Deep 模型的推荐目标:尽量推荐那些用户可能喜欢,愿意安装的应用。

问题:具体到 Wide&Deep 模型中,Google Play 团队是如何为 Wide 部分和 Deep 部分挑选特征的。

image.png

图2 Google Play Wide&Deep模型的细节 (出自Wide & Deep Learning for Recommender Systems )

上图2补充google play团队这个模型的细节:从左边的wide的特征开始看起,只利用两个特征(“已安装应用”特征和“曝光应用”特征)的交叉,就是说wide想学的东西是希望记住“因为A所以B”的规则——如果安装了应用A,是否会安装B这样的规则。

再看deep部分的左边:是一个非常典型的 Embedding+MLP 结构,其中的输入特征很多,有用户年龄、属性特征、设备类型,还有已安装应用的 Embedding 等等。把这些特征一股脑地放进多层神经网络里面去学习之后,它们互相之间会发生多重的交叉组合,这最终会让模型具备很强的泛化能力。如刚才35女和25男的栗子学到具有泛化性的模型。

五、tensorflow实现

这部分的特征处理和上一个task是一样的,看模型结构:

deep模块:和上个task的特征是一样的,输入层加两层 128 维隐层的结构,它的输入是类别型 Embedding 向量和数值型特征。

wide模块:把输入特征连接到输出层,注意Wide 部分所用的特征 crossed_feature。

# wide and deep model architecture
# deep part for all input features
deep = tf.keras.layers.DenseFeatures(numerical_columns + categorical_columns)(inputs)
deep = tf.keras.layers.Dense(128, activation='relu')(deep)
deep = tf.keras.layers.Dense(128, activation='relu')(deep)
# wide part for cross feature
wide = tf.keras.layers.DenseFeatures(crossed_feature)(inputs)
# 拼接wide和deep层
both = tf.keras.layers.concatenate([deep, wide])
output_layer = tf.keras.layers.Dense(1, activation='sigmoid')(both)
model = tf.keras.Model(inputs, output_layer)

生成了一个由“用户已好评电影”和“当前评价电影”组成的一个交叉特征,就是代码中的 crossed_feature,设置这个特征的目的在于让模型记住好评电影之间的相关规则,更具体点来说就是,就是让模型记住“一个喜欢电影 A 的用户,也会喜欢电影 B”这样的规则:

这样的规则不是唯一的,需要你根据自己的业务特点来设计, 比如在电商网站中,这样的规则可以是,购买了键盘的用户也会购买鼠标。在新闻网站中,可以是打开过足球新闻的用户,也会点击 NBA 新闻等等。

movie_feature = tf.feature_column.categorical_column_with_identity(key='movieId', num_buckets=1001)
rated_movie_feature = tf.feature_column.categorical_column_with_identity(key='userRatedMovie1', num_buckets=1001)
crossed_feature = tf.feature_column.crossed_column([movie_feature, rated_movie_feature], 10000)

在 Deep 部分和 Wide 部分都构建完后,我们要使用 concatenate layer 把两部分连接起来,形成一个完整的特征向量,输入到最终的 sigmoid 神经元中,产生推荐分数。

【拓展】尝试设置不同的特征,以及不同的参数组合,真实地体验深度学习模型的调参过程。

六、Pytorch实现

image.png

首先分别搭建两个部分:

class Linear(nn.Module):
    """
    Linear part
    """
    def __init__(self, input_dim):
        super(Linear, self).__init__()
        self.linear = nn.Linear(in_features=input_dim, out_features=1)
    def forward(self, x):
        return self.linear(x)
class Dnn(nn.Module):
    """
    Dnn part
    """
    def __init__(self, hidden_units, dropout=0.):
        """
        hidden_units: 列表, 每个元素表示每一层的神经单元个数, 比如[256, 128, 64], 两层网络, 第一层神经单元128, 第二层64, 第一个维度是输入维度
        dropout: 失活率
        """
        super(Dnn, self).__init__()
        self.dnn_network = nn.ModuleList([nn.Linear(layer[0], layer[1]) for layer in list(zip(hidden_units[:-1], hidden_units[1:]))])
        self.dropout = nn.Dropout(p=dropout)
    def forward(self, x):
        for linear in self.dnn_network:
            x = linear(x)
            x = F.relu(x)
        x = self.dropout(x)
        return x

最后拼接起来,搭建wide&deep模型,最后的输出部分可以对Wide和Deep的输出加上一个权重得到最后的输出。

class WideDeep(nn.Module):
    def __init__(self, feature_columns, hidden_units, dnn_dropout=0.):
        super(WideDeep, self).__init__()
        self.dense_feature_cols, self.sparse_feature_cols = feature_columns
        # embedding 
        self.embed_layers = nn.ModuleDict({
            'embed_' + str(i): nn.Embedding(num_embeddings=feat['feat_num'], embedding_dim=feat['embed_dim'])
            for i, feat in enumerate(self.sparse_feature_cols)
        })
        hidden_units.insert(0, len(self.dense_feature_cols) + len(self.sparse_feature_cols)*self.sparse_feature_cols[0]['embed_dim'])
        self.dnn_network = Dnn(hidden_units)
        self.linear = Linear(len(self.dense_feature_cols))
        self.final_linear = nn.Linear(hidden_units[-1], 1)
    def forward(self, x):
        dense_input, sparse_inputs = x[:, :len(self.dense_feature_cols)], x[:, len(self.dense_feature_cols):]
        sparse_inputs = sparse_inputs.long()
        sparse_embeds = [self.embed_layers['embed_'+str(i)](sparse_inputs[:, i]) for i in range(sparse_inputs.shape[1])]
        sparse_embeds = torch.cat(sparse_embeds, axis=-1)
        dnn_input = torch.cat([sparse_embeds, dense_input], axis=-1)
        # Wide
        wide_out = self.linear(dense_input)
        # Deep
        deep_out = self.dnn_network(dnn_input)
        deep_out = self.final_linear(deep_out)
        # out
        outputs = F.sigmoid(0.5 * (wide_out + deep_out))
        return outputs  

七、作业

对于 Deep 部分来说,一股脑地把所有特征都扔进 MLP 中去训练,这样的方式有没有什么改进的空间?比如说,“用户喜欢的电影风格”和“电影本身的风格”这两个特征,我们能不能进一步挖掘出它们之间的相关性,而不是简单粗暴地扔给神经网络去处理呢?

【答】改进算法的wide部分,提升记忆能力,使用端到端模型,减少人工操作。例如DCNMix、DeepFM。以DeepFM这个模型都可以很好学习到高低特征与交叉。(实际业界常用,推荐)。这里也可以回顾之前的各种典型网络模型:

image.png

【高低阶特征知识】

低阶特征:是指线性-线性组合,只能算一个有效的线性组合,线性-非线性-线性,这样算两个有效的线性组合,一般常说的低阶特征只有小于等于2阶;

高阶特征:说高阶特征,可以理解为经过多次线性-非线性组合操作之后形成的特征,为高度抽象特征,一般人脑很难解析出原有的特征了。

相关文章
|
1月前
|
机器学习/深度学习 搜索推荐 算法
推荐系统离线评估方法和评估指标,以及在推荐服务器内部实现A/B测试和解决A/B测试资源紧张的方法。还介绍了如何在TensorFlow中进行模型离线评估实践。
推荐系统离线评估方法和评估指标,以及在推荐服务器内部实现A/B测试和解决A/B测试资源紧张的方法。还介绍了如何在TensorFlow中进行模型离线评估实践。
249 0
|
3天前
|
机器学习/深度学习 搜索推荐 算法
基于深度学习神经网络协同过滤模型(NCF)的图书推荐系统
登录注册 热门图书 图书分类 图书推荐 借阅图书 购物图书 个人中心 可视化大屏 后台管理
基于深度学习神经网络协同过滤模型(NCF)的图书推荐系统
|
1月前
|
数据采集 机器学习/深度学习 搜索推荐
使用Python实现推荐系统模型
使用Python实现推荐系统模型
58 1
|
1月前
|
机器学习/深度学习 搜索推荐 算法
推荐系统算法的研究与实践:协同过滤、基于内容的推荐和深度学习推荐模型
推荐系统算法的研究与实践:协同过滤、基于内容的推荐和深度学习推荐模型
355 1
|
1月前
|
算法 搜索推荐 Python
探索Python中的推荐系统:混合推荐模型
探索Python中的推荐系统:混合推荐模型
102 1
|
1月前
|
存储 搜索推荐 算法
大模型开发:在构建推荐系统时,你会考虑哪些因素?
构建推荐系统涉及关键因素:用户行为数据(理解兴趣)、物品属性(相似性分析)、上下文信息(时间、地点)、冷启动问题(新用户/物品推荐)、可扩展性与性能(高效算法)、多样性(避免单一推荐)、可解释性(增强信任)和评估优化(准确性和用户满意度)。通过综合运用这些因素,打造精准且有效的推荐服务。
50 1
|
机器学习/深度学习 人工智能 自然语言处理
深度学习应用篇-推荐系统[12]:经典模型-DeepFM模型、DSSM模型召回排序策略以及和其他模型对比
深度学习应用篇-推荐系统[12]:经典模型-DeepFM模型、DSSM模型召回排序策略以及和其他模型对比
深度学习应用篇-推荐系统[12]:经典模型-DeepFM模型、DSSM模型召回排序策略以及和其他模型对比
|
机器学习/深度学习 人工智能 移动开发
人工智能领域:面试常见问题超全(深度学习基础、卷积模型、对抗神经网络、预训练模型、计算机视觉、自然语言处理、推荐系统、模型压缩、强化学习、元学习)
人工智能领域:面试常见问题超全(深度学习基础、卷积模型、对抗神经网络、预训练模型、计算机视觉、自然语言处理、推荐系统、模型压缩、强化学习、元学习)
|
机器学习/深度学习 SQL 存储
推荐系统[二]:召回算法超详细讲解[召回模型演化过程、召回模型主流常见算法(DeepMF_TDM_Airbnb Embedding_Item2vec等)、召回路径简介、多路召回融合]
推荐系统[二]:召回算法超详细讲解[召回模型演化过程、召回模型主流常见算法(DeepMF_TDM_Airbnb Embedding_Item2vec等)、召回路径简介、多路召回融合]
推荐系统[二]:召回算法超详细讲解[召回模型演化过程、召回模型主流常见算法(DeepMF_TDM_Airbnb Embedding_Item2vec等)、召回路径简介、多路召回融合]
|
存储 搜索推荐 NoSQL
带你读《云存储应用白皮书》之37:3. 表格存储在推荐系统中的应用
带你读《云存储应用白皮书》之37:3. 表格存储在推荐系统中的应用
158 0