|
系列文章链接
- 如何在工业界优化点击率预估:(一)开篇
- 如何在工业界优化点击率预估:(二)样本
- 如何在工业界优化点击率预估:(三)特征
- 如何在工业界优化点击率预估:(四)兴趣|序列建模
- 如何在工业界优化点击率预估:(五)特征交叉建模
- 如何在工业界优化点击率预估:(六)多场景建模
- 如何在工业界优化点击率预估:(七)图建模和预训练
- 如何在工业界优化点击率预估:(八)Debias&Loss&校准
- 如何在工业界优化点击率预估:(九)集成学习&模型压缩
一、前言
本文介绍一柄矛和一把盾,集成学习我相信大家都不陌生,尤其是在打Kaggle或者天池比赛里,是最后提升的核心技巧,虽然我们前面讲了那么多优化点击率预估的方案,但是在有监督学习算法中,想要学习出一个稳定的且在各个方面表现都很好的模型是较难的,因此可以用集成学习将多个模型组合到一起得到一个更好更全面的模型。当然既然要组合多个模型,那么在离线的资源消耗都要对应增长,这也是为什么并没有在工业界里普及的原因,我们团队也对此进行了尝试,期待在最小资源代价下引入模型的Diversity再获取组合后的收益,但并不是特别理想,但我们也在一些其他的技术迭代中逐渐看到集成学习落地的影子,除了一方面从源头出发设计最小计算代价的集成学习算法,还有一种方案即得到成品模型后进行模型压缩,当然从算力和模型复杂度平衡的角度,前面的方法都可以形成模型发展,模型压缩的交替循环。因此本文的核心内容如下。
二、集成学习
眼尖的同学可能发现了,集成学习明明还有个Boosting,咋给漏了,由于集成学习本身就会导致在离线计算资源的成倍增加,如果训练时效也成倍增长就更不能接受了,因此在探索的时候就没有考虑Boosting这个方向。
1、bagging
训练多个模型Bagging后效果增长,这是我们很早就明确的经验,比如在相同结构下,完全随机初始化多个模型,各自训练收敛后在测试集平均预估值作为打分,即使复杂如CAN模型,也能取得如下效果。
虽然效果有提升,但是由于模型数量增多带来的模型存储计算资源消耗也对应增加,即使是两个模型Bagging对于我们在线系统也是没法承受的。我们在权衡各个部分的算力后,认为参数膨胀主要来自于Embedding,算力增长主要来自于DNN以前的算法OP,例如Attentin,GRU,Co-Action Unit等。因此我们设想Embedding和初始算法OP复用,后端DNN独立的形式,希望能学到差异化,甚至各种利用dropout,随机分配负样本等企图增加Diversity的操作均没有取得显著效果。
当然,我们也曾想过为不同的DNN设计独立的Embedding DIM,即Embedding大部分共享,少部分独立,但可预期的效果增益受损,以及其带来的迭代复杂度,让我们不再尝试。不过我们并没有放弃对集成学习的思考,我们可以看到在最后一个方案中还有一点希望,即是否能改成特征拆分输入的Stacking
2、Stacking
事实证明Stacking如果直接采用 去做输入收益有限,但我们在其他方向中探索出了另一种集成学习方案,这个方案更轻量级,效果更显著
这里的少量特征是我们选取的一些重要但被深层学习淹没以及不需要和其他特征交叉的特征,比如计划类型之类,且我们发现这些特征即使都在主结构输入,依旧有提升,说明把特征一股脑送进单通道的DNN结构未必能有效学习。这种方式继承了上一小节说的差异化输入的方式,但又更加轻量,因为只需要在末端一个很小的结构引入有信息先验的Stacking形式。
当然业界也有很多其他方案流传出来,比如类似Model soup的移动多个checkpoint的参数平均,但我觉得对于OL迭代的模型生产这一类方法可能使得打分实时准度存在问题,投入建设的性价比不是很高。
三、模型压缩
模型压缩一般分为精度压缩,结构压缩,特征剪枝。对于精度压缩更多是工程问题,即如何利用FP16,INT8在效果近乎无损的情况下节约存储和计算,这里面一般为了保障效果还会根据算子的敏感性实现混合精度。对于结构压缩主要分为知识蒸馏和结构剪枝。虽然从我的迭代经验来看,因为知识蒸馏一般需要同时维护Teacher和Student的完整结构,导致迭代复杂度上升,训练任务的显存吃紧,所以我更倾向结构剪枝这种后验解耦方案。但是结构剪枝一般不破坏算子逻辑,只缩小结构矩阵的计算维度,针对上文的集成学习Stacking方案,无法还原梯形inference结构,因此想要压缩结构还得采用Distill,刚好我们团队自研的结构复用的Distill方案Rocket Traing,可以在最小训练代价下和上述结构契合压缩。因此下文主要介绍Rocket Training
1、结构Distill:Rocket Training
Rocket Training是一类结构复用的Distill方法,他的核心技术点如下
再看一个和集成学习Stacking方案的合并结构图,大家应该就能理解他具体怎么应用了。
3、结构剪枝
结构剪枝主要可分为基于度量标准、基于重建误差、基于稀疏训练等几种方法。其中,基于权重度量、基于重建误差等方法,在剪枝和retrain from scratch时需要继承原模型参数。换言之,剪枝过程与模型训练过程耦合,这无疑会在实际生产环境中给模型的训练/部署等流程增加复杂度。因此我们团队选用的基于稀疏训练的结构化剪枝方案。与模型的日常迭代解耦开来。
在这些算法中,比较有效的有Block Sparsity, 以及Channel wised pruning,但前者剪枝后的矩阵参数只存在于稀疏的小块中,需要依赖特别的GPU/CPU矩阵乘法库,因此部署到线上未必能取得性能的提升。而Channel wised pruning则起源于对CNN网络中Convolution layer channel的剪枝。由于每次需要完整地剪掉整个Channel,所以对应到二维矩阵里面,就是要完整得剪掉矩阵的一行或者一列。因此对现有系统更计算友好,我们一开始也是采用的这个方案。具体流程如下
其中X是与该参数矩阵做乘积的输入数据(一般为上一层的激活输出),Y为矩阵乘法的结果。算法的目标是找到参数矩阵砍掉若干列之后的一个子矩阵,使其依然能得到跟原矩阵相似的运算结果。我们使用了Lasso算法对其求解,先从数据集中抽取部分样本(通常10000条样本便足够),并计算出这些样本经过每一层FC Layer时的输入X和输出Y。然后从最后一层开始,从后往前剪枝。
但是我们从优化目标中能看到这种方式主要基于二范数的每一层的二范数重建误差。因此存在性能损失,而且无法量化具体的算力提升。因此我们团队自研了一种APAS算法,其算法核心是通过给每一个神经元叠加前馈权重,这个权重的软阈值作为强化学习算法DDPG的ACTION,从而调控每一层的稀疏程度。以模型评估指标以及算力约束指标作为Reward指导模型优化。
在模型剪枝截断过程,和前述方案类似,预留部分样本端到端训练。但优化目标略有不同,我们采取的是基于scaling factor的结构化剪枝方法。具体而言,我们在每个神经元的输出后面乘上一个gamma,然后对gamma进行稀疏惩罚,当某一神经元的gamma为0时,此时该神经元的输出为0,对其后的模型结构不再有任何影响,即视为该神经元被剪枝。
其中,L(y, f)为模型的损失函数,R_s(gamma)为对于scaling factor的稀疏惩罚,通常为l1正则。与此同时,我们采用了iterative pruning的方式,每隔t轮训练会对gamma为0的神经元进行mask,这样可以保证整个剪枝过程中模型的稀疏率是单调递减的。整体流程如下图所示,首先,APAS框架的输入为一个pretrained模型。然后,模型将进入pruning环节。在pruning环节,APAS会进行多轮one-shot pruning。DDPG agent在该过程中可以积累样本并进行训练,从而输出较优策略,指导模型剪枝,并最终输出reward最高且符合性能约束的topk个模型结构进入下面流程。随后,这些topk模型结构将会retrain from scratch。最终,APAS输出SCORE_pi(x_test, y_test)分值最高的模型结构,作为整个APAS框架的输出。
3、特征剪枝
特征剪枝的方案有很多种,但大部分和评测目标解耦,基于特征权重进行剪枝,以致于需要反复调试截断阈值避免效果损失,比如DropRank,方法和上文的Scaling factor有点类似,只不过是乘到feature group粒度。目前我们团队用过最好用的特征剪枝算法是遗传算法。这个方法不用重训,可以直接在现有迭代模型上进行调试,待模型收敛后直接对应FC1层的矩阵裁剪即可。不过由于搜推广样本只能训练一次,所以依赖OL数据Lifelong训练直到收敛。
整体流程如上,退出后的模型可以直接替换线上生产模型。
Reference
1. Rocket Launching: A Universal and Efficient Framework for Training Well-performing Light Net
2. Practice on Pruning CTR Models for Real-world Systems
3. Ensembled CTR Prediction via Knowledge Distillation
4. Channel Pruning for Accelerating Very Deep Neural Networks |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
×
|