网盛创新研究院 - AI、区块链、云计算、大数据技术的研究与应用交流平台!

网盛创新研究院/大讲堂/正文

模型吞噬特征工程

地址:杭州

2019-03-18

特征工程是机器学习成败的关键一步,其意义一点都不比模型低。宏观层面来说,模型水平决定了机器学习的上限,特征工程水平决定了能接近上限多少。而对于具体问题层面,特征工程水平决定了机器学习在这个问题上的上限,模型决定了能接近上限多少。

blob.png

但是特征工程和模型并不是泾渭分明。比如,那些年间工业界风起云涌了那么多 Learning to Rank 的模型,最终都变成了特征。另外一方面,那些年间工业界那么多下里巴人的特征工程技巧,被模型吞噬,变成阳春白雪模型的一部分。今天我们只聊一聊特征工程到模型的转化。

blob.png

一、特征工程简介

我个人认为,特征工程可以分为两个阶段。1)准备数据,也就是根据领域知识拉取相应的数据,并且进行数据清洗。比如我们认为星期几对人们感兴趣的文章有影响,那么我们构造样本时,就会把星期几的特征放进去,并进行缺失值处理等等数据清洗的工作。2)数据变化,也就是各种归一化、取 Log 、离散化、特征组合交叉等等操作。数据变换目的是为了规整数据量纲和挖掘数据内部规律,从而增强数据表示。

blob.png

当然,有不少朋友认为数据准备不是特征工程。认为只有数据变化部分才是特征工程。我的想法是这样的。很多时候,加合理而重要的特征是特征工程的重要内容之一。加特征这个操作同时涉及到数据准备和数据变化。数据变化又分为五个部分:

特征提取,直接使用数据准备得到的原始特征,或者根据原始特征计算新特征。特征变换,比如归一化、离散化和取 Log,是将一个特征值变换为特征值。特征组合,其中最著名的特征组合就是高阶特征交叉。比如,我们将用户性别和商品颜色进行交叉,得到性别_颜色特征,能很好的刻画不同性别用户对不同颜色商品的偏好。特征选择,就是选择合适的特征,删除冗余特征。特征 ID 化,机器学习模型接受的实例一般是稠密或者稀疏的特征向量,这就需要我们将特征进行排列并赋予 ID。我把特征 ID 化也算进特征工程里来了。不然特征工程和模型之间还有一层特征 ID 化,太麻烦了。数据变化的三个部分并不是严格按照 1,2,3,4,5 的顺序进行的,而是按照个人编程时的喜好进行的。我们说模型正在越来越多地将特征工程吸收进模型,当然说的是数据变化部分,也就是特征变换、特征组合和特征 ID 化。数据准备是不可能纳入模型的。

二、特征提取

特征提取变成模型一部分最著名的例子便是 CNN 了。

抽取图片特征最直观办法就是拿着模板匹配。比如最著名的例子——分辨图中是猫还是狗,如果我们没有深度学习模型也没有计算机视觉知识,我们能想到的办法:1)人肉选取一定大小的猫和狗的典型部位,即模板,比如猫和狗的鼻子、爪子、耳朵和尾巴等等;2)滑动一个和模板大小一致的窗口逐步扫描图片,计算窗口内图片和模板的匹配程度;3)每一个模板的不同窗口的匹配程度取最大值,得到长度为模板个数的特征向量;4)将这个特征向量扔到分类模型中预测。

在实际研究和工作中,直观的模板匹配想法是做不出来的,难点在于如何有效地选择模板。但这种特征提取思路被 CNN 内化了,模板对应卷积核,取最大值对应最大池化,分类模型对应全连接层[8]。

blob.png

唯一不同的是,CNN 可以通过联合学习自动得到卷积核。也就是说,CNN 其实是将特征提取纳入模型中了。

另一个自动提取特征的模型是 CatBoost。CatBoost 号称是能处理类别特征的梯度提升树。实际上 CatBoost 是自动提取了不同类别对应的标签值的比率(计算公式经过优化),得到连续比率值作为特征。

blob.png

三、特征变换

我们确实很少看到,试图将取 Log 、取平方、开根号、Scaling、Dummy 化、 离散化和 归一化等等特征变换手段,变成模型一部分的工作。但也不是不存在这方面的工作。

首先取 Log、取平方和开根号都是不需要额外参数的数学操作。只要数据够,机器够,我肯定都直接要了。没有看到工作让模型自动决定要不要开 取 Log、取平方和开根号等操作的。

其次 Scaling。Scaling 没有归一化优雅和鲁棒(太容易受异常值的影响),在工业场景中出现得比较少,一般都是自己代码处理了。

然后 Dummy 化。Dummy 化是离散类型特征的必选项,连续特征的必不选项(其实也是有奇技淫巧可以用的)。

再然后离散化。模型自动离散化,好像真没有。

最后归一化。模型自动对数据进行归一化,好像也没有。

四、特征组合

在线性模型为主的时代,因为线性模型不能处理非线性高阶特征,因此我们发展了一套特征交叉的特征工程技巧。比如,我们将用户性别和商品颜色进行交叉,得到性别_颜色特征,能很好的刻画不同性别用户对不同颜色商品的偏好。

为了自动进行特征交叉,人们发明了 Factorization Machine (FM) 算法,算法的公式如下所示

FM 相对线性模型除了每个特征有一个权重 w 之外,还有一个向量权重 v 。两个向量权重内积乘特征值,就表示交叉特征的贡献。通过这个操作,FM 模型将交叉特征纳入到模型中。作为 FM 的进一步发展,人们又发明了 Field-aware Factorization Machines (FFM),其公式如下图所示。

FFM 认为特征都属于不同的 Fields, 比如性别属于用户 Field,颜色属于物品 Field,时间属于上下文 Field,好友信息属于社交 Field。 FFM 中每个特征都有 n 个向量权重,其中 n 是 Fields 个数。计算交叉特征时,会用对方特征的 Field 所对应的向量权重。这样做是为了更好地刻画不同特征的交互信息。

沿着将特征组合纳入模型的思路,在大规模线性模型时代,LR 开启了 FM -> FFM 的进化路线。进入深度学习时代, DNN 复制了大规模线性模型的进化之路,开启了 W&D -> DCN -> DeepFM -> DeepFFM 的进化。这一切进化的原动力,便是将特征组合纳入到模型。

上面是一个成功的故事,现在讲一个不成功的故事。为了自动挖掘特征组合, Facebook 在 2014年介绍了通过 GBDT + LR 的方案 [4](XGBoost 是 GBDT 的后续发展)。 XGBoost + LR 融合方式原理很简单。先用数据训练一个 XGBoost 模型,然后将训练数据中的实例给 XGBoost 模型得到实例的叶子节点,然后将叶子节点当做特征训练一个 LR 模型。XGBoost + LR 的结构如下所示。

blob.png

XGBoost 的叶子节点代表了不同特征的高阶组合,本来也是一个强大模型自动完成特征组合的故事。但是根据 [5] 的观点,目前 XGBoost + LR 并没有发展出自己的进化之路,XGBoost 只是成为了提取更多组合特征的工具。我个人认为原因在 XGBoost 和 LR 以及深度学习模型,不能像 CNN 特征提取器和分类模型一样联合训练,XGBoost 等树模型是通过叶子节点分裂进行训练,LR 以及深度学习基于梯度进行训练。但是这个故事并没有结束,现在人们继续探索树模型和深度学习模型的融合之路 [6]。

五、特征选择

我们手动进行特征选择,一般是利用各种指标给特征排序,选择 Top K 的特征作为选择特征。我们使用的大部分模型算法已经 特征选择纳入其中, 将一直在一定意义上进行自动特征选择。

从机器学习的很早期,模型就开始关注各种正则, 比如著名 L1 Norm 和 L2 Norm。L1 Norm 和 L2 Norm 能够使得出现频率很低或者不相关的特征的权重很低,特别是 L1 Norm 非常倾向于让这类特征权值为 0 。 L1 Norm 在自动特征选择上如此成功,以致于人们选择特征直接用 L1 Norm 做。

blob.png

进入深度学习时代, 模型依然很关注正则项。除了 L1 Norm 和 L2 Norm 之外,深度学习模型还发展出了 dropout 和 dropconnect 正则项。

我个人觉得,正是因为机器学习从很早期到大规模应用的现代,一直关注减少模型复杂度各种理论和实践,在相当程度上做了特征选择的工作,才是得特征选择长期处于发育不良的状态。比如我们做大规模 CTR 预估,处理好的特征不做刷选,直接扔到模型里训练。即使有冗余特征,我们也会觉得模型内在 “特征选择” 机制能处理得七七八八。

六、特征 ID 化

特征 ID 化将特征进行排列并赋予 ID。比如特征性别男的 ID 是 12,我们就将特征性别男放到特征向量第 12 位。在算法层面,模型没有将特征 ID 化纳入到模型本身。但是在工程角度上,特征 ID 化是模型模块的一部分。 特征 ID 化只有两种方法:

方法一建立一个大的 map,将特征名作 key, 特征 id 作 value。不同版本的模型,用到的特征很可能不太一样,所以同一个特征名对应的特征 id 很可能是不一致的。因此真实生产环境要求训练程序将产生的模型和 map 同时保存到某个目录,线上预测服务将模型和 map 都加载完毕才开始对外提供服务。这个机制在逻辑上将模型和 map 看成一体的。一般这个机制是有工程师自己保证的。

然后我们看到了 Tensorflow 的 Feature Column。Feature Column 的一个重要好处,就是将这套机制封装,对工程师不可见。工程师在写训练时,看到的是特征名;在调用深度学习服务时,用的也是特征名。当然 Feature Column 也不是完美的,Feature Column 内部是转成稠密向量。因此用 Feature Column 处理 id 类特征,就会产生巨大的浪费。

blob.png

在 Tensorflow 中的编程体验来说, Feature Column 几乎可以看成计算图的一部分。工程上,模型把这部分特征 ID 化工作纳入来了。

方法二用一个 hash 函数将特征名映射出特征。这个方法好处不用再维护一个巨大的 map, 但必须解决 hash 冲突的问题。

blob.png

在大规模线性模型时代,hash 函数生成一个 int64 数字作为特征位,以此来解决冲突问题。 哈希值冲突几率类似于 生日问题。 k 个均匀分布在 2^64 范围的特征哈希值发生冲突的概率为:

1-exp^{-k(k-1)/2^64}

冲突几率就非常小了。在冲突率很小的情况下,即使有冲突也不影响模型性能。

这种解决冲突的方法只能用于支持特征位取值范围很大的大规模稀疏特征的模型,比如线性模型。但是 XGBoost 等一类的树模型和 DNN 等深度学习模型,就用不了了。对了深度学习模型,有人希望 Tensorflow 在工程上实现类似下图的功能[1,2]。

blob.png

这个功能什么意思呢?意思就是使用传统 HashTable 技术解决冲突,然后将整个 HashTable 变成模型的一部分(可训练)。有独立开发者实现了部分功能,可惜碰到了 Tensorflow 2.0 的大升级,被搁置下来了[3]。Tensorflow 2.0 大升级将对全部 lookup 类 API 进行审视。这也是工程上,模型纳入特征 ID 化的工作。

七、总结

一般实践中,除了数据准备之外, 我们在算法层面需要关注的特征工程 有特征提取、特征变换和特征组合;在工程层面需要关注的有特征提取、特征变换、特征组合和特征 ID 化。因为一般模型有控制复杂度的机制,相当于一定意义上进行自动特征选择,特征选择一般不需要关心。

特征工程和模型并不是泾渭分明。那些年间工业界那么多下里巴人的特征工程技巧,被模型吞噬,变成阳春白雪模型的一部分。这也是模型进化的原动力之一。


【版权提示】网盛创新研究院网倡导尊重与保护知识产权。未经许可,任何人不得复制、转载、或以其他方式使用本网站的内容。如发现本站文章存在版权问题,烦请提供版权疑问、身份证明、版权证明、联系方式等发邮件至wzy@netsun.com,我们将及时沟通与处理。
关于我们创新研究院大讲堂服务介绍
© 生意宝(002095) 版权所有  浙公网安备 33010002000015号 工商执照 浙ICP证  网络工商