赞
踩
最近忙里偷闲,看了两篇深度学习在工业界落地的paper,这里总结一下,方便以后的复习和回顾。主要参考了2019年facebook的paper《Deep Learning Recommendation Model for Personalization and Recommendation Systems》和2019年第四范式在KDD上发表的paper《AutoCross: Automatic Feature Crossing for Tabular Data in Real-World Applications》。
一开始我想说的是,一般讲深度学习在工业界落地的paper,那么其模型本身一般都不是特别的复杂,但是其中有很多工程化的技巧和工程化的架构设计还是非常值得我们学习的。
上图就是facebook提出的整体模型架构图,整体来看是非常普通的,甚至还不如当下很多在会议上灌水的paper提出的架构“花哨”。从底向上看,对于sparse feature进行了Embedding的表示,而对于dense feature,则是把所有的dense feature拼接起来通过MLP,得到和sparse feature Embedding向量一样的维度,方便后续做特征的交叉操作(向量的内积)。接下来将sparse feature和经过了MLP的dense feature进行特征之间的两两交叉操作,然后将交叉后的结果和原始的特征一起拼接起来在经过MLP从而得到最终的输出结果。
可以说从模型上来看的话,这篇paper提出的结构没有任何新颖之处。但是最后作者讲到了一些工程实现上的技巧,思想还是非常值得我们去学习的。
其实上图就包含了facebook在将这篇paper落地时候使用的工程技巧,即数据并行+模型并行。在特征的表示即输入阶段,由于Embedding的参数量是非常巨大的,而通常Device(一般指GPU)的容量是有限的,故这里将Embedding参数拆分到了多台Device中去;到了后续的MLP阶段即计算阶段,由于这部分的计算量比较大,而参数量比较小,故这里采用了数据并行的策略,即同一份参数拷贝到多台Device中去,这些Device同时可以对不同的数据进行计算,计算梯度之后对梯度进行汇总,然后更新参数。目前开源的深度学习框架,Pytorch和Caffee都没有很好的同时提供这两种粒度的并行,故facebook推荐团队自研了学习框架。
第二篇要讲的就是第四范式提出的AutoCross,这属于AutoML领域的一个方向。说道这里我来讲一下什么是AutoML即Auto machine leaning,把机器学习的过程看成一个pipeline,那么可以大致包含以下几个步骤:1 数据预处理;2 特征工程;3 模型选择;4 模型超参数选择;5 模型训练;6 模型发布。这6个步骤的自动化就可以称之为AutoML。而本篇的AutoCross就是第二个步骤,即特征工程部分的自动化,而且强调是表结构数据特征工程的自动化(区别于图像和文本数据),其主要在探索如何高效的衍生出high-order特征来提高模型的分类性能。
上图就是第四范式提出的实现Auto-cross的工程架构图,三个虚线框,最左边的是逻辑流,中间是算法流,右边是工程架构图。
其中preporcess部分主要是缺失值的填充和数值类型的离散化。这里需要强调一下,一般在进行数值离散化的时候,分桶的个数是一个超参数,而作者也发现这个超参数的设置对最终模型的效果影响较大,而为了真正体现AtuoML的原则,作者采用了对同一数值特征采用多粒度分桶的策略,如下图所示:
这样好处是可以将各个分桶粒度都覆盖,不必为了调整分桶个数这一超参数而烦恼,缺点就是会使特征维度大大增加,为了控制入模的特征维度,作者这里使用了Field-wise 的LR对特征进行重要性筛选,只选择比较重要的特征,至于具体什么是Field-wise的LR,后面会详细论述。
作者也发现,如果直接对原始特征进行高阶特征交叉扩展,这样的搜索空间太大了,根本没法穷举所有的高阶特征组合情况,于是提出了beam search的方法利用启发式的方法对特征进行交叉扩展:
从图中可以看出,这种搜索策略是一种基于树型结构的搜索策略。根节点就是原始的特征集合,底下每一层叶子节点的特征都是包含了根节点的原始特征加上一个父节点内的pair-wise交叉特征,每次从同一层选出最佳节点,然后从该节点开始往下扩展,生成过程paper里原文如下描述:
那么如果衡量每一层中哪个节点包含的特征集合是最佳集合呢?为了加快工程上的训练速度,这里作者使用了Field-wise LR的方法,即训练一个LR模型来根据LR模型在预测集上的表现来评判对应特征的重要性,之所以选用简单的LR模型,也是因为LR模型简单,训练速度快,有利于工程化的实现。即假设原始特征集是
[
A
,
B
,
C
]
[A,B,C]
[A,B,C],那么在父节点训练出的每一个特征权重是
[
W
A
,
W
B
,
W
C
]
[W_A,W_B,W_C]
[WA,WB,WC],那么下一层扩展出的子节点就有
[
A
,
B
,
C
,
A
B
]
,
[
A
,
B
,
C
,
A
C
]
,
[
A
,
B
,
C
,
B
C
]
[A,B,C,AB],[A,B,C,AC],[A,B,C,BC]
[A,B,C,AB],[A,B,C,AC],[A,B,C,BC],它们对应的参数就有
[
W
A
,
W
B
,
W
C
,
W
A
B
]
,
[
W
A
,
W
B
,
W
C
,
W
A
C
]
,
[
W
A
,
W
B
,
W
C
,
W
B
C
]
[W_A,W_B,W_C,W_{AB}],[W_A,W_B,W_C,W_{AC}],[W_A,W_B,W_C,W_{BC}]
[WA,WB,WC,WAB],[WA,WB,WC,WAC],[WA,WB,WC,WBC],那么训练对于的每一个新的叶子节点的时候,固定住从父节点那里继承来的特征的权值,只更新新加入特征的权重,这样的话,父节点那些特征和权重的内积就可以看成是一个固定值,
P
l
e
a
f
=
s
i
g
m
o
i
d
(
b
s
u
m
+
W
n
e
w
∗
X
n
e
w
)
P_{leaf}=sigmoid(b_{sum}+W_{new}*X_{new})
Pleaf=sigmoid(bsum+Wnew∗Xnew)。这样做的愿意也是为了加入模型的训练速度。
当然作者在对每一层叶子节点中的特征集进行衡量的时候,也不是对每一个叶子节点都把所有的训练数据过一遍,这样当数据量比较大而叶子节点个数比较多的时候,会特别消耗时间,采用了一种近似的方法:
即对原始训练数据按照一定的规律进行划分,每次只取一部分数据来更新各个叶子节点的候选集参数,然后每一次循环就淘汰掉一半的后选集。
其实,从模型本身来看这两篇paper都不是特别的复杂,没有那种给人眼前一亮的感觉。但是其中在工程实现上的很多技巧还是非常值得我们去学习的。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。