今天给大家介绍一篇有关深度CTR模型增量训练的文章,来自华为诺亚方舟实验室。
深度CTR模型需要大量的数据进行训练,同时需要不断的更新以适应最新的数据分布。如果模型没有及时更新,则有可能带来线上效果的衰减,如下图,当模型5天没有更新时,线上AUC会有0.66%的下降,这会带来巨大的收入损失,同时对用户体验也会造成一定影响。
为了保证线上模型的有效性,通常需要对模型进行天级别/小时级别甚至是分钟级别的更新。而本文将重点放在天级别更新上。
模型的天级别更新比较常用的方式是使用规定时间窗口的数据对模型进行重新训练,如下图,模型0使用第1天到第10天的数据进行训练,模型1使用第2天到第11天的数据进行训练,依次类推:
上述重新训练模型的做法,其缺点是耗时比较高,更新可能不及时,因此可以考虑增量训练的方式,如下图,模型0同样使用第1天到第10天的数据,模型1在模型0的基础上,加入第11天的数据进行更新,依次类推:
本文重点介绍华为如何对深度CTR模型进行增量训练,我们在下一节中一起学习一下。
华为增量训练框架如下图所示:
如上图,该框架主要包含三个模块:数据模块、特征模块、模型模块,接下来对这三个模块依次进行介绍。
数据模块主要对数据进行存储和混合。如上图,在第t天更新模型时,从t-1天的数据池中选择部分数据,同时混合第t天新的数据,作为第t天模型更新所使用的数据。论文中提到,应该选择t-1天的数据池中哪部分的数据,这块仍然处于研究中,期待后续的研究进展。
特征模块主要对特征进行处理,这块重点讲解对于离散型特征的增量更新。
对于离散变量来说,许多取值出现的次数非常少,通常会设定一个出现次数的阈值,当该取值出现的次数高于阈值时,会计作一个单独的类别,而出现次数低于阈值的所有取值,会被统一当作others类别处理。当得到所有的类别之后,会将每一个类别映射到一个特定的id,最后转换成对应的embedding。
类别映射到id的方法有许多种,文中提到了自增映射(auto-increment)和哈希映射( hash-coding)。论文使用的是自增映射,这里也简单介绍下哈希映射(论文没有提及,个人经验,欢迎各位纠错)。对哈希映射来说,首先要确定一个总的哈希空间大小,如2^10,然后通过某种哈希方式(如murmur哈希),将对应的类别转换为对应的hash值,作为该类别的id值。对哈希映射来说,通常设定的hash空间的会比实际的类别数量大很多,以尽可能避免冲突的出现。使用Hash这种方式的好处个人认为主要是新出现的特征类别,不需要改变embedding向量的个数,embedding向量的个数和hash空间的大小相同;但hash空间的大小往往比实际的类别数量,会导致导出的模型比较大,同时需要采用合适的hash算法,否则会导致冲突的出现,降低模型的准确度。
而本文使用的自增映射方式,当新类别出现或者Others类别中某种取值出现的次数超过阈值时,则需要进行特殊处理。如上图所示,t-1天的模型,只有Feat A和Feat B出现次数超过了阈值,因此只需要将Feat A和Feat B转换为对应的id,分别为1和2(上图有点不太严谨了,应该还有Others类别,不过不影响理解)。此时训练的模型,embedding的大小为2* K(k为每个embedding向量的长度)。当收集了第t天的数据后,Feat C出现次数也超过了阈值,因此采用自增的方式,将Feat C转换为对应的自增id,即3。此时第t天的模型不能继续使用第t-1天的模型进行继续训练,而必须重新进行embedding的初始化,大小为3 * K,其中前两行使用t-1天模型训练后的embedding值进行初始化,第三行则进行随机初始化。
下面是对特征模块处理过程的总结,其中Eexist表示t-1天模型中存在的id对应的embedding,Enew表示第t天模型新增的embedding:
对于模型的更新,这里介绍两种方式,Fine-tune和Knowledge distillation。
对于Fine-tune方式,除Embedding从t-1天模型进行warm-start外,其余的网络参数也从t-1天模型进行拷贝。然后使用数据模块混合后的训练数据进行参数更新。这里还使用了一些小的trick来实现更好的效果,比如对于Eexist部分的embedding,使用较小的学习率,而对于Enew部分的embedding,则使用一个相对更大的学习率。模型使用交叉熵损失进行更新。
为了增强模型从历史数据中学到的知识,避免出现不同天的模型预测差距过大的情况,在使用Fine-tune方式所有特性的基础上,还增加了teather网络,来辅助模型的训练。
此时模型的损失变为:
首先提一下,这个地方我感觉符号上还是有些值得商榷的地方,即student net的预测值,在和真实值(hard label)计算交叉熵损失,以及和teacher net的预测值(soft label,Ysoft)计算交叉熵损失时,二者的计算是存在一定的差别的(区别在于是否把log logits即Z除以temperature τ),因此符号上应该也做区别处理更加合适。
上面损失的三项分别是student net的预测值和真实值计算的交叉熵损失,student net的soft预测值和teacher net的soft预测值计算的交叉熵损失,以及正则项。
简单解释下损失中temperature τ的含义,知识蒸馏这种方式,我们希望得到的结果是student net和teacher net的输出尽可能接近,假设不对logits除以temperature,那么teacher net输出的类别概率可能会比较悬殊,比如0.99和0.01,那么0.01这一类对于损失的贡献是非常小的,解决方式就是在计算损失函数时放大其他类的概率值所对应的损失值。假设teacher net的log logits = 3,那么softmax之后两类的概率分别为0.95和0.05,再假设temperature=10,那么softmax之后两类的概率分别为0.57和0.43,这样两种类别对于损失的贡献更为接近了。这样更加有助于student net向teacher net的方向优化。
关于teacher net的选择,文中给出了两种方式:
KD-batch:使用一定时间窗口内全量数据训练的模型
KD-self:t-1天的模型
后续会给出这两种方式的实验对比结果,好了,接下来是对模型模块的总结:
好了,最后来看一下论文的实验结果:
首先,使用论文提到的增量训练的方式,表现能否超过本文一开始提到的使用固定长度的时间窗口重新训练模型的方式呢?结果如下表所示,其中Batch-0表示使用最新的时间窗口训练的模型,Batch-1表示使用延迟一天的时间窗口训练的模型,依次类推,可以看到增量训练方式得到了一定程度的AUC的提升,以及模型更新耗时的大幅缩短。
同时,从上表可以看到,在模型模块使用或Fine-tune或者KD的方式,在Criteo数据集上表现接近,但在华为App上的数据来看,KD的方式表现更好。
最后,论文还验证了特征模块的作用,如果不对新加入的特征列别进行处理的话,会带来效果的衰减,随着天数的增加,这种衰减会越来越明显。
好了,本文就介绍到这里,又是一篇可以学到很多工业经验的文章,值得仔细品读!
推荐系统遇上深度学习(九十二)-[腾讯]RecSys2020最佳长论文-多任务学习模型PLE
2020-10-02
推荐系统遇上深度学习(九十三)-[谷歌]提升谷歌网盘推荐质量的工业经验
2020-10-03