Wide & Deep
Wide & Deep模型是一种结合了广度学习(wide learning)和深度学习(deep learning)方法的混合模型。它旨在解决推荐系统中的记忆(memorization)和泛化(generalization)问题。Wide & Deep模型由Google Research于2016年提出,并成功地应用于Google Play应用商店的推荐系统中。该模型旨在同时捕捉低阶特征交互(通过wide部分)和高阶特征交互(通过deep部分),从而充分利用大规模稀疏数据,实现准确且多样的推荐。
Wide部分: Wide部分主要用于捕捉不同特征之间的交互。它通常使用线性模型,如线性回归(Linear Regression)或逻辑回归(Logistic Regression),并采用大量的特征交叉组合。这些特征交叉组合有助于模型更好地理解特征之间的复杂关系。Wide部分的主要优势在于它可以很好地处理高维稀疏数据,并且具有很好的记忆能力,可以找到频繁出现的特征组合。
Deep部分: Deep部分主要用于捕捉特征之间的高阶关系和非线性关系。它通常使用深度神经网络(Deep Neural Networks,DNN),包括多个隐藏层。每个隐藏层的神经元都可以学习输入特征的不同抽象表示。Deep部分的主要优势在于它可以学习到数据中的高阶特征和泛化能力,这有助于预测不常出现的特征组合。
结合Wide和Deep部分: Wide & Deep模型将Wide部分和Deep部分的输出结合在一起,使用一个输出层(通常是sigmoid激活函数)进行最终预测。结合两者的优点使得Wide & Deep模型既能够处理稀疏高维数据,也能捕捉特征之间的复杂关系。这使得模型在推荐系统中表现尤为出色,可以在保证泛化性能的同时,捕获高频和低频特征组合。
应用场景: Wide & Deep模型主要应用于推荐系统,特别是那些需要处理大量高维稀疏数据的场景。例如,电影推荐、新闻推荐和电商推荐等领域。通过Wide & Deep模型,可以有效地平衡用户兴趣的多样性和推荐内容的准确性。
Wide & Deep模型在实际应用中有很多优点,下面列举了一些主要的优点:
记忆与泛化的平衡: Wide & Deep模型通过结合线性模型(Wide部分)和深度神经网络(Deep部分)实现了对记忆和泛化的平衡。Wide部分能够很好地捕捉频繁出现的特征组合,具有很强的记忆能力。而Deep部分则能够学习到数据中的高阶特征和泛化能力,有助于预测不常出现的特征组合。这种平衡使得Wide & Deep模型能够在推荐系统中实现高精度和多样性。
高维稀疏数据处理能力: Wide & Deep模型特别适合处理高维稀疏数据,如推荐系统中的用户和物品特征。通过特征交叉和深度神经网络,模型可以学习到特征之间的复杂关系,提高预测准确性。
端到端训练: Wide & Deep模型可以进行端到端的训练,即直接从输入特征到输出预测的整个过程都可以进行优化。这使得模型可以根据实际任务自动学习到最有用的特征表示,提高预测性能。
可解释性:尽管深度神经 部分的可解释性有限,但Wide部分的线性模型具有较好的可解释性。通过分析Wide部分的权重和特征交叉,可以了解不同特征之间的关系以及它们对最终预测的影响。
灵活性: Wide & Deep模型具有很高的灵活性,可以根据实际应用场景对Wide部分和Deep部分进行调整。例如,可以调整特征交叉的复杂程度或深度神经网络的层数,以满足不同的性能和计算资源需求。
Wide & Deep模型通过结合广度学习和深度学习方法,在推荐系统领域取得了显著的成功。该模型在处理高维稀疏数据、泛化能力和记忆能力方面具有优势,已经被广泛应用于电影推荐、新闻推荐和电商推荐等场景。
下面我们将详细介绍这两部分的数学推导。
Wide部分(线性模型):
Wide部分使用线性模型来捕捉特征之间的低阶交互。给定输入特征向量x,线性模型的输出可以表示为:
y_wide = w_0 + ∑[ w_i * x_i ] + ∑[ w_ij * x_i * x_j ]
其中,y_wide是wide部分的输出,w_0是偏置项,w_i是第i个特征的权重,x_i是第i个特征的值,w_ij是第i个特征和第j个特征交叉项的权重,x_i和x_j分别是第i个特征和第j个特征的值。在实际应用中,我们通常使用L1正则化(Lasso)来约束模型的复杂度,避免过拟合。
Deep部分(深度神经网络):
Deep部分使用深度神经网络(DNN)来捕捉特征之间的高阶交互。模型的输入通常是将原始特征通过embedding层转换为密集向量,然后将这些向量输入DNN。给定输入特征向量x,DNN的输出可以表示为:
y_deep = DNN(x_embed)
其中,y_deep是deep部分的输出,x_embed是经过embedding层转换后的输入特征向量,DNN()是深度神经网络函数。
y_deep = f_L(…f_2(f_1(x, W_1), W_2)…, W_L)
其中,f_l表示第l层的激活函数(如ReLU),W_l表示第l层的权重矩阵,L表示神经网络的层数。
Wide & Deep模型的组合:
将Wide部分和Deep部分组合起来,我们可以得到Wide & Deep模型的输出:
y = σ(w_wide * y_wide + w_deep * y_deep)
其中,σ表示激活函数(如sigmoid),w_wide和w_deep分别表示Wide部分和Deep部分的权重。在二分类问题中,我们可以将输出y解释为正类的概率。对于多分类问题,可以将激活函数σ替换为softmax,以获得每个类别的概率。
目标函数:
对于二分类问题,通常使用对数损失函数:
L(y, ŷ) = -∑[ y * log(ŷ) + (1 - y) * log(1 - ŷ) ]
其中,L(y, ŷ)是损失函数,y是真实值(0或1),ŷ是模型的预测值(点击概率)。
Wide & Deep模型的目标是最小化损失函数(如交叉熵损失)。给定训练样本(x_i, y_i),我们可以计算模型的损失:
L = ∑l(y_i * log(y_i_hat) + (1 - y_i) * log(1 - y_i_hat))
其中,y_i_hat表示模型的预测值,l表示正则化项(如L1或L2正则化)。
通过最小化损失函数,可以优化模型参数,我们可以使用随机梯度下降(SGD)或其他优化算法(如Adam)来最小化损失函数或其他优化算法来学习模型的参数(如wide部分的权重和deep部分的权重、偏置项等。)
总之,Wide & Deep模型通过组合线性模型(Wide部分)和深度神经网络(Deep部分)来实现对低阶和高阶特征交互的捕捉。通过最小化损失函数,模型可以学习到适当的权重,从而实现准确的预测。
在实际应用过程中也需要注意一些挑战和潜在的局限性:
特征工程的挑战: Wide部分依赖于特征交叉来捕捉特征之间的关系,这需要对特征进行大量的预处理和特征工程。合适的特征交叉对于提高模型性能至关重要,但寻找合适的特征交叉通常需要大量的领域知识和实验。此外,特征工程的复杂性可能导致模型的维度迅速增加,这可能会影响模型的训练速度和性能。
计算资源需求:尽管Wide & Deep模型可以处理高维稀疏数据,但深度神经网络部分可能需要大量的计算资源。随着神经网络层数的增加,模型的参数数量会急剧增加,这会导致训练和推理过程的计算复杂度上升。因此,在实际应用中可能需要权衡模型性能和计算资源需求。
超参数调优: Wide & Deep模型涉及许多超参数,如特征交叉的数量、神经网络层数和神经元数量等。这些超参数对模型性能有很大影响,但寻找合适的超参数组合通常需要大量的实验和调优。虽然可以通过自动调参方法(如贝叶斯优化和网格搜索)来简化调参过程,但这仍然需要消耗大量的计算资源和时间。
冷启动问题:与其他推荐系统模型一样,Wide & Deep模型也受到冷启动问题的影响。当系统面临全新的用户或物品时,模型可能无法获得足够的信息来进行准确的预测。为解决这一问题,可能需要结合其他技术(如基于内容的推荐或协同过滤)来提高冷启动时的推荐性能。
相关模型
DeepFM(Deep Factorization Machines): DeepFM模型结合了因子分解机(FM)和深度神经网络。FM部分用于捕捉低阶特征交互,而深度神经网络部分用于捕捉高阶特征交互。与Wide & Deep模型相比,DeepFM在特征交叉上具有更高的灵活性,能够自动学习有效的特征交叉组合。
NFM(Neural Factorization Machines): NFM模型将神经网络引入因子分解机,使得模型可以学习到更加复杂的特征交互。NFM采用了一种叫做Bi-Interaction Pooling的技术,可以自动发现高阶特征交互,同时保持计算效率。
xDeepFM(eXtreme Deep Factorization Machines): xDeepFM模型结合了DeepFM和Wide & Deep模型的优点,通过引入一种新的网络结构——Compressed Interaction Network(CIN),用于自动学习高阶特征交互。CIN结构可以有效地发现高阶特征交互,同时保持较低的计算复杂度。
AutoInt(Automatically Learning Feature Interactions): AutoInt模型采用了自注意力(Self-Attention)机制来自动发现特征交互。自注意力机制可以在不同特征之间建立关联,从而实现自动特征交叉。AutoInt模型旨在克服手动特征交叉的局限性,提高特征交互的学习效率。
这些模型都在各自的方式上尝试结合不同的学习策略,以实现更好的记忆和泛化能力。虽然这些模型在某些方面可能优于Wide & Deep模型,但在实际应用中,选择合适的模型需要根据具体问题和数据特征进行权衡。
以下是一些在推荐系统领域的其他相关研究方向:
强化学习在推荐系统中的应用:强化学习(Reinforcement Learning,RL)是一种学习方法,通过与环境的交互来学习最优策略。在推荐系统中,强化学习可以用来建立用户与推荐物品之间的动态交互,实现更个性化和长期有效的推荐。例如,强化学习可以用于序列推荐,通过学习用户的历史行为来推荐可能感兴趣的物品。
图神经网络在推荐系统中的应用:图神经网络(Graph Neural Networks,GNN)是一种基于图结构的深度学习方法,用于处理图数据。在推荐系统中,用户和物品之间的关系可以表示为图结构,GNN可以用来学习用户和物品之间的潜在关系,从而提高推荐的准确性。例如,GNN可以用于社交网络推荐,通过分析用户的社交关系来推荐可能感兴趣的物品。
生成模型在推荐系统中的应用:生成模型(Generative Models)是一种深度学习方法,可以学习数据的潜在分布。在推荐系统中,生成模型可以用于生成用户和物品的潜在表示,进一步提高推荐的准确性。例如,变分自编码器(Variational Autoencoder,VAE)和生成对抗网络(Generative Adversarial Networks,GAN)等生成模型可以应用于协同过滤和基于内容的推荐。
上下文感知推荐系统:上下文感知推荐系统考虑了上下文信息,如用户的地理位置、时间和设备等,以提高推荐的准确性和多样性。这种推荐系统可以更好地捕捉用户在不同上下文下的兴趣变化,从而实现更个性化的推荐。
多模态推荐系统:多模态推荐系统利用来自不同来源和类型的数据(如文本、图像、音频和视频等),以提高推荐的准确性和多样性。通过融合多模态信息,推荐系统可以更全面地理解用户和物品的属性,从而实现更精准的推荐。
这是一篇具有划时代意义的论文,于2016年由Google工程师向业界公布,介绍了一套个性化推荐的系统框架。目前,该框架已被广泛应用于搜索、推荐、广告等排序系统中。与传统搜索类似,推荐系统面临的一个挑战是如何在保证推荐结果准确性的同时,实现扩展性。精准推荐的内容可能使用户兴趣收敛,缺乏新鲜感,不利于长期留存;而泛化的推荐可能无法满足用户的具体兴趣,导致用户流失。相较于推荐准确性,扩展性更倾向于改善推荐系统的多样性。
论文仅有4页,思路简洁明了。作者设计了一种融合浅层(wide)模型和深层(deep)模型进行联合训练的框架,充分利用浅层模型的记忆能力和深层模型的泛化能力,实现单一模型在推荐系统准确性和扩展性方面的平衡。对于提出的W&D模型,论文从推荐效果和服务性能两方面进行了评价:
在推荐效果方面,通过在Google Play上进行线上A/B实验,W&D模型与经过高度优化的Wide浅层模型相比,app下载率提高了3.9%。与deep模型相比,也取得了一定程度的提升。
在服务性能方面,通过将一次请求需要处理的app的批量大小切分为更小的尺寸,并利用多线程并行请求,实现了处理效率的提高。单次响应耗时从31毫秒降低到了14毫秒。
正如我们在之前的文章中所提到的,广告系统实际上可以被看作是一种搜索排序系统。它以用户信息和用户浏览的上下文信息为输入,返回一个经过排序的序列。
正是基于这个原因,广告系统面临着与搜索排序系统相似的挑战:权衡记忆性和泛化性。记忆性可以简单地理解为对商品或特征间成对出现的学习。由于用户历史行为特征具有很强的相关性,记忆性可以带来更好的效果。然而,这也会带来一些问题,最典型的就是模型泛化能力不足。
泛化能力的主要来源是特征之间的相关性和传递性。可能特征A与特征B直接与label相关,或者特征A与特征B相关,特征B与label相关,这种现象称为传递性。通过利用特征间的传递性,我们可以探索历史数据中很少出现的特征组合,从而获得较强的泛化能力。
在大规模的在线推荐广告排序系统中,如LR(逻辑回归)等线性模型被广泛应用,因为它们简单、易扩展、性能优越且具有良好的可解释性。这些模型通常使用one-hot这样的二进制数据进行训练。例如,如果用户安装了Netflix,那么"user_installed_app=Netflix"这个特征值为1,否则为0。因此,一些二阶特征的可解释性非常强。
例如,如果用户还浏览了Pandora,那么"user_installed_app=Netflix,impression_app=Pandora"这个组合特征值为1。组合特征的权重实际上就反映了这两者之间的相关性。然而,这种特征需要大量的人工操作,而且由于样本稀疏性,对于那些在训练数据中未出现过的组合,模型将无法学习到它们的权重。
但是这个问题可以被基于embedding的模型解决,比如之前介绍过的FM模型,或者是深度神经网络。它可以通过训练出低维度下的embedding,用embedding向量去计算得到交叉特征的权重。然而如果特征非常稀疏的话,我们也很难保证生成的embedding的效果。在某些特殊情况下,如用户偏好明显或商品比较小众的场景,基于embedding的模型可能会导致过拟合和推荐效果不佳。这些用户-商品组合中的行为数据非常稀疏,即用户很少或从未与这些商品产生过互动。
在这种情况下,由于数据稀疏,embedding向量可能无法很好地表示这些特征组合,因此算出的权重可能不准确。权重大于0意味着这个用户-商品组合被认为具有一定的相关性,但实际上可能并没有相关性。这就可能导致过拟合现象,使得推荐结果不准确。
而线性模型在这种特殊情况下可能会表现得更好,因为它更容易拟合稀疏数据,并具有较好的泛化能力。线性模型通过简单地计算特征之间的线性关系来进行预测,相对来说更不容易受到过拟合的影响,因此在这种特殊情况下可能会表现得更好。
在这篇paper当中,我们将会介绍Wide & Deep模型,它在一个模型当中兼容了记忆性以及泛化性。它可以同时训练线性模型以及神经网络两个部分,从而达到更好的效果。
论文的主要内容有以下几点:
Wide & Deep模型,包含前馈神经网络embedding部分以及以及线性模型的特征转换,在广义广告系统当中的应用
Wide & Deep模型在Google Play场景下的实现与评估,Google Play是一个拥有超过10亿日活和100w App的移动App商店
Wide & Deep模型实践细节
构建样本:
要构建模型,我们需要从日志中获取样本。通常情况下,我们会通过埋点技术记录用户的行为数据,然后对这些日志进行清洗,以便获得用户的行为信息。样本通常采用三元组的格式:用户ID、项目ID和标签。至于相应的特征,我们需要根据用户ID和项目ID从相应的Hive表格中获取并整合。
正负样本:
正样本:用户点击的广告或商品。
负样本:用户在点击最大位置之上曝光但未点击的广告或商品;以及那些从未被点击过的用户部分曝光但未点击的广告或商品。
例如,有以下用户行为记录:
第一条:曝光
第二条:点击
第三条:曝光
第四条:点击
第五条:曝光
在这个例子中,我们可以看到用户在第二条和第四条记录中点击了广告或商品,因此这些可以作为正样本。然后,在第一条、第三条和第五条记录中,用户看到了广告或商品,但并未进行点击,这些可以作为负样本。
如何选择正负样本:
处理日志:
在处理日志时,我们需要区分Web端和App端,以避免增加无效的负样本。
用户点击最大位置以上曝光未点击的广告:
这种方法实际上被称为"Skip Above",即过滤掉最后一次点击。这样做的原因是,我们认为用户没有观察到之后的广告。
控制高度活跃用户对损失的影响:
为了降低高度活跃用户对损失的影响,我们在训练集中为每个用户提取相同数量的样本。
从未点击的用户部分曝光未点击的广告:
去除这部分用户可能导致模型仅学习活跃用户和有购买意向用户的行为习惯,导致线上和线下数据分布不一致。然而,如果保留这部分用户,这些无效用户可能会影响模型的推荐效果。为了解决这个问题,我们可以通过A/B测试来判断是否需要将这部分用户纳入样本,以及需要多少这样的用户。
避免特征穿越:
在构建特征时,需要确保特征是在样本时间之前生成的,以防止特征穿越问题。
总之,在选择正负样本时,我们需要综合考虑各种因素,包括数据来源、用户行为、样本数量以及特征选择。通过A/B测试,我们可以找到最佳的样本策略,从而优化模型的推荐效果。
如何解决样本不平衡问题:
在训练模型时,我们通常会遇到正负样本不平衡的问题,即未点击的广告(负样本)数量远多于点击的广告(正样本)。为了解决这个问题,我们可以采用以下方法:
下采样负样本:
通过从负样本中随机选择一部分样本,以减少负样本的数量,使正负样本数量更接近。
调整样本权重:
提高正样本的权重,以使正负样本在模型训练中具有更平衡的影响力。
然而,这些方法只能在一定程度上缓解类别不平衡问题,最根本的解决方案还是增加标注数据。需要注意的是,下采样和调整样本权重会改变样本分布,这可能导致训练样本分布与线上真实分布不一致。因此,在线上实际环境中模型是否能取得好的提升效果,还需要观察模型在真实数据上的表现。
处理噪声样本:
用户在不同时间可能对同一广告有不同的行为,导致收集到的样本中既有正样本(点击)也有负样本(未点击)。针对这种情况,我们可以采用以下方法处理:
如果两次行为之间的时间间隔较短,可以选择删除这些样本,或只保留其中一个。
如果两次行为之间的时间间隔较长,可以保留这些样本。因为可能用户的上下文环境发生了变化,时间特征能够在一定程度上区分样本的差异,帮助模型学习到用户短期兴趣的变化。
模型离线训练:
数据划分:使用7天的数据作为训练集,1天的数据作为测试集。
模型调优:
-
防止过拟合:添加Dropout和L2正则化。
-
加速收敛:使用Batch Normalization。
-
确保训练稳定和收敛:尝试不同的学习率(Wide部分为0.001,Deep部分为0.01效果较好)和批次大小(当前设置为2048)。
-
优化器:我们比较了SGD、Adam、Adagrad等优化器,最终选择了效果最好的Adagrad。
模型在线训练:也称为在线学习,是指模型在持续接收新数据的过程中不断更新和调整。Wide & Deep模型的在线训练可以采用以下策略:
在线模型更新:将模型部署在生产环境中,实时处理用户行为数据。每当收集到足够的新数据(例如,一定数量的用户点击或曝光),就对模型进行一次更新。
增量训练:每次收到新数据时,不需要从头开始训练模型,而是在当前模型的基础上继续训练。这可以大大提高训练效率。
学习率衰减:在线训练过程中,逐渐降低学习率。这有助于模型在初始阶段快速收敛,并在后期更稳定地微调。
数据窗口:为了保持模型的实时性,可以使用滑动窗口策略。只保留最近一段时间内的数据作为训练集,丢弃过旧的数据。这样可以确保模型关注最近的用户行为和趋势。
在线评估:定期评估模型在实时数据上的性能,以检测模型是否出现退化现象。如果发现性能下降,可以及时进行调整。
A/B测试:在线训练期间,可进行A/B测试,以便实时监测新模型相对于旧模型的性能。根据测试结果,可以决定是否应用新模型。
模型融合:在实际应用中,可以将多个在线训练的模型进行融合,以提高整体推荐性能。
请注意,在线训练可能会面临数据泄露、安全性和隐私等问题。因此,在实施在线训练时,请确保遵循相关法规和公司政策
Tensorflow1
# 导入所需的库
import numpy as np
import tensorflow as tf
# 这段代码定义了一个名为WideAndDeepModel的类,用于构建、训练和评估一个宽度和深度的神经网络模型。这个模型包含两个部分:宽度模型和深度模型。宽度模型是一个线性模型,深度模型是一个多层感知器(MLP)。
#
# __init__():初初始化方法,用于设置模型的参数,如向量维度、特征域长度、DNN层列表、学习率、正则化系数、提前停止轮数等。同时,它还调用build_graph()方法构建模型的计算图。
#
# build_graph:构建计算图方法,用于构建模型的计算图,包括输入、模型结构、损失函数、优化器等。这个方法调用了add_input()和inference()方法,并在最后设置了TensorBoard摘要。
#
# add_input:添加输入方法,用于创建特征域和标签的输入占位符。
#
# inference():定义模型的前向传播过程,包括广度(Wide)部分和深度(Deep)部分。广度部分使用FTRL优化器,深度部分使用Adam优化器。两部分的优化操作都被组合到self.train_op中。宽度模型是一个线性模型,深度模型是一个多层感知器(MLP)。同时设置损失函数、优化器以及其他评估指标。
#
# train():模型的训练方法。使用给定的训练数据和验证数据进行训练,支持批处理和最大迭代次数。在训练过程中,会对验证集进行评估,输出验证损失、验证准确率和验证AUC。这些性能指标将被用于判断模型是否过拟合或欠拟合。在验证集的AUC不再提高时,将触发提前停止。此外,还实现了早停(early stopping)策略。
#
# get_batches():一个生成器函数,用于从数据中生成批次。它将数据打乱,并按批次大小生成训练数据子集。这个方法在训练过程中被调用,以便在每个epoch中遍历训练数据。
# 定义 WideAndDeepModel 类
class WideAndDeepModel:
# 初始化方法
def __init__(self, vec_dim=None, field_lens=None, dnn_layers=None, wide_lr=0.001, l1_reg=0.1, deep_lr=0.01,
early_stopping_rounds=10, tensorboard_logdir=None,