21|注意力机制、兴趣演化:推荐系统如何抓住用户的心?

你好,我是王喆。

近几年来,注意力机制、兴趣演化序列模型和强化学习,都在推荐系统领域得到了广泛的应用。它们是深度学习推荐模型的发展趋势,也是我们必须要储备的前沿知识。

作为一名算法工程师,足够的知识储备是非常重要的,因为在掌握了当下主流的深度学习模型架构(Embedding MLP架构、Wide&Deep和DeepFM等等)之后,要想再进一步提高推荐系统的效果,就需要清楚地知道业界有哪些新的思路可以借鉴,学术界有哪些新的思想可以尝试,这些都是我们取得持续成功的关键。

所以,我会用两节课的时间,带你一起学习这几种新的模型改进思路。今天我们先重点关注注意力机制和兴趣演化序列模型,下节课我们再学习强化学习。

什么是“注意力机制”?

“注意力机制”来源于人类天生的“选择性注意”的习惯。最典型的例子是用户在浏览网页时,会有选择性地注意页面的特定区域,而忽视其他区域。

比如,图1是Google对大量用户进行眼球追踪实验后,得出的页面注意力热度图。我们可以看到,用户对页面不同区域的注意力区别非常大,他们的大部分注意力就集中在左上角的几条搜索结果上。

那么,“注意力机制”对我们构建推荐模型到底有什么价值呢?

价值是非常大的。比如说,我们要做一个新闻推荐的模型,让这个模型根据用户已经看过的新闻做推荐。那我们在分析用户已浏览新闻的时候,是把标题、首段、全文的重要性设置成完全一样比较好,还是应该根据用户的注意力不同给予不同的权重呢?当然,肯定是后者比较合理,因为用户很可能都没有注意到正文最后的几段,如果你分析内容的时候把最后几段跟标题、首段一视同仁,那肯定就把最重要的信息给淹没了。

事实上,近年来,注意力机制已经成功应用在各种场景下的推荐系统中了。其中最知名的,要数阿里巴巴的深度推荐模型,DIN(Deep Interest Network,深度兴趣网络)。接下来,我们就一起来学习一下DIN的原理和模型结构。

注意力机制在深度兴趣网络DIN上的应用

DIN模型的应用场景是阿里最典型的电商广告推荐。对于付了广告费的商品,阿里会根据模型预测的点击率高低,把合适的广告商品推荐给合适的用户,所以DIN模型本质上是一个点击率预估模型。

注意力机制是怎么应用在DIN模型里的呢?回答这个问题之前,我们得先看一看DIN在应用注意力机制之前的基础模型是什么样的,才能搞清楚注意力机制能应用在哪,能起到什么作用。

下面的图2就是DIN的基础模型Base Model。我们可以看到,Base Model是一个典型的Embedding MLP的结构。它的输入特征有用户属性特征(User Proflie Features)、用户行为特征(User Behaviors)、候选广告特征(Candidate Ad)和场景特征(Context Features)。

用户属性特征和场景特征我们之前也已经讲过很多次了,这里我们重点关注用户的行为特征和候选广告特征,也就是图2中彩色的部分。

我们可以清楚地看到,用户行为特征是由一系列用户购买过的商品组成的,也就是图上的Goods 1到Goods N,而每个商品又包含了三个子特征,也就是图中的三个彩色点,其中红色代表商品ID,蓝色是商铺ID,粉色是商品类别ID。同时,候选广告特征也包含了这三个ID型的子特征,因为这里的候选广告也是一个阿里平台上的商品。

我们之前讲过,在深度学习中,只要遇到ID型特征,我们就构建它的Embedding,然后把Embedding跟其他特征连接起来,输入后续的MLP。阿里的Base Model也是这么做的,它把三个ID转换成了对应的Embedding,然后把这些Embedding连接起来组成了当前商品的Embedding。

完成了这一步,下一步就比较关键了,因为用户的行为序列其实是一组商品的序列,这个序列可长可短,但是神经网络的输入向量的维度必须是固定的,那我们应该怎么把这一组商品的Embedding处理成一个长度固定的Embedding呢?图2中的SUM Pooling层的结构就给出了答案,就是直接把这些商品的Embedding叠加起来,然后再把叠加后的Embedding跟其他所有特征的连接结果输入MLP。

但这个时候问题又来了,SUM Pooling的Embedding叠加操作其实是把所有历史行为一视同仁,没有任何重点地加起来,这其实并不符合我们购物的习惯。

举个例子来说,候选广告对应的商品是“键盘”,与此同时,用户的历史行为序列中有这样几个商品ID,分别是“鼠标”“T恤”和“洗面奶”。从我们的购物常识出发,“鼠标”这个历史商品ID对预测“键盘”广告点击率的重要程度应该远大于后两者。从注意力机制的角度出发,我们在购买键盘的时候,会把注意力更多地投向购买“鼠标”这类相关商品的历史上,因为这些购买经验更有利于我们做出更好的决策。

好了,现在我们终于看到了应用注意力机制的地方,那就是用户的历史行为序列。阿里正是在Base Model的基础上,把注意力机制应用在了用户的历史行为序列的处理上,从而形成了DIN模型。那么,DIN模型中应用注意力机制的方法到底是什么呢?

我们可以从下面的DIN模型架构图中看到,与Base Model相比,DIN为每个用户的历史购买商品加上了一个激活单元(Activation Unit),这个激活单元生成了一个权重,这个权重就是用户对这个历史商品的注意力得分,权重的大小对应用户注意力的高低。

那现在问题就只剩下一个了,这个所谓的激活单元,到底是怎么计算出最后的注意力权重的呢?为了搞清楚这个问题,我们需要深入到激活单元的内部结构里面去,一起来看看图3右上角激活单元的详细结构。

它的输入是当前这个历史行为商品的Embedding,以及候选广告商品的Embedding。我们把这两个输入Embedding,与它们的外积结果连接起来形成一个向量,再输入给激活单元的MLP层,最终会生成一个注意力权重,这就是激活单元的结构。简单来说,激活单元就相当于一个小的深度学习模型,它利用两个商品的Embedding,生成了代表它们关联程度的注意力权重

到这里,我们终于抽丝剥茧地讲完了整个DIN模型的结构细节。如果你第一遍没理解清楚,没关系,对照着DIN模型的结构图,反复再看几遍我刚才讲的细节,相信你就能彻底消化吸收它。

注意力机制对推荐系统的启发

注意力机制的引入对于推荐系统的意义是非常重大的,它模拟了人类最自然,最发自内心的注意力行为特点,使得推荐系统更加接近用户真实的思考过程,从而达到提升推荐效果的目的。

从“注意力机制”开始,越来越多对深度学习模型结构的改进是基于对用户行为的深刻观察而得出的。由此,我也想再次强调一下,一名优秀的算法工程师应该具备的能力,就是基于对业务的精确理解,对用户行为的深刻观察,得出改进模型的动机,进而设计出最合适你的场景和用户的推荐模型。

沿着这条思路,阿里的同学们在提出DIN模型之后,并没有停止推荐模型演化的进程,他们又在2019年提出了DIN模型的演化版本,也就是深度兴趣进化网络DIEN(Deep Interest Evolution Network)。这个DIEN到底在DIN的基础上做了哪些改进呢?

兴趣进化序列模型

无论是电商购买行为,还是视频网站的观看行为,或是新闻应用的阅读行为,特定用户的历史行为都是一个随时间排序的序列。既然是和时间相关的序列,就一定存在前后行为的依赖关系,这样的序列信息对于推荐过程是非常有价值的。为什么这么说呢?

我们还拿阿里的电商场景举个例子。对于一个综合电商来说,用户兴趣的迁移其实是非常快的。比如,上一周一位用户在挑选一双篮球鞋,这位用户上周的行为序列都会集中在篮球鞋这个品类的各个商品上,但在他完成这一购物目标后,这一周他的购物兴趣就可能变成买一个机械键盘,那这周他所有的购买行为都会围绕机械键盘这个品类展开。

因此,如果我们能让模型预测出用户购买商品的趋势,肯定会对提升推荐效果有益。而DIEN模型正好弥补了DIN模型没有对行为序列进行建模的缺陷,它围绕兴趣进化这个点进一步对DIN模型做了改进。

图4就是DIEN模型的架构图,这个模型整体上仍然是一个Embedding MLP的模型结构。与DIN不同的是,DIEN用“兴趣进化网络”也就是图中的彩色部分替换掉了原来带有激活单元的用户历史行为部分。这部分虽然复杂,但它的输出只是一个h'(T)的Embedding向量,它代表了用户当前的兴趣向量。有了这个兴趣向量之后,再把它与其他特征连接在一起,DIEN就能通过MLP作出最后的预测了。

好了,现在问题的焦点就在,DIEN模型是如何生成这个兴趣向量的。关键就在于DIEN模型中彩色部分的三层兴趣进化网络,下面,我就按照从下到上的顺序,给你讲讲它们的名称和作用。

最下面一层是行为序列层(Behavior Layer,浅绿色部分)。它的主要作用和一个普通的Embedding层是一样的,负责把原始的ID类行为序列转换成Embedding行为序列。

再上一层是兴趣抽取层(Interest Extractor Layer,浅黄色部分)。它的主要作用是利用GRU组成的序列模型,来模拟用户兴趣迁移过程,抽取出每个商品节点对应的用户兴趣。

最上面一层是兴趣进化层(Interest Evolving Layer,浅红色部分)。它的主要作用是利用AUGRU(GRU with Attention Update Gate)组成的序列模型,在兴趣抽取层基础上加入注意力机制,模拟与当前目标广告(Target Ad)相关的兴趣进化过程,兴趣进化层的最后一个状态的输出就是用户当前的兴趣向量h'(T)。

你发现了吗,兴趣抽取层和兴趣进化层都用到了序列模型的结构,那什么是序列模型呢?直观地说,图5就是一个典型的序列模型的结构,它和我们之前看到的多层神经网络的结构不同,序列模型是“一串神经元”,其中每个神经元对应了一个输入和输出。

在DIEN模型中,神经元的输入就是商品ID或者前一层序列模型的Embedding向量,而输出就是商品的Embedding或者兴趣Embedding,除此之外,每个神经元还会与后续神经元进行连接,用于预测下一个状态,放到DIEN里就是为了预测用户的下一个兴趣。这就是序列模型的结构和作用。

至于上面提到过的GRU序列模型,它其实是序列模型的一种,根据序列模型神经元结构的不同,最经典的有RNNLSTMGRU这3种。这里我们就不展开讲了,对理论感兴趣的同学,可以点击我给出的超链接,参考这几篇论文做更深入的研究。

事实上,序列模型已经不仅在电商场景下,成功应用于推测用户的下次购买行为,在YouTube、Netflix等视频流媒体公司的视频推荐模型中,序列模型也用来推测用户的下次观看行为(Next Watch)。除此之外,音乐类应用也非常适合使用序列模型来预测用户的音乐兴趣变化。所以,掌握DIEN模型的架构对于拓宽我们的技术视野非常有帮助。

小结

注意力机制和兴趣演化序列模型的加入,让推荐系统能够更好地抓住用户的心。

对于注意力机制来说,它主要模拟了人类注意力的天性。具体到阿里的DIN模型上,它利用激活单元计算出用户对于不同历史商品的注意力权重,针对当前广告商品,作出更有针对性的预测。

而序列模型更注重对序列类行为的模拟和预测。典型的例子是DIEN模型对用户购买兴趣进化过程的模拟。DIEN模型可以应用的场景非常广泛,包括电商平台的下次购买,视频网站的下次观看,音乐App的下一首歌曲等等。

总的来说,注意力机制的引入是对经典深度学习模型的一次大的改进,因为它改变了深度学习模型对待用户历史行为“一视同仁”的弊端。而序列模型则把用户行为串联起来,让用户的兴趣随时间进行演化,这也是之前的深度学习模型完全没有考虑到的结构。

最后,我把今天的重要概念总结在了表格中,方便你及时查看和复习。

课后思考

DIN使用了一个结构比较复杂的激活单元来计算注意力权重,你觉得有没有更简单、更实用的方式来生成注意力权重呢?其实,计算注意力权重就是为了计算历史行为物品和广告物品的相关性,在这个过程中,你觉得能不能利用到特征交叉的知识呢?为什么?

欢迎把你的思考和疑问写在留言区,如果你的朋友们也在关注注意力机制和兴趣演化序列模型的发展,那不妨也把这节课转发给他们,我们下节课见!

精选留言

  • 浣熊当家

    2020-11-29 02:23:01

    图3中DIN的激活单元里我们用到了“外积”, 之前的课程里感觉我们多数是用“内积”。请问老师,如何选择使用“内积”和“外积”, 有什么规则吗?
    作者回复

    本质上都是做特征交叉,计算相似性的方式,一般来说,外积因为输出是一个向量,所以表达能力更强一些。

    2020-12-01 12:20:15

  • 李元

    2021-01-09 14:14:52

    根据NLP的发展,我觉得GRU这种提取序列信息的方式肯定会被Transformer取代。不知道有没有人已经发paper了。
    作者回复

    已经不少了,最近提的比较多的是bert for rec

    2021-01-10 03:50:58

  • Sebastian

    2020-11-28 09:50:52

    老师想问下,DIN模型在工业界的排序阶段使用的多吗?因为我在想在业界每个用户都有比较长的用户行为序列的场景可能还是少数,很多公司的场景可能是,用户进入app端后点击了2-3次后可能就没有后续行为了,那么这种场景下,DIN应该就不适用了吧?
    作者回复

    DIN比DIEN的使用场景要求低很多,我知道很多团队在用,或者说很多团队在用DIN的思路来构建自己的模型。

    就我自己的实践经验,attention机制是非常有价值的,推荐在自己的场景下尝试。

    2020-12-01 09:54:27

  • Leo Zhao

    2020-11-28 20:23:23

    思考题:广告和历史行为 相关性 其实就是 广告物品与历史物品的相关性,可以用一个dot层 或者通过物品embedding 算出similarity 当作feature 直接输入。
    作者回复

    非常好

    2020-12-01 09:56:44

  • fsc2016

    2020-12-09 16:38:20

    1,老师,看了最近几章介绍的推荐模型,发现神经网络的隐层数量都比较少(相对cv),这个是防止模型太复杂,导致线上推断太慢吗
    2,请教下老师,业界常用的MLP隐层数量和神经元数量,有没有一个大致的取值范围?
    作者回复

    这个问题其实挺好的。相比CV动辄上百的隐层数量,推荐模型真的是比较“浅”的了。

    隐层数量大致在1到5之间吧,确实在推荐问题上再提高隐层数量效果上意义不大,inference延迟还大,得不偿失。

    至于为什么相比cv,推荐模型不需要那么多隐层,你能分享下你的思考吗?

    2020-12-10 08:31:03

  • 2021-01-06 15:17:52

    老师您好,我有一个问题请教您:
    transformer中有position encoding,而在推荐的领域中,点击的序列中同样有时间间隔的因素,例如取用户最近若干次点击,可能每次间隔时间不等。这个间隔时间应该是有信息可以揭示用户兴趣的变迁速率等信息的吧?但是如何将其引入到推荐序列中呢?
    是类似于transformer中 position learned encoding这样么?
    作者回复

    这是一个很好的idea。但说实话我还没有见到非常成功的案例说能够很好的利用event interval然后取得很大的收益。也许是这个信号本身不够强,带来的收益有限。

    如果今后发现相关paper,可以分享到这里。

    2021-01-07 02:12:12

  • 小红亮

    2021-04-10 11:22:59

    老师,请教一下DIEN中用到了GRU,它是串行处理的,那么推理的过程会比较慢,这就不太适合延长要求很高的场景,比如计算广告,那对于电商场景来说它DIEN的推理延迟能满足业务要求吗,或者有什么优化手段可以解决延迟问题吗
    作者回复

    这是个非常好的问题,一般上线前要做模型的割裂,把复杂部分生成的Embedding做预生成,线上直接使用。

    2021-04-11 11:58:02

  • 浣熊当家

    2020-11-29 02:12:03

    想请教老师一个题外问题, 您作为面试官的话,对于MLE的候选人会更注重考察哪方面的能力(比如算法coding, 系统架构设计,机器学习的领域知识)?,然后对于机器学习的各种模型会期待候选人有多深的了解(比如说了解DIEN的各个层级的结构就够了,还是要知道GRU是具体如何实现的)。
    随着老师课程,我对深度学习燃起了更大的热情,觉得想真正提高的话,最好的方法还是能从事做深度学习的工作,想知道从面试角度来讲,怎么学习才是性价比最高的选择, (比如注重项目经验,刷题,还是算法的理论公式推到)。
    作者回复

    我在知乎有一篇专栏文章专门讲面试,可以参考 https://zhuanlan.zhihu.com/p/76827460

    我在课程最后也会有一些总结。

    2020-12-01 12:21:42

  • Geek_3c29c3

    2020-12-16 16:16:32

    老师,我对DIN里面的注意力机制有一点疑问:就是DIN的目标广告的id和usr behavior的id是同一领域的id,那能不能推广到比如我们的广告id和商城内的物品不是同属于一个id系列的。就是广告的内容和商城的内容(包含用户行为)是不一样的,这时候还可以用DIN的注意力机制了吗?如果不能,还有什么方法呢?
    作者回复

    这是个好问题,我觉得是可以的,因为广告内容和商城内容从经验上来说也会有一定的相关性。

    就拿deepfm的思路来说,其实可以做任意两个特征之间的交叉。对于注意力机制,当然也可以学任意两个特征间的注意力。但到底作用有多大,能不能提高效果,就看自己的实践了。

    2020-12-17 03:46:20

  • Geek1254

    2021-03-03 20:19:59

    老师您好。
    1.我看到在Sparrow里面的代码。没有严格意义上使用外积吧?使用的是element-wise sub & multipy。然后用这两个向量去拼接,组成的activation_all。请问这是老师实践之后得到的方法吗?
    2. 我看到参考代码中使用的是PRelu(),请问这种激活函数适合哪些场景呢?
    作者回复

    1. 确实没有使用外积。我的实践经验来看外积的作用不是很大,而且大幅增加参数量,所以我个人不是很喜欢外积操作。
    2. PRelu几乎是深度学习默认的激活函数,速度比较快,梯度消散问题比较小。如果有特殊需要可以测试其他激活函数,看实践。

    2021-03-06 17:53:10

  • 庄小侠

    2021-02-18 19:08:18

    老师,我看了下这节课DIN.py里面的代码,发现 user_behaviors_emb_layer和candidate_emb_layer是两套不同的embding向量,请问这是为什么啊?我的理解是它们都是电影的embding向量,共用一套embding不是参数量更少嘛。实际使用里面,大家都是这样用嘛?
    作者回复

    问的非常好。其实应该是共用一套,用shared embedding。DIN的代码是咱们同学贡献的,如果可以改进的话,可以提交PR,非常欢迎越来越多人参与进来。

    2021-02-23 10:09:35

  • 张弛 Conor

    2020-11-27 19:01:15

    思考题:可以借鉴FM及DeepFM中特征交叉的计算方式,对两个向量直接计算内积,或者先通过Embedding层转换成维度相等的Embedding再求内积,又或者可以像双塔结构一样,设计一个历史行为物品塔和广告物品塔,在塔的最后通过求内积或者拼接后用全连接层输出权重。
    课后疑问:
    DIEN模型中输出的用户当前兴趣向量h'(T)是由用户的历史兴趣向量所得,我的问题是,DIEA能否探索到历史兴趣以外的兴趣呢?如果可以的话,是如何在没有其他兴趣向量的参与下做到的呢?如果不行的话,请问老师在实践中是否有什么方法,可以对用户历史兴趣以外的兴趣进行探索的方法呢?
    作者回复

    思考题的回答很赞同。

    关于疑问,我不是很清楚你的问题,什么叫做“历史兴趣以外的兴趣”?

    2020-12-01 09:47:54

  • 那时刻

    2020-11-27 11:47:50

    DIN 使用了一个结构比较复杂的激活单元来计算注意力权重,能否有其它方法来计算呢?我开始想到的上节课提到的特征交叉,我回顾了下特征交叉,它是加强模型对于特征组合和特征交叉的学习能力以及对于未知特征组合样本的预测能力。而注意力权重是计算历史物品和广告物品相关行。我觉得它们是不同的。
    作者回复

    其实只要是接收两个embedding,生成一个输出分数的结构理论上都可以作为激活单元。所以最简单的结构其实就是dot product或者cosin similarity。因为它们刚好揭示了两个item之间的相似度。

    2020-12-01 09:46:20

  • 张弛 Conor

    2020-11-27 19:13:42

    课后疑问:
    请问老师,对于DIN和DIEN这种包含N个历史商品的模型,如果用户历史商品数小于N,那么这些位置应该如何去填充呢?如果用户商品数大于N,是否是选择最近的N个商品呢?
    作者回复

    大于N肯定要选择最近的N个, 小于N考虑使用masking layer
    tf.keras.layers.Masking

    2020-12-01 13:11:24

  • 范闲

    2020-12-02 14:57:29

    1.历史行为和广告物品直接dot
    2.利用双塔模型,取最终的输出做特征
    作者回复

    没问题

    2020-12-03 04:15:01

  • Geek_e0d66a

    2020-11-28 23:19:41

    请问老师,DIN中的激活单元,的网络结构中,为什么用户Embedding和候选集的embedding的外积,再拼接在一起??
    作者回复

    因为DIN的同学经过多次实验之后这个网络结构最好。曾经最早的DIN的激活单元是通过element wise minus做特征交叉,但是几经修改,所以都是实践的结果。

    2020-12-01 12:22:45

  • VictorWu

    2021-01-13 16:54:06

    DIN.py 文件中第137行 tf.keras没有sum方法,sum方法应该在tf.keras.backend中

    我发了个pr哈
    作者回复

    感谢,我找时间review。

    2021-01-14 02:39:31

  • 邓生

    2020-12-22 11:25:53

    关于sum pooling有一点不明确,假如user1买了good1,对应embedding是[1,2,3],sum pooling后是[1,2,3],user2买了good1 good2,对应embedding是[1,2,3]和[4,5,6],sum pooling 后是[5,7,9]。然后后续都输入到神经网络。这样就实现了神经网络固定维度输入,是这样理解吗?
    作者回复

    是这样

    2020-12-23 03:38:21

  • freedom

    2020-11-30 19:53:05

    老师我想问一个问题,在训练模型过程中,在用到BN的时候,经常会出现BN层训练不好的情况,具体表现为训练时候(is_training=TRUE)准召比较高。但是设置is_training为false的时候 准召降得比较厉害。moving_mean和moving_var也都有更新。请问这是因为什么原因呢,该如何解决呢?
    作者回复

    抱歉不能提供很多经验上的指导,我很少在推荐模型里面使用BN层,从原理上怀疑是某些类别型特征非常系数导致的,权当猜测。
    如果其他同学有相关经验,欢迎讨论。

    2020-12-01 12:59:49

  • 墨量

    2021-01-12 23:54:50

    大佬,这一句(它的输入是当前这个历史行为商品的 Embedding,以及候选广告商品的 Embedding)加几个字,变为:
    它的输入是当前这个【用户的】历史行为商品的 Embedding,以及候选广告商品的 Embedding。
    是不是更好理解哇
    作者回复

    这不是好不好理解的问题,是你理解错了的问题。

    2021-01-13 09:59:29