阿里巴巴CAN:Embedding前置的特征交互新思路

内容源自:
想为特征交互走一条新的路
屠龙少年与龙:漫谈深度学习驱动的广告推荐技术发展周期

声明:非博主原创内容,仅作为学习记录。

本篇文章介绍了阿里妈妈定向广告团队的最新作品:Co-Action Net(以下简称CAN)。CAN提出了一种全新的特征交互思路,将待交互的特征(用户侧和商品侧特征)分别作为DNN的输入和权重,用DNN的输出作为特征交互的结果。CAN在提升了特征交互的表达能力同时,降低了传统的笛卡尔积交叉所需要的计算复杂度。

embedding看法----大佬发言

我一直对embedding结构耿耿于怀:它太粗暴,lookup table的方式使得集中了CTR模型99%以上参数量的embedding matrix学习很低效。从很早之前我就一直试着设计不一样的结构来更好地完成sparse id到dense representation这一过程的参数化,折腾了不少方案,但至今都没找到漂亮的解法。这让我对embedding充满了怨念:id不得不经过低效learning的embedding翻译后续的网络部件才能处理,而embedding又不太有什么意义,纯粹是data-driven的学习过程收敛出来的结果,且任意两次随机初始化的训练,embedding之间也很难有什么内在的泛化性联系。相反地,原始的sparse id本身有着确定性意义,或者说输入端蕴含的信息是确定的,只不过embedding这个翻译的codebook有随机性。为此,在推进输入端建模时我非常强烈地坚持了在embedding之前“搞事情”

CAN的初衷-为何笛卡尔积有效?

1、实验现象

CTR预估建模问题里,把待预估的商品信息(如item id)和用户历史行为序列信息(如item id sequence)做笛卡尔积,形成一个新的id sequence,对其直接做embedding后pooling效果很好,会在DIN和DIEN的基础上再有比较明显的提升。

2、为何笛卡尔有效?

当时细想一下,笛卡尔积有效并不神奇,同时一定能找到参数量更少的模型方案来替代笛卡尔积这种hard的id组合方式。比如用户行为序列中有一个商品ID为A,待预估商品为B,笛卡尔积形成新的ID A&B,A&B每次在一条样本里出现,训练时都会更新独立属于自己的embedding。而这个A&B的embedding,我们认为其学习的是A,B两个ID在一条样本共现后对Label的co-action信息。

这个co-action信息为什么重要其实很好理解,比如CTR预估问题,要解决的本来就是每条样本最后预测是否点击,其实解的问题就是所有输入信息X条件下点击的概率 P ( Y / X ) P(Y/X) P(Y/X)。建模co-action信息就是单独建模P(Y|A,B) 。

具体的,如果A和B分别是待预估的商品ID,和用户行为序列里的商品ID。如果我们对行为序列做SUM/AVG pooling就等于忽视了ID间的co-action,对序列做DIN/DIEN类似的aggregation,在co-action的视角下可以看做是一个scalar的co-action,没有方向,且只能对原始行为序列ID的embedding做一个纯量的修正

那么每个序列的ID都和预估商品ID做一个笛卡尔积呢,把原始的序列变成一个笛卡尔积ID序列,再给每个ID都学习一个embedding。这个时候co-action就是用向量来建模,且这个新的embedding和原始序列的embedding完全独立,自由度更大,模型capacity更大。如果原始ID的co-action信息建模本身有用,那么笛卡尔积就是建模co-action最直接的方式。

笛卡尔积+端到端学习的embedding其实很像一个大的memory network,只不过写入和读出的索引相同,都是笛卡尔积化后的ID。这样的模式下这些代表co-action的笛卡尔积ID的embedding在训练时,具备样本穿越性。训练时,任意一个笛卡尔积ID A&B的embedding都是独立学习的,同时强保证了,在下一条A&B出现的样本里,这个embedding能把当前学到的co-action信息无损的带入,保证了参数更新的独立性

而简单的特征cross方法,比如把 A 1 A_1 A1 的embedding和 B 1 B_1 B1 的embedding做外积,这个时候 A 1 {A_1} A1 & \& & B 1 {B_1} B1 的co-action为 E m b A 1 ∗ E m b B 1 Emb_{A_1}*Emb_{B_1} EmbA1EmbB1 ,它在训练时也会被 B 1 B_1 B1 embedding本身的学习 E m b A 1 ∗ E m b B 1 Emb_{A_1}*Emb_{B_1} EmbA1EmbB1等更新,很难保证学习到的co-action信息在下一次出现时,还保留上一次学习的信息,也就是说无法保证参数更新的独立性

综上所述,核心观点为:核心点是embedding之前交叉本质上是增加了独立的输入参数自由度,而embedding之后任意两个id已经被对应的embedding向量表征了,再做交叉只是对MLP的一种先验变形。我们设计参数化的方案,就是希望保留输入端新增自由度的同时,尽量缩减这个新自由度引入的参数膨胀问题。项目组同学们的创造力由此被激发、设计出了CAN模型的结构。

3、笛卡尔不是终局

笛卡尔积其实是非常常用也比较好理解其实现方式的一个方案。不过对用户行为序列item seq和待预估item做笛卡尔积组合其实有蛮多弊端,即使已经看到了离线的部分提升,我对着急把这样的方案推进全面生产化不是很感兴趣。

  1. 这种序列笛卡尔积在训练端和在线服务端其实成本蛮大的。训练可能比较好解决,但是在线服务会有比较明显的瓶颈,因为每一次预估需要生成的ID,和查询embedding的ID会急剧膨胀,而这些操作是需要CPU计算的,这部分的可优化空间也比较小。算下来成本比一个计算复杂型模型要高不少,至少对于我们,一个熟知如何优化计算复杂型的团队是这样。
  2. 笛卡尔积意味着强记忆性,是比较hard的方案,对于一些样本里未出现的ID组合,是直接无法学习的。同时稀疏的组合和稀疏的ID,学习效果也很差,大部分情况下只能选择过滤(是不是和FM初衷似曾相识,那么是否可以参考FM方案解决呢?马上揭晓)。
  3. 笛卡尔积的参数膨胀本身就会带来模型无论从性能还是维护迭代上鲁棒性的进一步降低。

下面我们来推演一下在笛卡尔积有效的情况下,我们有没有机会找到参数量更少的模型方案来替代笛卡尔积这种hard的id组合方式。
1、第一条线索,参数空间视角:前文提到二维笛卡尔积的方式,如果我们局限以对Item ID做co-action建模分析,可以看做是一个全参数空间为 N ∗ N ∗ D N * N * D NND 的方法, N N N为item ID的数量, D D D是embedding的维度。这个参数空间是非常大的, N N N 在淘宝是十亿以上的规模。当然了实际上训练时不需要那么大的空间,因为并不是所有ID的组合都会在样本中出现,但是笛卡尔积这个方法的假设参数空间依旧是 N ∗ N ∗ D N * N * D NND。意味着在它有效的状态下,也是存在大量的参数空间冗余的,再考虑到稀疏出现的笛卡尔积(是不是感觉FM要呼之欲出了),如出现次数个位数的笛卡尔积embedding无法有效学习。笛卡尔积方法,大部分的假设参数空间都是无效的。

2、第二条线索,学习难度视角:前文提到,笛卡尔积的方式保障了任意一组co-action组合的学习是独立且强记忆能实现样本穿越的。而如直接外积的方式很难建模co-action,因为没有参数来稳定维持对co-action的建模学习信息。虽然笛卡尔积的方式是有效且看上去对co-action建模最直接的,但是难以忽视的一点是比如在电商场景,商品与商品之间是有联系的,是有相似性的,任意两个商品之间的co-action信息也应该有overlap的部分,不应该是完全独立的。直接外积的方式呢,共享的维度过大,单侧ID的信息完全共享,参数空间为 N ∗ D N * D ND 。如果我们能有效利用不同co-action之间有信息可共享,我们就有机会找到把参数空间降低 N ∗ T ∗ D N * T * D NTD 的方法(敲黑板:这个地方降低的是共享参数的空间,原来参数是完全共享的,参数空间为 N ∗ D N * D ND,当空间变大为 N ∗ T ∗ D N * T * D NTD后,增大了各自的独享空间,自然就降低了共享空间,降低从此而来,理解不对欢迎大家拍砖),其中 N < < D N << D N<<D

4、千呼万唤始出来:CAN:Co-Action Net

最开始我们从memory net的视角想了一种方案,把item id的参数从 D D D 扩展到 D ∗ T D * T DT ,即把embedding变成一个有 T T T个slot的矩阵,这种方案下任意一个ID都有 T T T个slot,每个slot存放维度为 D D D的vector。这时候可以借如attention的思路来建模co-action并保持不同组合co-action学习的部分独立性。比如在建模co-action时,让不同的slot对另一个ID的所有slot做attention aggregation,并和aggregation后的结果做外积(element wise乘法):在这里插入图片描述
核心的思想是,建模不同的co-action时,采纳T个slot中不同的参数,同时更新不同的参数,保持co-action建模一定的参数独立性。当然这种思路下可以去设计和尝试的具体模型方案非常多,整个交叉实验代价还蛮大的。

既然我们的核心目的是让co-action的建模过程中有相对比较稳定和独立的参数来维持对建模信息的学习记录,同时又想让不同的co-action间有一定的信息共享。不同于memory net的这个思路,我们组的小伙伴提出了一种更简单的方案:把co-action希望建模的两个ID,一端信息作为输入,另一端信息作为MLP的参数,用MLP的输出来表达co-action信息。

整体模型结构如下图所示,CAN的部分在左侧:

这种方式下,由于MLP的有多层,再加上每一层插入非线性函数,如此, A 1 A_1 A1 和不同的ID做co-action,如 B 1 , B 2 B_1,B_2 B1,B2 ,其输出co-action有一定信息共享(个人理解:把NN输出可以理解为简单的门控,虽然没有SENet那样精确,或者是不是换成基于senet的门控网络是不是更好些呢),在参数更新时也会不同,比如MLP的激活函数如果是relu,甚至是稀疏会更新一部分,就做到了我们之前说的通过部分保留参数更新的独立性(通过激活函数实现),而实现co-action的稳定性。当然了具体的我们的实际方法里这部分激活函数是Tanh,这其实是个实验结论。做实验的小兄弟认为:因为我们在第一层输入时,手动增加了输入信息的多阶计算, e m b A 1 1 + e m b A 1 2 + e m b A 1 3 emb_{A_1}^1 +emb_{A_1}^2+emb_{A_1}^3 embA11+embA12+embA13,Tanh会保护训练时输出更平滑。不过我没有完全接受这个观点,relu或者dice都会更贴近我们最初设计的思路。

最后这个方法我们无论是在我们的业务数据集,还是公开数据集都做了比较完备的实验。CAN确实性能优异,效果比笛卡尔积更好,同时模型参数量并不会急剧膨胀,因为这种方式需要查询参数的ID数不变,对在线服务CPU和RT也比较友好。至于增加的GPU计算部分嘛,一个是GPU的算力增长还是比较符合摩尔定律的,增加GPU负担比较便宜,另一个这部分的计算优化本来就是定向广告团队的拿手好戏: )。毕竟到现在都还有人没办法相信DIEN的在线服务,可能在线优化这块真的很难?在工程团队的给力配合下,我们很快就将这样的方案全面生产化,给业务带来了明显增长。

这个工作是我们团队在原始输入信息交互建模上的第一次尝试,如果真实业务情况笛卡尔积用着比较舒服,也不影响RT和迭代,其实笛卡尔积就是蛮好的方式。CAN是我们希望推进找到模型化的方案替代笛卡尔积建模co-action,背后希望的是找到一条新的路,让交互信息建模还有进一步的迭代空间。毕竟如果终结于笛卡尔积的方式,我很担心我们走上step1:手动加特征 step2:无脑增加多阶特征 step3:讲AutoML做特征搜索的故事 step4:跳槽开始step1的循环。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值