今天的论文参考了2019年KDD的paper《Practice on Long Sequential User Behavior Modeling for Click-Through Rate Prediction》和2020年的paper《Search-based User Interest Modeling with Lifelong Sequential Behavior Data for Click-Through Rate Prediction》,这也是阿里妈妈盖坤组最新的在定向广告方向的研究实践成果,即在进行CTR预估的时候考虑了用户更长时间的行为序列信息。
首先从整体来讲,我觉得这篇paper是有一定划时代的意义的,和之前看到的只是从改进模型结构本身来提升CTR不同的是,这篇paper体现了下一代推荐系统的发展趋势:算法和架构的 co-design,这也是我在去年9月份的AI大会上听阿里妈妈资深算法专家朱小强提到的。
众所周知,随着深度学习的到来,给各个行业都或多或少的带来了很多增益,其中属广告推荐等领域获益最大,因为这些领域积累了大量的用户行为数据。于是在一开始的时候,所有算法工程师要做的事情就是不断提升模型的复杂度,从这些海量而复杂的用户行为序列中学习规律,其实包括学术界也是一样,结构复杂、眼花缭乱的复杂模型架构层出不穷的出现在各种顶会的paper上。确实在一开始的时候,越复杂越精巧的模型总能不断刷新各个场景模型的baseline,这也得益于GPU等硬件设备的优化、普及和推广以及越来越模块化、易用的深度学习框架。我们称这一时期为计算力的红利,从DNN => DIN => DIEN模型越来越复杂,这一时期一直到2018年年底,工业界的很多人会越来越感到计算力红利差不多到了一个瓶颈,因为由于硬件本身技术的限制,模型的复杂度被限制在了一个瓶颈下,再提升模型的复杂度,可能就没法到达工业界要求的响应时延。再往后看,在硬件技术无法取得突破性进步之前(硬件技术的本质突破是很难在短时间内完成的),恐怕单纯的提高模型复杂度已经走不通了。那么在下一个硬件技术期突破来临之前,当下的最可能能够进一步提升系统效果的思路就是:算法和架构的co-design。
而今天讲的paper就是模型和架构co-design的一个比较初步但是有效的实现,即2019年的paper《Practice on Long Sequential User Behavior Modeling for Click-Through Rate Prediction》。
话不多说,先上架构图:
左边的是阿里原来的定性广告预测架构图,右边是改进后的架构图。图中的traffic request是粗排那边得到的广告集合很和用户当前请求组成的request,传统的方法是根据当前的用户ID去数据库里提取用户在一段时间内的行为序列(一般是2周),然后对用户在2周内的行为数据进行建模分析,这种架构最大的缺点就是,因为有在线响应时延的要求,用户行为序列的处理长度是有限的,对于有些特别活跃的用户,可能2周内的行为序列长度有1000以上,对于这种只能强制截取了。但是作者通过绘制如下图:
从图中非常容易的可以看出,时间段范围越长,用户的平均行为序列越长;模型使用越多的用户行为序列,那么就能达到更好的AUC值。所以如果能在保证在线时延的情况下,尽力增加模型可以建模使用的行为序列长度,对最终的CTR一定是大有好处的。
于是作者提出了名为:UIC(user interest center) Server的一种结构。其实这个UIC里面就存储了每一个用户的点击行为序列信息,不过这个信息是经过了编码压缩之后的,不是原始的、直接的点击序列样式。这样,在进行traffic request响应的时候,系统直接去UIC去取之前算好的用户行为序列表征,即解耦用户兴趣建模和CTR预估。而从图中也可以非常清楚的看出,这个UIC是当每次用户有行为的时候进行更新,而不是traffic request的时候一起算。这里我要说明一下,这篇paper的应用场景是手机淘宝打开的时候的定向广告推荐,这在paper里叫做traffic request,而用户打开手机淘宝后,会对一些商品有点击、购买等行为,这个叫做realtime user behavior。不难看出这个UIC的结构是非常重要的,也是本文最大的创新点。
从整个系统的运行角度来说,UIC的在线步骤和预测模块的在线部分是独立的,论文里称UIC为“latency free for realtime”,即UIC是伴随用户每次点击商品就会及时更新用户状态,而预测模块在用户发起traffic request的时候,直接去UIC里取计算好的用户行为状态,整个UIC的结构如下所示:
为了从用户超长的点击序列(通常在1000以上)中全面、准确地压缩抽取出用户的多样化的兴趣,paper作者基于memory network的思想提出了一种称之为“multi-channel memory network”的架构,示意图如下所示:
因为每个用户的点击序列可以反映出其多样化的兴趣爱好,也就是说一个序列在一个人多种的兴趣爱好之下下产生的,“multi-channel memory network”可以根据用户的点击序列,来自动的对其中每一个channel network的参数进行跟新,从而达到了对用户行为序列信息进行存储于压缩,原来长度超过1000的行为信息,被压缩到了固定长度的多channel的memory network,参数表示为{Mt(i)∣i=1m}\{M_t(i)|_{i=1}^m\}{Mt(i)∣i=1m},其中m就代表了channel的数量,需要注意的是每一个用户会对应于一个独有的memory network,不同用户之间的memory network是不共享的。下面讲解一下memory network的状态更新过程:
1 memory read
当接收到用户t时刻的行为,controller就产生一个read key ktk_tkt(在具体实现中这个controller是由GRU来做的,这个read key包括后面的write key,add vector 和 erase vector是由当前t时刻用户浏览的商品和上一时刻的状态一起作为GRU的输入而产生的),然后这个ktk_tkt就会对memory network中的不同的channel向量进行相似度的计算得到wtrw_t^rwtr:
wtr(t)=exp(K(kt,Mt(i)))∑jmexp(K(kt,Mt(j)))w_t^r(t)=\frac{exp(K(k_t,M_t(i)))}{\sum_{j}^mexp(K(k_t,M_t(j)))}wtr(t)=∑jmexp(K(kt,Mt(j)))exp(K(kt,Mt(i)))
其中分子分母中的KKK运算就是向量计算cos夹角的操作。得到了read key针对每一个memory channel的相似度权重,然后进行加权求和操作:
rt=∑imwrt(i)Mt(i)r_t=\sum_{i}^mw_r^t(i)M_t(i)rt=∑imwrt(i)Mt(i)
2 memory write
和memory read部分一样,也会产生一个write key,继续和memory channel进行相似度计算,最后得到wtww_t^wwtw,在这一步骤中controller会继续产生一个erase vector ete_tet和add vector ata_tat,接下来就是MtM_tMt的状态更新公式了:
Mt=(1−wtw⨂et)⨀Mt−1+wtw⨂atM_t=(1-w_t^w\bigotimes e_t)\bigodot M_{t-1}+w_t^w\bigotimes a_tMt=(1−wtw⨂et)⨀Mt−1+wtw⨂at
其中⨂\bigotimes⨂代表了outer product操作,⨀\bigodot⨀代表了dot product操作。
当然作者发现了这些不同memory channel之间的更新并不是公平的,特别当用户点击序列里面大量都是热门商品的时候,这样就会使某一个或两个memory channel更新比较频繁,为了解决这个问题,作者提出了一种正则策略,即对最终wtww_t^wwtw再乘以一个参数矩阵gtg_tgt,使其累计权重值能够更加的平均一些:
Pt=softmax(Wggt)P_t=softmax(W_gg_t)Pt=softmax(Wggt)
wtnew=wtwptw_t^{new}=w_t^wp_twtnew=wtwpt
wnew=∑t=1Twtneww^{new}=\sum_{t=1}^Tw_t^{new}wnew=∑t=1Twtnew //代表了截止到T时刻为止,累计www^www权重之和
Lreg=λ∑i=1m(wnew(i)−1m∑i=1mwnew(i))2L_{reg}=\lambda\sum_{i=1}^m(w^{new}(i)-\frac{1}{m}\sum_{i=1}^mw^{new}(i))^2Lreg=λ∑i=1m(wnew(i)−m1∑i=1mwnew(i))2 //m代表了memory channel的数量
3 memory induction unit
由于memory network存储的是原始的用户行为记录信息,但是对于用户行为的演化确没有很好的建模,为了对用户行为演化信息进行很好的建模。因此这里就引入了以GRU为具体进行实现的memory induction unit,结构图如下所示:
在每次经过了memory write操作更新了memory network的参数之后,即从Mt−1=>MtM_{t-1}=>M_tMt−1=>Mt之后,会选取topk(wtr)∣i=1ktop_k(w_t^r)|_{i=1}^ktopk(wtr)∣i=1k 对应的memory slot信息输入到GRU中,公式如下:
St(i)=GRU(St−1(i),Mt(i),et)S_t(i)=GRU(S_{t-1}(i),M_t(i),e_t)St(i)=GRU(St−1(i),Mt(i),et)
最后作者通过实验证明了这种实验结构是有效的,尤其是在对超长用户行为序列建模方面相比于之前只使用最近2周的用户行为信息,能够更加精准的预测用户行为。
第二篇分享的工作参考了2020年的paper《Search-based User Interest Modeling with Lifelong Sequential Behavior Data for Click-Through Rate Prediction》,这个工作也可以看做是2019年工作的进一步延伸。
因为memory network 的记忆是有限的,因此针对超长用户行为建模方面还是有一些提升空间的。针对这种情况作者提出了一种名为Search-based Interest model,即把整个CTR预测过程分成了2个stage:1 从超长的用户行为序列中检索出和当前预测item最相关的k个item候选列表;2 使用后续的DIN/DIEN等模型对筛选出的k个item行为列表进行建模与预测。
这里针对第一步采用不同的检索策略,可以分为hard-search和soft-search两种方式:
1 hard-search Sign(Ci=Ca)Sign(C_i=C_a)Sign(Ci=Ca) i代表了当前输入item,a代表了target item。这里hard的方式就是利用了电商场景商品的天然特性,即每一个商品会有一个“类别”标签,因此只要是和当前target item属于同一个类别的商品都会被筛选出来,这种看似粗暴的方式其实也是最终阿里妈妈在实际中的使用方式,具体实做中会构建user=>category=>itemuser=>category=>itemuser=>category=>item这样的两级索引结构,直接快速的检索出和当前target item相关的item序列集合;
2 soft-search (Wbei)⨀(Waea)T(W_be_i)\bigodot (W_ae_a)^T(Wbei)⨀(Waea)T 其中Wb,WaW_b,W_aWb,Wa是参数矩阵,⨀\bigodot⨀代表了内积操作,即通过内积的方式找出最相似的k个item。同时需要注意到的是,long-term和short-term用户的行为分布是不一致的,因此在soft-search部分加入了auxiliary loss辅助item embedding的生成,而soft-search对应部分的网络架构也是比较简单的,细节直接看下图就可以了,这里就不再赘述了。
整体2阶段的模型架构图如下所示:
在通过first stage得到了压缩的用户行为序列之后,这些序列就会被输入到second stage对应的网络结构中去。从上图可以看到这部分使用了Exact Search Unit和DIEN对用户行为进行建模,DIEN在前面的博客已经讲过,这里就不再赘述了。这个Exact Search Unit其实是参考了multi-head attention的思想,具体细节如下:
针对用户每一个点击的时间间隔,引入了类似于位置向量的时间间隔向量序列:
Et=[e1t;e2t......;eKt]E_t=[e_1^t;e_2^t......;e_K^t]Et=[e1t;e2t......;eKt]
接下来是item的embedding序列:
E∗=[e1∗;e2∗......;eK∗]E^*=[e_1^*;e_2^*......;e_K^*]E∗=[e1∗;e2∗......;eK∗]
两者拼接得到zj=concat(ej∗,ejt)z_j=concat(e_j^*,e_j^t)zj=concat(ej∗,ejt)作为用户行为的最终表征。接下来使用类似的multi-head网络结构:
attscorei=Sotfmax(wbizb⨀waiea)att_{score}^i=Sotfmax(w_{bi}z_b\bigodot w_{ai}e_a)attscorei=Sotfmax(wbizb⨀waiea),其中eae_aea代表了target item的embedding表示。
headi=attscoreizbhead_i=att_{score}^iz_bheadi=attscoreizb
其中iii代表了第iii个head的参数,假设head的数量为q个,那么最终得到最终的形式为final=concat(head1,head2,.....headq)final=concat(head_1,head_2,.....head_q)final=concat(head1,head2,.....headq),最终将final向量输入到MLP网络中去得到最终的CTR预估结果。
最终模型的loss由first stage的GSU损失和second stage的ESU 损失组成,即Loss=αLossGSU+βLossESULoss=\alpha Loss_{GSU}+\beta Loss_{ESU}Loss=αLossGSU+βLossESU。