雷锋网按:本文原作者阿萨姆,本文整理自作者在知乎《如何有效处理特征范围差异大且类型不一的数据?》问题下的回答。雷锋网已获得转载授权。
1. 特征类型混杂: 连续变量,离散变量,描述变量共存
2. 不同变量之间取值差异大: 例如有些变量取值在 0~1 但有些取值为 10000-50000
以 KDD99 网络入侵数据集为例:
总共 41 个特征,其中 3 个 categorical,5 个 binary,剩下 33 个均为连续型特征。
下图为训练集 downsample 了 5W 条数据后针对连续型特征的统计:
可见,不同特征的取值范围差异极大,特征本身分布也是很散(似乎有点长尾)。
面对这样混合的特征类型,而且特征取值范围差异极大的情况,如何进行有效而 reasonable 的特征选择?
这个问题是典型的特征工程(Feature Engineering)的范畴,这个领域的奇淫巧技实在太多,只能粗略的说一下对这种数据类型的基本处理流程。我反对直接进行简单粗暴的归一化或标准化,往往其风险大于收益。
首先我们假设,做数据处理的前提是我们不知道什么分类模型效果最好,且大部分分类器无法直接处理 “描述变量”(categorical variable)。当然,我们知道以决策树为原型的模型可以处理不同的数据类型,且对于变量取值范围比较不敏感,还自带特征选择 (如计算节点分裂的基尼指数)。因此很多时候在进行复杂操作前,不妨先使用随机森林 (Random Forest) 或其他集成学习的树模型暴力做一下。有类似良好的特性 (能自动选择有效特征) 的分类器还包括:
特定种类的深度网络。
L1 范数正则化后的线性模型等。
从本质上看,上面提到的这几种做法其实就是嵌入式特征选择 (Embedding Feature Selection),属于偷懒的一站式操作:) 而这个答案的重心在于将数据处理成可被一般分类器所使用的形态,因为在很多情况下我们无法使用这种偷懒的做法。
回答的结构如下:
移除不必要的数据,降低变量的维度。
对描述变量进行转化,使其适用于大部分的分类器。
分析数据之间的相关性,如共线性。如果有必要,进行特征选择。
归一化和标准化。
* 懒人选项:选用适当的 (对高方差数据鲁棒性好) 的分类模型。
上面这个顺序的逻辑是 1. 初步降低数据维度 2. 再将描述变量转化为其他算法可以分析的格式 3. 分析是否需要特征选择 4. 进行归一化和标准化。一般而言,我们可能会根据情况选择其中的一部分处理方法,比较灵活。
如果 1-4 对你来说太复杂,不妨先试试捷径方法 5。
既然答主提到这个 99 年 KDD 的数据,那么我就以这个数据集为例来回答。
在进行各种维度变换和复杂的处理前,一般我们希望去掉无用和低贡献度的变量,这会大大降低后续的处理难度。
单一值变量:整个数据中该值取值恒定,因此对于模型无贡献。
如下图所示,在除了预测值 (Target) 以外的 41 个值中,有两个变量 num_outbound_cmds 和 is_host_login 在整个数据集中取值唯一,应该被移除。于是我们成功的去掉了两个无用变量,此时也就不用思考这两个变量对于整体取值范围的影响。
1.2. 移除低方差 (low variance) 的变量
和单一取值的变量相似,低方差的变量虽然取值不唯一,但整体的变化很小。我们可以通过人为设定阈值 (threshold) 来去除这种变量。以一个变量只有两个取值为例,我们可以设定阈值来去掉低方差的变量。
如上图所示,此处所调用的 Sklearn 的 API 还有一个作用就是自动移除单一取值的数据,一举两得。
更多资料请移步 Sklearn 官方文档: 1.13. Feature selection
2. 转化描述变量 (convert categorical var to numeric)
如上文描述的,我们在不假设分类器的前提下,必须对描述变量转化为数字类型变量,因为大部分算法无法直接处理描述变量。
描述变量一般分两种,其转换方法不同:
1. 有序变量。比如小学,初中,高中,大学。又比如非常满意,满意,不满意,极不满意。这类变量中的可取值之间都有一种顺序关系,因此不能单纯的用独热编码 (One-hot Encoding) 来转化,因为在转化过程中会失去顺序信息。在这种情况下可以由来转换, N 代表该变量可取的值得总数。此处也要注意,不是每种顺序对每个问题都是有意义的。比如假设一个变量可以取三个值:“头等舱”,“商务舱”,“经济舱”,对于票价而言是有顺序的,但对于到达时间,这三者是无序的。
2. 无序变量。比如一个公司有三个部门: 研发,测试,HR。
在分类问题中我们可以简单的使用独热编码进行转化。
若在聚类问题中,我们一般希望度量其差异性,比较常见的是 Value Difference Metrics (VDM) 这一类。说白了就是直接看两个点的这个维度是否相同,若有 N 个无序变量,我们一般构建一个的矩阵来描述差异度(Degree of Difference)。
3. 变量相关性分析及特征选择
在进行建模前,可以快速的查看变量之间的相关性,这对下一步的是否进行特征选择有比较重要的意义。我们假设在这一步的时候,已经去除了多余变量且所有描述变量都转化为了数字型变量。
计算变量之间的相关性可以得到一个矩阵,用于描述每两个变量这件的相关性 (-1 代表负相关,0 代表无关,1 代表正相关)。在可视化后 KDD99 数据的相关性图谱后可得到下图。
做相关性图谱的原因是为了看一下是否存在大量的共线性 (colinearity)。 最极端的特例就是虽然特征很多,但事实上之间互相关联性很强,存在强线性关系,对于模型帮助不大。
以 KDD 的数据为例,我们可以看出变量间存在一些共线性,但并不算是极端严重。这告诉我们可以两个可以尝试的方法来处理这些变量:
特征选择 (feature selection)
维度压缩 (dimensionality reduction), 例如主成分分析 (PCA)
如果我们足够幸运,看到了零共线性 (现实情况是不会发生的) 或者低共线性,我们大可以暂时跳过特征选择。当然,略过特征选择的风险是某个变量可能和我们要去预测的事情完全无关。
特征选择是一个很大的话题,简单说就是从多个变量中选择出一部分对于分类比较重要的特征,抛弃冗余变量 (redundant variables)。
统计学习中一般用子集搜索 (subset),包括全搜索 (exhaustive search),贪心算法类搜索 (正向搜索,逆向搜索,和从两边同时搜索)。
机器学习中一般有三种特征选择:
过滤式 (filter): 其实我们刚才查看相关性图谱就是一种过滤式搜索的思路。在这种方法中,我们仅通过评价不同变量之间的统计相关性来进行特征选择,如 Chi Squared 和 Pearson。
包裹式 (wrapper): 和过滤式不同,包裹式特征选择引入了分类器,通过评估不同的变量在相同分类器下的表现来选择最优的变量。注意,选择出的 "最优变量" 可能仅仅在当前分类器下表现好,后续使用其他分类器效果很难保证。
嵌入式 (embedding): 思路是建立分类器的同时选择有效的变量,文章开头处提到的 L1 正则化和很多决策树模型都有这个特质。
以本题中的 KDD 数据为例,或许降维是一个比特征选择更加划算的做法。主成分分析即将高维数据投射到一个低维空间中来压缩和合并。
在非线性降维领域,流形学习 (manifold learning) 现在正大行其道,有兴趣的朋友可以关注一下。
此处必须提醒大家 PCA 和大部分流形学习都要求数据的归一化,我们稍后会简单介绍。
4. 归一化 (Normalization) 和标准化 (Standardization)
归一化和标准化是两种常见的数据转换方法,但这两种方法有一定的风险,我并不推荐一上来就先进行归一化或者标准化。这类数据转化方法存在的意义有很多,比较常见的应用是统距离度量 (distance estimation) 时的范围。简单来说,以 KNN 为例,我们计算两个数据点的相似度为其几何距离,那么如果不同变量的可取值区间不同甚至相差巨大,那么可能会有部分变量有过大的影响力。
归一化和标准化的目标都是将元数据投射到一个规范区间中,如 [0,1] 。给出一个最简单的标准化例子,假设原数据 [1,2,3,4,5]通过一种最简单的转化为 [0,0.25,0.5,0.75,1] 。由此可见我们可以人为的控制数据的投射范围,但不可避免的数据中的一部分信息可能会遗失。
相关的算法还有很多且资料很多,不在此赘述,如主成分分析中使用的 z-score 规范化:
5. 什么模型对于高方差且变量类型复合比较友善?
像我在答案开头提到的,比较稳定的是以决策树为基学习器的集成学习:
在分类问题中,不妨先试试随机森林 (Random Forests)。
回归问题中可以试试 Gradient Boosted Tree Regression。
这一类模型都可以很好的做到降低高方差、处理非线性关系、选择有效特征。对于 KDD99 的比赛,如果那个时候已经有了随机森林 (2001 年的论文) 的话,可能冠军会是 Breiman 吧:)
祝大家炼丹愉快 (͡๏̯͡๏)
不灵叔@雷锋网