【datawhale202206】pyTorch推荐系统:精排模型 DeepFM&DIN

小结

补充了推荐系统的相关背景知识,可以更好地理解本次所学习的两个模型:DeepFM和DIN在推荐系统中的作用(精排)。

随后学习了DeepFM和DIN两个模型的结构,理解模型的诞生背景或许是更加值得关注的。

DeepFM的大背景尝试让模型是学习更多的特征,来提升推荐模型的效果,创新点在于并行处理了FM和DNN,使得高低阶的特征更好地被结合和学习;

DIN的大背景是在累积了足够多的历史用户行为数据的应用场景,创新点是引入了注意力机制有针对性地处理历史用户行为数据。在DIN中,由于大背景与常规推荐系统任务不同(有大量用户历史行为数据),因此需要了解历史用户行为数据是如何在模型输入中被表示的,以及如何在模型及代码实现中处理(本身不等长-》multi-hot等长-》输入模型稠密后不等长-》代码实现时padding等长,mask标记)

0 rechub和推荐系统

0.1 rechub项目及安装

rechub是一个聚焦复现业界实用的推荐模型,以及泛生态化的推荐场景的项目,目标是易用易拓展,项目地址

可以通过下面指令安装

#稳定版 
pip install torch-rechub

#最新版(推荐)
1. git clone https://github.com/datawhalechina/torch-rechub.git
2. cd torch-rechub
3. python setup.py install

本次在colab上配置环境,实现如下:
在这里插入图片描述

项目主页提供了更详细的介绍及使用的简单示例。

0.2 推荐系统

0.2.1 推荐系统是什么

推荐系统入门这篇博客中有蛮好的简单介绍。

推荐系统是一种 信息过滤系统,根据用户的历史行为、社交关系、兴趣点算法可以判断用户当前感兴趣的物品或内容。你也可以将它理解为一家只为你而开的商店。店铺里摆放的都是你需要的,或者适合你的商品。

实现推荐的方式分为:

  • Content-based Filtering:给内容打标签,推荐相似的其他内容
  • Collaborative Filtering:给用户打标签,根据相似用户的行为推荐
  • Using data to solve problems:有了数据后实现,依然是分为内容和用户行为两个方面,分析data判断相似度,然后推荐solve problems
  • 物品本身:Content-based 基于物品本身的内容,而不是用户购买/浏览物品的行为
  • 用户行为:
    显性反馈数据:用户明确表示对物品的喜欢行为:评分,喜欢,收藏,购买
    隐性反馈数据:不能明确反映用户喜好的行为:浏览,停留时间,点击

0.2.2 推荐系统的算法框架

由于主要涉及的项目是推荐系统的算法模型,所以我们要熟悉的是推荐系统的算法架构,由召回粗排排序重排等四个算法环节组成,下面这张图是一个简单的说明。
在这里插入图片描述

对应地,四个算法环节的功能可以简单理解为:

  • 召回:可以理解为一个快速地筛选及形成值得注意的数据的过程,具体为实现从推荐池中选取几千上万的item,送给后续的排序模块;
  • 粗排:可以理解为初步过滤计算,实现缩减精排层计算量的过程;
  • 精排:获取粗排模块的结果,对候选集进行打分和排序。精排需要在最大时延允许的情况下,保证打分的精准性,是整个系统中至关重要的一个模块,也是最复杂,研究最多的一个模块。精排系统构建一般需要涉及样本、特征、模型三部分;
  • 重排:根据具体的使用目的,对精排的结果进行微调;
  • 混排:如果有多种数据源,在这里进行一个结合。

其中,对于上图中提到的物料库,显然它不会是以一个原始所有数据堆积的形式实现的,而是被整理为描述(用户/商品)画像的数据形式。一般推荐系统还会加入多模态的一个内容理解(包含文本理解,关键词标签,内容理解,知识图谱等)。

下图是微信看一看的内容画像框架,可以帮助理解物料库里放的到底是什么东西,从而对我们推荐算法所需要处理的数据有一个理解。
在这里插入图片描述

下面这段文字可以帮助我们更好地理解推荐算法在实际推荐系统中的作用,及我们需要关注的地方。

我们在入门学习推荐系统的时候,更加关注的是哪个模型AUC更高、topK效果好,哪个模型更加牛逼的问题,从基本的协同过滤到点击率预估算法,从深度学习到强化学习,学术界都始终走在最前列。一个推荐算法从出现到在业界得到广泛应用是一个长期的过程,因为在实际的生产系统中,首先需要保证的是稳定、实时地向用户提供推荐服务,在这个前提下才能追求推荐系统的效果。
算法架构的设计思想就是在实际的工业场景中,不管是用户维度、物品维度还是用户和物品的交互维度,数据都是极其丰富的,学术界对算法的使用方法不能照搬到工业界。当一个用户访问推荐模块时,系统不可能针对该用户对所有的物品进行排序,那么推荐系统是怎么解决的呢?对应的商品众多,如何决定将哪些商品展示给用户?对于排序好的商品,如何合理地展示给用户?
所以一个通用的算法架构,设计思想就是对数据层层建模,层层筛选,帮助用户从海量数据中找出其真正感兴趣的部分

也就是说,对实际推荐系统而言,不是只需要做出一个简单的推荐算法模型就可以,因为会受到数据源质量及数量规模的限制和影响。因此,考虑可以利用合理的算法架构,筛选数据,然后最大化算法模型的效果。

而本次所涉及到的,是精排环节的模型。

精排层,也是我们学习推荐入门最常常接触的层,我们所熟悉的算法很大一部分都来自精排层。这一层的任务是获取粗排模块的结果,对候选集进行打分和排序。精排需要在最大时延允许的情况下,保证打分的精准性,是整个系统中至关重要的一个模块,也是最复杂,研究最多的一个模块。
精排是推荐系统各层级中最纯粹的一层,他的目标比较单一且集中,一门心思的实现目标的调优即可。最开始的时候精排模型的常见目标是ctr,后续逐渐发展了cvr等多类目标。精排和粗排层的基本目标是一致的,都是对商品集合进行排序,但是和粗排不同的是,精排只需要对少量的商品(即粗排输出的商品集合的topN)进行排序即可。因此,精排中可以使用比粗排更多的特征,更复杂的模型和更精细的策略(用户的特征和行为在该层的大量使用和参与也是基于这个原因)。
精排层模型是推荐系统中涵盖的研究方向最多,有非常多的子领域值得研究探索,这也是推荐系统中技术含量最高的部分,毕竟它是直接面对用户,产生的结果对用户影响最大的一层。目前精排层深度学习已经一统天下了,精排阶段采用的方案相对通用,首先一天的样本量是几十亿的级别,我们要解决的是样本规模的问题,尽量多的喂给模型去记忆,另一个方面时效性上,用户的反馈产生的时候,怎么尽快的把新的反馈给到模型里去,学到最新的知识。

0.2.3 推荐系统的评价标准

根据目的,推荐系统显然是具有有现实意义的评价标准的,当评价目标的定义有变化时,推荐结果也会发生变化。

评价目标包括但不限于下图(来源 推荐系统入门):
在这里插入图片描述

  • 准确度:打分系统,top N推荐
  • 覆盖率:对物品长尾的发掘能力
  • 多样性:推荐列表中物品两两之间的不相似性
  • 新颖度:给用户suprise
  • 惊喜度:推荐和用户历史兴趣不相似,却满意的
  • 信任度:提供可靠的推荐理由
  • 实时性:实时更新程度

具体到评价标准,例子包括

  • CTR:点击率(点击量/展示量)
  • CVR:转化的情况,商家关注的指标(转化量/点击量)
  • GPM:平均1000次展示,平均成交金额

  • 根据场景需求进行选择。场景很多,包括(来源 推荐系统入门):
    在这里插入图片描述
    本次涉及的模型,均是面对CTR(点击率)的模型。

1 DeepFM

1.1 模型诞生的背景

对于CTR问题,被证明的最有效的提升任务表现的策略是特征组合(Feature Interaction),在CTR问题的探究历史上来看就是如何更好地学习特征组合,进而更加精确地描述数据的特点。

显然,随着特征组合的增多,会导致模型复杂度的爆炸,从而拖慢计算速度。而推荐系统的实际应用还有一个非常重要的要求是实时性,因此“如何高效地学习特征组合”成为一个很重要的问题。

DNN是很好地解决这一问题的方法,但也存在局限性:需要合理处理特征的表述形式,来防止维度猛增,在此基础上增加层数,可以实现高阶特征组合,但仍缺少低阶的特征组合

当我们使用DNN网络解决推荐问题的时候存在网络参数过于庞大的问题,这是因为在进行特征处理的时候我们需要使用one-hot编码来处理离散特征,这会导致输入的维度猛增。这里借用AI大会的一张图片:
在这里插入图片描述
这样庞大的参数量也是不实际的。为了解决DNN参数量过大的局限性,可以采用非常经典的Field思想,将OneHot特征转换为Dense Vector
在这里插入图片描述
此时通过增加全连接层就可以实现高阶的特征组合,如下图所示:
在这里插入图片描述
但是仍然缺少低阶的特征组合。

此时在DNN中引入FM来表示低阶特征组合,这就有了FNN(串行FM和DNN),和PNN(在FNN的基础上又串入了一个product层)。

结合FM和DNN其实有两种方式,可以并行结合也可以串行结合。这两种方式各有几种代表模型。在DeepFM之前有FNN,虽然在影响力上可能并不如DeepFM,但是了解FNN的思想对我们理解DeepFM的特点和优点是很有帮助的。
在这里插入图片描述
FNN是使用预训练好的FM模块,得到隐向量,然后把隐向量作为DNN的输入,但是经过实验进一步发现,在Embedding layer和hidden layer1之间增加一个product层(如上图所示)可以提高模型的表现,所以提出了PNN,使用product layer替换FM预训练层。

但是上述模型由于直接串行了FM和DNN,对低阶特征的学习还是不太够,所以又进化出了Wide&Deep模型(改串行为并行),由google提出(具体可以参考教程)。

FNN和PNN模型仍然有一个比较明显的尚未解决的缺点:对于低阶组合特征学习到的比较少,这一点主要是由于FM和DNN的串行方式导致的,也就是虽然FM学到了低阶特征组合,但是DNN的全连接结构导致低阶特征并不能在DNN的输出端较好的表现。
将串行方式改进为并行方式能比较好的解决这个问题。于是Google提出了Wide&Deep模型,但是如果深入探究Wide&Deep的构成方式,虽然将整个模型的结构调整为了并行结构,在实际的使用中Wide Module中的部分需要较为精巧的特征工程,换句话说人工处理对于模型的效果具有比较大的影响(这一点可以在Wide&Deep模型部分得到验证)。
在这里插入图片描述

但是,简单的并行结合仍然存在问题,主要受限于特征的组合形式:
在output Units阶段直接将低阶和高阶特征进行组合,很容易让模型最终偏向学习到低阶或者高阶的特征,而不能做到很好的结合。

DeepFM就是在这个背景下诞生的,它试图解决高阶及低阶的良好结合问题。

1.2 模型的结构(思考题2)

先摆出一个模型图
在这里插入图片描述
其中:前面的Field和Embedding处理是和前面的方法是相同的,如上图中的绿色部分;DeepFM将Wide部分替换为了FM layer如上图中的蓝色部分

教程中提示我们模型中有三个需要注意的地方:

  • Deep模型部分
    Deep Module是为了学习高阶的特征组合,使用用全连接的方式将Dense Embedding输入到Hidden Layer,这里面Dense Embeddings就是为了解决DNN中的参数爆炸问题,这也是推荐模型中常用的处理方法。Embedding层的输出是将所有id类特征对应的embedding向量concat到到一起输入到DNN中。
    在这里插入图片描述

  • FM模型部分
    FM Layer是由一阶特征和二阶特征Concatenate到一起在经过一个Sigmoid得到logits。在实现的时候需要分开考虑。
    在这里插入图片描述

  • Sparse Feature中黄色和灰色节点代表什么意思【思考题2】
    在DeepFM模型的结构图中,Sparse Features中的黄色节点与模型连接,参与了训练,而灰色节点没有参与训练。
    根据原论文,黄色节点代表输入的稀疏向量中数值为1的点,灰色节点代表数值为0的点,因为数值0输入模型中学习得到的权重也仍然为零,所以可以看作是不参与训练。
    (Sparse Feature全部为需要dense的离散特征(类别型特征))

1.3 模型的代码实现

rechub中实现了DeepFM模型,整体模型架构如下:
在这里插入图片描述
模型大致由两部分组成

  • FM(进一步细分为一阶特征的处理和二阶特征的处理)
  • DNN
    因此实现细化为
  • FM的线性特征处理
  • FM的二阶特征交叉处理
  • DNN的高阶特征交叉

在代码中也能够清晰的看到这个结构。此外每一部分可能由是由不同的特征组成,所以在构建模型的时候需要分别对这三部分输入的特征进行选择。

代码如下,更详细的代码见GitHub

def DeepFM(linear_feature_columns, dnn_feature_columns):
    # 构建输入层,即所有特征对应的Input()层,这里使用字典的形式返回,方便后续构建模型
    dense_input_dict, sparse_input_dict = build_input_layers(linear_feature_columns + dnn_feature_columns)

    # 将linear部分的特征中sparse特征筛选出来,后面用来做1维的embedding
    linear_sparse_feature_columns = list(filter(lambda x: isinstance(x, SparseFeat), linear_feature_columns))

    # 构建模型的输入层,模型的输入层不能是字典的形式,应该将字典的形式转换成列表的形式
    # 注意:这里实际的输入与Input()层的对应,是通过模型输入时候的字典数据的key与对应name的Input层
    input_layers = list(dense_input_dict.values()) + list(sparse_input_dict.values())

    # linear_logits由两部分组成,分别是dense特征的logits和sparse特征的logits
    linear_logits = get_linear_logits(dense_input_dict, sparse_input_dict, linear_sparse_feature_columns)

    # 构建维度为k的embedding层,这里使用字典的形式返回,方便后面搭建模型
    # embedding层用户构建FM交叉部分和DNN的输入部分
    embedding_layers = build_embedding_layers(dnn_feature_columns, sparse_input_dict, is_linear=False)

    # 将输入到dnn中的所有sparse特征筛选出来
    dnn_sparse_feature_columns = list(filter(lambda x: isinstance(x, SparseFeat), dnn_feature_columns))

    fm_logits = get_fm_logits(sparse_input_dict, dnn_sparse_feature_columns
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SheltonXiao

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值