600字范文,内容丰富有趣,生活中的好帮手!
600字范文 > 【注意力+推荐系统】Attention!当推荐系统遇见注意力机制

【注意力+推荐系统】Attention!当推荐系统遇见注意力机制

时间:2019-02-17 11:10:40

相关推荐

【注意力+推荐系统】Attention!当推荐系统遇见注意力机制

点击上方,选择星标,每天给你送干货!

NewBeeNLP原创出品

公众号专栏作者@上杉翔二

悠闲会·信息检索

当注意力机制都已经变成很tasteless的手法的时候,使用或者魔改注意力机制一定要专注讲好自己的故事:即『为什么要用Attention,为什么要魔改Attention

现阶段从传统的CF,FM等方法到NFM,DeepFM等等,虽然开始用深度学习DNN来处理深度的特征交叉,还缺少的主要有两点:

用户历史行为的特征挖掘。

特征冗余度问题。二阶or高阶的特征基本都是枚举式的。

DIN和DIEN都是阿里针对CTR预估的模型,都主要是对用户历史行为数据的进一步挖掘的工作。CTR预估任务是,根据给定广告/物品、用户和大量的上下文情况等信息,对点击进行预测,所以对用户的兴趣理解,历史行为数据非常重要。

然后自从Transformer出现,BERT在NLP界屠榜,所以很自然在推荐系统上的应用也开始升级。本篇博文将整理四篇关于Attention的文章,从普通的Attention一路升级到BERT。

DIN

论文:Deep Interest Network for Click-Through Rate Prediction

地址:/abs/1706.06978

DIN这篇文章的Attention故事出发点在于两点观察:

「Diversity」:多样性是指用户的兴趣是广泛的,一个用户会对多个物品,多个领域感兴趣

「Local activation」:部分对应是指只有部分历史数据与目前推荐的物品相关(如推荐零食物品就与用户以前买过什么装备无关)

那么怎么把这部分相关历史给动态的捕捉到呢?DIN的做法是,将用户的历史数据和当前的 item之间计算相似度,即计算Attention值,对每个用户的兴趣表示都赋予不同的权值,然后再加权求和。先看公式:

其中 代表用户的特征向量, 代表用户兴趣的特征向量(用户历史行为), 代表物品的特征向量。 是用户兴趣和候选物品的相关性 ,对齐了用户兴趣,实际上就是解决了Local Activation问题。然后用户特征向量就是所有加权后的历史行为和了。

整个模型框架如上图所示,左边是base模型,主要是将特征one-hot或multi-hot(主要是对用户历史行为数据)后再embedding,值得注意的是,每个用户的历史点击个数是不相等的,但需要变成一个固定长的向量,所以对于multi-hot的特征会多做一个element-wise(即图中的+号),即不管用户的行为序列有多长,都会pooling成同一个维度。最后拼接之后用MLP预测最终的分数。但是这个base版本作者认为pooling的结果显然丢失了大量信息,很显然使用Attention能够提高用户行为特征的表达,所以右边的图就是加了Attention之后的版本。

加注意力的思路很简单。然后还有两个重要的Trick:

「1. Data Dependent Activation Function(Dice激活函数)」

原来一般的Relu激活函数在值大于0时y=x,小于0时直接输出为0,这样导致了许多节点的“死亡”,更新缓慢。因此Leaky Relu在左边小于0的部分也给一定的梯度即y=ax。但这样仍然是不够的,因为它们的默认分割点都是在0这个地方(比0大的左边或者右边),不合理,分割点应该由数据决定,所以需要Dice。

第一个式子是Leaky的改版,但是此时在Leaky Relu左边的y=ax上会多一个控制的参数p,而p是对数据进行均值归一化后(即利用数据的均值和方差进行调整)的结果,即把整个激活函数移动到了数据的均值处。

优点:根据数据分布灵活调整阶跃变化点,具有BN的优点

缺点:BN复杂度,比较耗时

defdice(_x,axis=-1,epsilon=0.000000001,name=''):#DataAdaptiveActivationFunctionwithtf.variable_scope(name_or_scope='',reuse=tf.AUTO_REUSE):alphas=tf.get_variable('alpha'+name,_x.get_shape()[-1],initializer=tf.constant_initializer(0.0),dtype=tf.float32)beta=tf.get_variable('beta'+name,_x.get_shape()[-1],initializer=tf.constant_initializer(0.0),dtype=tf.float32)input_shape=list(_x.get_shape())reduction_axes=list(range(len(input_shape)))delreduction_axes[axis]broadcast_shape=[1]*len(input_shape)broadcast_shape[axis]=input_shape[axis]#case:trainmode(usesstatsofthecurrentbatch)#计算batch的均值和方差mean=tf.reduce_mean(_x,axis=reduction_axes)brodcast_mean=tf.reshape(mean,broadcast_shape)std=tf.reduce_mean(tf.square(_x-brodcast_mean)+epsilon,axis=reduction_axes)std=tf.sqrt(std)brodcast_std=tf.reshape(std,broadcast_shape)x_normed=tf.layers.batch_normalization(_x,center=False,scale=False,name=name,reuse=tf.AUTO_REUSE)#x_normed=(_x-brodcast_mean)/(brodcast_std+epsilon)x_p=tf.sigmoid(beta*x_normed)returnalphas*(1.0-x_p)*_x+x_p*_x#根据原文中给的公式计算defparametric_relu(_x):#PRELU激活函数,形式上和leakReLU很像,只是它的alpha可学习#alpha=0,退化成ReLU。alpha不更新,退化成Leakwithtf.variable_scope(name_or_scope='',reuse=tf.AUTO_REUSE):alphas=tf.get_variable('alpha',_x.get_shape()[-1],initializer=tf.constant_initializer(0.0),dtype=tf.float32)pos=tf.nn.relu(_x)neg=alphas*(_x-abs(_x))*0.5#用alpha控制returnpos+neg

完整的源码笔记:/nakaizura/Source-Code-Notebook/tree/master/DIN

「2. Adaptive Regularization(自适应正则)」

这个方法提出的动机是输入的数据长尾分布,非常稀疏维度高应该怎么防止过拟合。直接L1、L2、Dropout效果不佳,直接丢弃又损失了信息可能加重过拟合,怎么办?自适应的正则方法,按照出现的频率调整正则化的强化,即频率高的,正则化强度小,频率低的,正则化强度高。也就是说会惩罚那些出现频率低的item。

DIN的设计对工业界的帮助更大,因为上线的时候受制于内存所以User Embedding不能很大,那么显然无法很好的表示用户特征,想表示用户的多兴趣(多峰)就很难了。此时DIN基于用户历史行为再加入Attention就很好的缓解了这个问题。

缺点:用到了历史行为数据,但是忽略了序列关系。

DINE

论文:Deep Interest Evolution Network for Click-Through Rate Prediction

地址:/abs/1809.03672

升级DIN,改进DIN中存在两个缺点:

用户兴趣应该是不断进化的。DIN抽取的用户兴趣是固定的,没有捕获到兴趣的这种进化性

如何保证通过用户的显式的行为得到的兴趣是有效的

所以DIEN中主要开发了兴趣抽取层Interest Extractor Layer、兴趣进化层Interest Evolution Layer以解决上面两个缺点。

Interest Extractor Layer

兴趣抽取层的主要目标是提取出兴趣序列,而用户在某一时刻的兴趣是具有时序关系的,所以设计了GRU with attentional update gate (AUGRU,这个是Evolution Layer中加入注意力后的形态),增强在兴趣变化中相关兴趣的影响,减弱不相关兴趣的影响。同时为了判定兴趣是否表示的合理,又增加了一个辅助loss,来提升兴趣表达的准确性:

如上图中左边的小块是辅助网络,输入用户下一时刻真实的行为e(t+1)作为正例,负采样的行为为负例e(t+1)',分别与GRU抽取出的兴趣h(t)到辅助网络中即可,以充分的提升用户兴趣的表达。

defauxiliary_loss(self,h_states,click_seq,noclick_seq,mask,stag=None):mask=tf.cast(mask,tf.float32)click_input_=tf.concat([h_states,click_seq],-1)#正例noclick_input_=tf.concat([h_states,noclick_seq],-1)#负例#输到网络得到概率click_prop_=self.auxiliary_net(click_input_,stag=stag)[:,:,0]noclick_prop_=self.auxiliary_net(noclick_input_,stag=stag)[:,:,0]#计算lossclick_loss_=-tf.reshape(tf.log(click_prop_),[-1,tf.shape(click_seq)[1]])*masknoclick_loss_=-tf.reshape(tf.log(1.0-noclick_prop_),[-1,tf.shape(noclick_seq)[1]])*maskloss_=tf.reduce_mean(click_loss_+noclick_loss_)returnloss_#辅助网络的结构defauxiliary_net(self,in_,stag='auxiliary_net'):bn1=tf.layers.batch_normalization(inputs=in_,name='bn1'+stag,reuse=tf.AUTO_REUSE)dnn1=tf.layers.dense(bn1,100,activation=None,name='f1'+stag,reuse=tf.AUTO_REUSE)dnn1=tf.nn.sigmoid(dnn1)dnn2=tf.layers.dense(dnn1,50,activation=None,name='f2'+stag,reuse=tf.AUTO_REUSE)dnn2=tf.nn.sigmoid(dnn2)dnn3=tf.layers.dense(dnn2,2,activation=None,name='f3'+stag,reuse=tf.AUTO_REUSE)y_hat=tf.nn.softmax(dnn3)+0.00000001returny_hat

Interest Evolution Layer

兴趣进化层目标是刻画用户兴趣的进化过程,这里的Attention故事是:

interest drift:用户的兴趣具有偏向性。

interest individual:用户的兴趣之间具有独立性。

所以需要注意力机制去增强在兴趣变化中相关兴趣的影响,减弱不相关兴趣的影响,即给 GRU计算Attention权重,如上图红色的部分。注意力有三种变体可以选择:

GRU with attentional input (AIGRU):将注意力作为输入

Attention based GRU(AGRU):用注意力代替GRU的更新门

GRU with attentional update gate (AUGRU):对更新门加权

BST

论文:Behavior Sequence Transformer for E-commerce Recommendation in Alibaba

地址:/abs/1905.06874

把Attention升级成Transformer之后真的简单粗暴,Transformer[1]博主已经整理过了,不再赘述。BST把特征Embedding之后直接送进去就ok。主要看看输入的几个特征吧:

图最左边的other feature分为四个部分,用户特征、商品特征、上下文特征、交叉特征

item里面的蓝色是位置编码,红色是行为序列中的物品

位置编码和Transformer里面不一样的是,会把表示位置的时间戳直接映射成向量而不是sin函数,最后就是一般的损失函数:

BERT4Rec

论文:BERT4Rec: Sequential Recommendation with Bidirectional Encoder Representations from Transformer

地址:/abs/1904.06690

有了Transformer,升级成BERT[2]就很自然了。BERT首用于NLP,那么正好,用户的行为序列很像文本序列,于是BERT4Rec吧。模型结构如上图所示,输入是[v1,v2,...,vt]的序列,同时最后一个vt被mask掉,然后强制Transformer结合上下文预测vt,那么对于用户的行为序列,很自然就能得到最后的输出为推荐的结果。

有两个Trick需要注意:

输入不是所有的用户行为序列。因为不同用户的行为序列长度可能相差太大了,所以采用最近的N个行为序列做输入

在模型训练的时候并不是只mask最后一个,而是和BERT本身一样,随机mask,然后预测masked的部分

PRM

论文:Personalized Re-ranking for Recommendation

地址:/abs/1904.06813

这篇阿里ResSys'19文章的重点在于推荐后的重排序。贡献主要是利用Transformer+用户个性化重排:

用户和列表中物品的交互能更有倾向性

Transformer的self-attention可以有效捕捉特征间的交互

具体模型架如上图,得到initial list之后把每个item的特征x和用户偏好p拼起来,这两个特征都是预训练得到的(比如用任意一个CRT的模型结合用户的历史行为,物品等等的信息进行训练就行):

再把目前item在列表中的位置编码加进去:

再用Transformer来捕捉交互得到score就是重排的结果了。

注意力的其他玩法

推荐系统也算是很大的领域了,所以关于注意力的玩法也有很多,所以重点决定是为什么要用Attention。比如

要融合各种特征(attention或者co-attention,cross-attention)

特征是否分级(Hierarchical,level-attention)

特征间是否存在交互(interactive attention)

特征是否群组关系(Group-Attention)

是否存在动态的变化(dynamic attention,可能一般的用法会按时间线算多次以捕捉这种动态性)

然后或许仅仅算Attention已经不够了,那么魔改升级Attention变成High-order-Attention,Channel-wise-Attention,Spatial-Attention等等.....还有其他的注意力变体[3]博主以前也整理过了,就不再多说。

目前Attention的升级已经逐步暴力,从self-Attention到Transformer到BERT,效果也自然是变好了。

说个正事哈

由于微信平台算法改版,公号内容将不再以时间排序展示,如果大家想第一时间看到我们的推送,强烈建议星标我们和给我们多点点【在看】。星标具体步骤为:

(1)点击页面最上方深度学习自然语言处理”,进入公众号主页。

(2)点击右上角的小点点,在弹出页面点击“设为星标”,就可以啦。

感谢支持,比心。

投稿或交流学习,备注:昵称-学校(公司)-方向,进入DL&NLP交流群。

方向有很多:机器学习、深度学习,python,情感分析、意见挖掘、句法分析、机器翻译、人机对话、知识图谱、语音识别等。

记得备注呦

推荐两个专辑给大家:

专辑 |李宏毅人类语言处理笔记

专辑 | NLP论文解读

专辑 |情感分析

整理不易,还望给个在看!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。