论文:
论文地址:https://arxiv.org/pdf/2011.05625.pdf
论文题目:《CAN: Revisiting Feature Co-Action for Click-Through Rate Prediction 》
本论文是Din作者周国睿发表的一篇关于如何对特征进行交叉对论文,很少在阿里的论文中看见关于特征交叉的工作,更多的是对特征的agg操作,比如像在din中那样对用户的点击序列进行agg操作。can这篇论文从特征笛卡尔积的角度入手来考虑特征交叉,并且进行了改进,是我近期看到的少数几篇能够把作者内心思路写出来的论文。
一 、背景
特征交叉在推荐领域一直是很重要的工作,举个例子,假如有个用户特征age=25,gender=女,而候选item有个特征是categories类别=口红,那么这三个特征直接的组合就是一个很有用的信号,因为25岁的女孩子喜欢口红的概率是很大的。
回想在din中的工作,论文是对user behaviors进行weight sum pooling操作,这个过程在本论文的角度来看是属于 Aggregation方式的。除了din中这种对于历史的点击序列进行agg操作外,还有图神经网络中对子图进行聚合的方式,比如在GraphAge中对边上的节点进行聚合的操作。这两种方式都是在体现一种共现特性:co-action,也就是CAN这篇论文中反复提到的一个词,怎么来理解这个词呢?
在我看来它要说的意思其实很明显,就是特征同时进行表征会更容易刻画出用户的兴趣。不管是用户还是物品,都有很多特征,co-action可以解释为原始特征里面的sub-graph,这个sub-graph跟图神经网络中是类似的定义,你可以理解为多个原始特征的组合。
一般特征的交叉都是两维的,比如说FM,FM对所有对离散特征进行了两两组合,FM已经在很多工作中表现出很好的效果了,无论是在召回模型还是排序模型中都可以发挥一个baseline model的作用。两个embeding之间的交叉可以使用外积这样的操作,但是不管是FM还是其他特征交叉的计算方式都有这么一个问题,训练过程中,原始embedding的更新跟外积的更新有可能是矛盾的。
再来看论文中对于特征交叉的描述:
一个比较直观的解释:无论是特征A还是特征B,或者说他们的交叉特征对于判断候选item是不是用户感兴趣的都是至关重要的。
假如我们把特征A跟特征B的交叉当成一个新的特征,并且跟其他原始的特征一样都送到神经网络中的话,那么我就就把这种交叉的特征叫做笛卡尔积,如果我们进一步的对所有对特征都进行两两之间的笛卡尔积的话,这就得到了一个叫cartesian product model的baseline。
对于笛卡尔积,我是这么理解的,只要两个id特征同时出现在一次点击中,那么这两个特征就是有着co-action的情形,更多的是体现了一种id之间的共现性。举个例子:比如一个用户id跟某个口红品牌的id一直同时出现,那么我们对这两个id进行笛卡尔积后的建模是十分有效的,至于为什么,也很简单我们既然牺牲了很大的空间去直接对两个id的笛卡尔积进行建模学习,那么他们的共现性特征就很容易学习到了。
在文章开始的时候,作者就已经提到了,在一些小数据集中经过实验,笛卡尔积的模型比其他stoa的效果都要好,这也验证了在笛卡尔积上进行改进的模型效果也不会很差,事实上后面的实验也验证了这一点。
好了,我们回到笛卡尔积这个定义上面,学过数据库的都知道笛卡尔积的定义,也就是两个表的内容进行完全的匹配,特征中的笛卡尔积的定义也差不多,假如总共有N个特征,每个特征的维度是d,那么进行笛卡尔积后,我们需要N*N个新特征,也就是说我们的参数空间变成了N*N*d,这个当特征是id的时候,交叉出来的存储是十分惊人的,即使是阿里这么大的公司也不能hold住这么大的内存开销。
实际上,不是所有的特征之间都存在共现性,也就是我们在前面说的N*N的结果是完全可以削减的,这个削弱的意思是我们可以只用更小数量级的参数空间来模拟出笛卡尔积的情形。
我么在之前亚马逊基于超大规模的协同过滤算法一文中提到一个网络memory net,就是如果我们在原始的embedding基础上,我们用一些更fancy的操作来将两个embedding之间的co-action表示出来,是不是可以在参数减少的情况下进行笛卡尔积了。
ps:图来源于周国睿在知乎上的回答“核心的思想是,建模不同的co-action时,采纳T个slot中不同的参数,同时更新不同的参数,保持co-action建模一定的参数独立性。当然这种思路下可以去设计和尝试的具体模型方案非常多,整个交叉实验代价还蛮大的。”
“既然我们的核心目的是让co-action的建模过程中有相对比较稳定和独立的参数来维持对建模信息的学习记录,同时又想让不同的co-action间有一定的信息共享。不同于memory net的这个思路,我们组的小伙伴提出了一种更简单的方案:把co-action希望建模的两个ID,一端信息作为输入,另一端信息作为MLP的参数,用MLP的输出来表达co-action信息。
----来源于周国睿在知乎上对于CAN一文的回答。
链接:https://zhuanlan.zhihu.com/p/287898562
带着这两句话我们直接来看模型部分吧。
二 、CAN的模型结构
先总体的看一下模型的输出跟损失函数,因为我们的主要重点在玉Co-Action这个地方。
模型的输出:
损失函数:
2.1 Co-Action
首先明确几个定义:
:用户的embedding表示,维度为D
:item的embedding表示,维度为T
T是>D的,至于为什么,后面讲到MLP的参数定义的时候会讲到。
首先当我们需要进行user-item之间的co-action的时候,我们看到Co-Action模型结构的输入部分:,而这个MLP的参数正是由于中reshape出来的,所以T是>D的:
为什么用item的向量当作MLP的参数呢?
这是个值得令人思考的问题,前面我们已经说到了,在user跟item进行笛卡尔积的时候,并不是所有的user跟item都有机会进行交叉,而且交叉的结果需要保持一些共有的部分,怎么理解这个共有的特征呢,我们输入后,需要跟不同的item id进行交叉,在经过多层MLP后,其输出co-action有一定信息共享,在参数更新时也会不同,比如MLP的激活函数如果是relu,甚至是稀疏会更新一部分,就做到了我们之前说的通过部分保留参数更新的独立性,而实现co-action的稳定性。
实际上论文中的激活函数采用的tanh,具体是什么原因呢?
就是试过了之后发现tanh的效果好呗。
最后我们定义co-action为:
同样的,我们要用同一个结构对用户的历史点击中的item跟候选item进行co-action,这里作者提到了因为在广告系统中候选的item只是所有item中的一部分,而且相比于用户的历史点击的item数量也是小的,所以用候选item的向量来初始化MLP。
我们来分析下这个co-action的参数数量:N*T,这个没什么好解释的,因为我们只需要N个维度为T的embedding就够了。
2.2 Multi-order Enhancement
直接看co-action的图,我们可以看到输入部分是三个原始向量的多项式:
这么做主要是为了让模型学到更多的非线性。
2.3 Multi-level Independence
first level: 参数独立,CAN模型让表示学习和co-action独立了,训练的时候不会有conflict
second level:combinations independence组合独立性,特征协作随着特征组合数量的增加而线性增长。
third level:指的是我们的co-action输入使用了多项式
三、实验结果
论文的代码还没开源,我还是很想看一下co-action中是怎么来对MLP进行参数更新的,期待。
网友评论