有这么一句话在业界广泛流传:数据和特征决定了机器学习的上限,而模型和算法只是逼近这个上限而已。由此可见,特征工程在机器学习中占有相当重要的地位。在实际应用当中,可以说特征工程是机器学习成功的关键。
数据清洗
数据清洗(data cleaning)的主要思想是通过填补缺失值、光滑噪声数据,平滑或删除离群点,并解决数据的不一致性来清理数据。
缺失值插补
由于现实世界中,获取信息和数据的过程中,会存在各类的原因导致数据丢失和空缺,称之为缺失值(missing values),通常编码为NA(Not Available)、NaN(Not a Number)或 NULL。
使用不完整数据集的基本策略是舍弃包含缺失值的整行或整列。但是,这是以丢失可能有价值的数据为代价的(即使数据不完整)。更好的策略是缺失值插补(imputation of missing values),即从数据的已知部分推断出缺失值。
缺失值的处理方法,主要是基于特征的分布特性和重要性(信息量和预测能力)采用不同的方法。处理策略主要分为以下几种:
- 删除特征:若特征的缺失率较高(大于80%),且重要性较低,可以直接删除。
- 统计量插补:若缺失率较低(小于95%)且重要性较低,则可随机抽样插补,或使用缺失值所在各列的统计量(平均值/中位数/众数)插补。
- 模型插补:将每个包含缺失值的特征建模为其他特征的函数,并将该估计值用于插补。常用回归、贝叶斯、决策树等模型对缺失数据进行预测。
- 插补法:包括多重插补、拉格朗日插值、牛顿插值等。
- 哑变量插补:若变量是离散型,且类别较少,可转换成哑变量。例如,性别特征可使用one-hot编码为M/F/NA三列,此做法可最大化保留变量的信息。
多重插补:(multiple imputation)统计学中,通常的做法是同时执行多个插补。例如,为单个特征生成m个独立的插补。然后,将m个插补中的每一个都会进入后续的分析流程(特征工程,聚类,回归,分类)。最终获得m个分析结果(例如保留的验证错误),使数据科学家能够了解由于缺失值所引起的固有不确定性,分析结果可能会有所不同。上述做法称为多重插补。
KNN插补:(KNN imputation)使用最近邻方法(k-Nearest Neighbors)进行缺失值插补。
- 首先,查找缺失样本的k个最近邻(有特征值);
- 然后,k近邻的特征通过平均值或距离加权值来估算缺失值。
异常检测
远离其它内围点(inlier)的数据通常被定义为离群值(outlier),也称异常值。我们在实际项目中拿到的数据往往有不少异常数据,这些异常数据很可能让我们模型有很大的偏差。异常检测(anomaly detection)分为离群点检测以及新奇值检测两种。
离群点检测:(outlier detection)适用于训练数据中包含异常值的情况。离群点检测模型会尝试拟合训练数据最集中的区域,而忽略异常数据。
新奇值检测:(novelty detection)适用于训练数据不受异常值的污染,目标是去检测新样本是否是异常值。 在这种情况下,异常值也被称为奇异点(novelty)。
- 分位数检测:根据四分位点判断是否异常。通常认为小于 或大于 的点为离群点。
- 3倍标准差原则:假设数据满足正态分布,通常定义偏离均值的 之外内的点为离群点,。
- Elliptic Envelope:假设数据满足正态分布,训练一个椭圆包络线,边界外的点则为离群点
- One Class SVM:基于 SVM (使用高斯内核) 的思想在特征空间中训练一个超球面,边界外的点即为异常值。
- Isolation Forest:是一种高效的异常检测算法,它和随机森林类似,但每次分裂特征和划分点(值)时都是随机的,而不是根据信息增益或基尼指数来选择。
- LOF:基于密度的异常检测算法。离群点的局部密度显著低于大部分近邻点,适用于非均匀的数据集。
- 聚类检测:常用KMeans聚类将训练样本分成若干个簇,如果某一个簇里的样本数很少,而且簇质心和其他所有的簇都很远,那么这个簇里面的样本极有可能是异常特征样本了。
异常值常用的处理手段:
- 根据异常点的数量和影响,考虑是否将该条记录删除。
- 对数据做 log-scale 对数变换后消除异常值。
- 使用平均值或中位数替代异常点,简单高效。
- 树模型对离群点的鲁棒性较高。
噪声处理
噪声是变量的随机误差和方差,是观测点和真实点之间的误差。
- 通常的处理办法:对数据进行分箱操作,等频或等宽分箱,然后用每个箱的平均数,中位数或者边界值(不同数据分布,处理方法不同)代替箱中所有的数,起到平滑数据的作用。
- 另外一种做法:建立该变量和预测变量的回归模型,根据回归系数和预测变量,反解出自变量的近似值。
数据变换
标准化
一般而言,样本特征由于来源以及度量单位不同,它们的尺度(Scale)(即取值范围)往往差异很大,不进行处理可能会影响到数据分析的结果,因此,需要对数据按照一定比例进行缩放,使之落在一个特定的区域,便于进行综合分析。
特征缩放(Feature Scaling)泛指把数据特征转换为相同尺度的方法。在数据处理中较为常用,也被称之为标准化(Normalization)或归一化。对于每一维特征,通常先计算它的均值和方差方便使用
Min-Max Normalization:使用最大最小值将数据映射到 区间
Mean Normalization:使用平均值 将数据映射到 区间
Standardization:又称 Z-score Normalization。在实践中,我们通常会忽略分布的形状。使用平均值 和标准差 将样本特征值转换为均值为0,标准差为1的数据分布
Log Scaling:适用于数据量级相差较大的特征
L2 Normalization 使用特征向量的范数 将特征归一化
Robust Scaling:如果数据中包含许多离群值,使用数据的均值和方差进行缩放可能效果不佳。在这种情况下,可以使用对异常值鲁棒的统计信息来缩放特征,例如中位数(median)和四分位数间距(IQR)。
非线性变换
非线性变换(Non-linear transformation)通常有两种类型的转换:分位数变换和幂变换。分位数和幂变换都基于特征的单调变换,从而保持了每个特征值的秩。
分位数变换(Quantile Transformer):基于公式 将所有特征置于相同的期望分布中,其中 是特征的累积分布函数,并且 是期望输出分布 的分位数函数。
- 如果 是连续累积分布函数 的随机变量,则 是 区间上的均匀分布;
- 如果 是在 区间上符合均匀分布的随机变量,则 符合分布 。
通过执行秩变换,分位数变换可以平滑异常的分布,并且与标准化缩放相比,离群值的影响较小。但是,它确实扭曲了特征之间的相关性和距离。
分位数变换在训练样本足够大的情况下(通常需要几千个样本),可以把任意分布的数据变换成正态分布。分位数变换是一种非参数方法,它的结果比参数变换,例如Box-Cox 和 Yeo-Johnson变换,更难解释。在小样本下(几百个样本),分位数变换被证明是过度拟合的。因此,推荐使用参数变换。
幂变换(Power Transformer):是一组参数化的单调变换,旨在将数据从任何分布映射到尽可能接近高斯分布,以稳定方差并最小化偏度。
Yeo-Johnson 变换:
Box-Cox变换:
在这两种幂变换中,都是通过最大似然估计确定参数 。Box-Cox 变换不支持负值的输入。对于 lognormal 和 chi-squared 分布,Box-Cox 变换表现好于 Yeo-Johnson 变换。
重编码
ordinal encoding:对有序分类特征,可通过有序编码将其转化为连续值。如改善水平字段 {Poor, Improved, Excellent}
可以重编码为 {1,2,3}
。
one-hot encoding:对于可以取 个值的分类特征,可以使用one-hot (也称one-of-K或dummy)编码方案进行编码,为每个类别创建一个二元特征(0或1),最后返回 维向量。如下图示例
mean encoding:如果某一个分类特征的可能值非常多(高基数 high cardinality),那么再使用one-hot编码往往会出现维度爆炸。平均数编码的编码方法,在贝叶斯的架构下,利用所要预测的应变量(target variable),有监督地确定最适合这个定性特征的编码方式。
离散化:(Discretization)也称分箱(Binning)。数据离散化是指将连续的数据进行分段,使其变为一段段离散化的区间。数据离散化的原因主要有以下几点:
- 模型需要:比如决策树、朴素贝叶斯等算法,都是基于离散型的数据展开的。如果要使用该类算法,必须将数据离散化。有效的离散化能减小算法的时间和空间开销,提高系统对样本的分类聚类能力和抗噪声能力。
- 离散化的特征相对于连续型特征更易理解。
- 可以有效的克服数据中隐藏的缺陷,使模型结果更加稳定。
离散方法主要有以下三种:
- 等频法:使得每个箱中的样本数量相等。例如样本数 ,分成 个箱,则分箱原则是保证落入每个箱的样本量为20。
- 等宽法:使得属性的箱宽度相等。例如年龄变量(0-100之间),可分成 [0,20],[20,40],[40,60],[60,80],[80,100]五个等宽的箱。
- 聚类法:根据聚类出来的簇,每个簇中的数据为一个箱,簇的数量由模型给定。
二值化:(Binarization)是将连续特征用阈值 过滤以获得布尔值的过程
WOE(Weight of Evidence,证据权重)编码是对离散化特征的一种编码形式,使用每个箱中的WOE值编码,表示每个分箱对目标变量的一种影响。
其中, 为第 个分箱中的正负样本数, 为总的正负样本数。
特征选择
在实际项目中,我们可能会有大量的特征可使用,有的特征携带的信息丰富,有的特征携带的信息有重叠,有的特征则属于无关特征,尽管在拟合一个模型之前很难说哪些特征是重要的,但如果所有特征不经筛选地全部作为训练特征,经常会出现维度灾难问题,甚至会降低模型的泛化性能,因为较无益的特征会淹没那些更重要的特征。
特征选择(Feature Selection)是选取原始特征集合的一个有效子集,使得基于这个特征子集训练出来的模型效果最好。简单地说,特征选择就是保留有用特征,移除冗余或无关的特征。
- 相关特征(relevant feature): 对于学习任务有帮助,可以提升学习算法的效果;
- 无关特征(irrelevant feature): 对于学习任务没有任何帮助,不会给算法的效果带来任何提升;
- 冗余特征(redundant feature): 特征的信息可以由其他的特征推断出。
需注意的是,特征选择过程必须确保不丢失重要特征,否则后续学习过程会因为重要信息的缺失而无法获得好的效果。有时冗余特征会降低学习任务的难度,例如学习目标是估算立方体的体积,则“底面积”这个冗余特征的存在将使得体积的估算更容易。本章暂且假定数据中不涉及冗余特征,井且假定初始的特征集合包含了所有的重要信息。
特征选择算法可看作搜索技术和评价指标的结合。前者提供候选的新特征子集,后者为不同的特征子集打分。通过选择不同的评价指标,可以把特征选择算法分为过滤式、包裹式和嵌入式方法。
- 过滤式方法:先对数据集进行特征选择,然后用特征子集来训练学习器,特征选择过程与后续学习器无关。
- 包裹式方法:直接把最终将要使用的学习器的性能作为特征子集的评价准则。
- 嵌入式方法:是将特征选择过程与学习器训练过程融为一体。
过滤式方法
过滤式方法(Filter Method)先对数据集进行特征选择,然后用特征子集来训练学习器,特征选择过程与后续学习器无关。过滤式方法运行速度快,是一种非常流行的特征选择方法。过滤式方法也常常用于包裹式方法的预处理步骤,以便在问题太复杂时依然可以用包裹式方法。
过滤式方法按照发散性或相关性对各个特征进行评价,设定阈值或者待选择的特征个数进行筛选。
- 特征是否发散:如果一个特征不发散(低方差),也就是说样本在这个特征上基本上没有差异,这个特征对于样本的区分并没有什么用。
- 特征与目标的相关性:显然,与目标相关性高的特征,应当优选选择。特征选择给出各特征的重要性,用户可根据重要性选择。
移除低方差特征:(VarianceThreshold)是特征选择的一种简单的基本方法。它删除方差不满足阈值的特征,即在所有样本中的值差别不大。
例如,我们想要移除布尔特征中0或1的比例超过80%的特征。布尔特征是伯努利(Bernoulli)随机变量,方差公式 。因此,我们可以使用阈值0.8*(1-0.8)
进行选择。
信息增益:(Information gain)即引入特征后条件分布 的不确定性的减少程度。
其中, 分别表示原数据的熵, 表示引入特征后的条件熵。
Pearson相关系数:(Pearson Correlation coefficient)衡量了两个连续变量之间的线性相关程度,其取值范围 。
卡方检验:(Chi-squared test)是检验两个分类变量的相关性。
互信息法:(Mutual information)用于衡量两个变量相互依赖的程度,两分类变量的计算方式如下
方差分析:基于F检验的方法估计连续变量和分类变量的相关性。
其中,MSA 为组间均方差,MSE 为组内均方差。对于回归问题,sklearn 中使用相关系数对两连续变量进行F检验。
IV(Information Value,信息价值)用来评价分箱特征对二分类变量的预测能力。
其中, 为第 个分箱中的正负样本数, 为总的正负样本数。
包裹式方法
包裹式方法(Wrapper Method)直接把最终将要使用的学习器的性能作为特征子集的评价准则。因此,从最终学习器性能来看,往往能为特定类型的模型找到性能最好的特征集。但另一方面,由于在特征选择过程中需多次训练学习器,因此包裹式特征选择的计算开销通常比过滤式特征选择大得多。
子集搜索:(Subset Search)目标是找出最佳特征子集。假设原始特征数为 ,则共有 个候选子集。若直接遍历所有特征子集,效率太低。最常用的方法是采用贪心策略搜索,可大大减小时间复杂度。
- 前向搜索:(Forward Search)初始特征子集为空集,而后的每一次循环我们都持续放入能最大限度提升模型性能的特征,直到任何变量都不能提升模型表现。
- 后向搜索:(Backward Search)该方法先用所有特征建模,再逐步剔除最不显著的特征来提升模型表现。同样重复该方法直至模型表现收敛。
- 双向搜索:(Bidirectional Search)将前向搜索与后向搜索结合起来,即在每一轮中既有添加操作也有剔除操作。
递归特征消除:(recursive feature elimination,RFE)使用一个基模型(通常用于支持向量机)来进行多轮训练来选择特征。首先,预测模型在原始特征上训练,每项特征指定一个权重。然后,从当前的特征集合中移除最不重要的特征。在特征集合上不断的重复递归这个步骤,直到最终达到所需要的特征数量为止。
基于排列的特征重要性(permutation feature importance):表示了模型对特征的依赖程度。单个特征取值被随机打乱时模型得分的降低程度。可以通过特征的不同排列进行多次计算。
特征 的重要性为
其中 表示模型关于原始数据集 的参考分数, 表示第 次随机打乱数据集 后的得分。
注意:特征排列重要性本身并不能反映特征的内在预测价值,但是能体现这个特征对于特定模型的重要性。
回归系数:训练线性回归或逻辑回归,提取每个变量的表决系数,进行重要性排序。
嵌入式方法
嵌入式方法(Embedded Method):在过滤式和包裹式特征选择方法中,特征选择过程与学习器训练过程有明
显的分离。与此不同,嵌入式特征选择是将特征选择过程与学习器训练过程融为一体,两者在同一个优化过程中完成,即在学习器训练过程中自动地进行了特征选择。
基于树的特征选择:树模型在学习时,利用不纯度可以确定最优特征,这本身也可以看作一个特征选择的过程。对于分类问题,通常采用基尼不纯度或者信息增益,对于回归问题,通常采用的是方差或者最小二乘拟合。
基于惩罚项的特征选择:我们可以通过正则化(Regularization)来实现特征选择。正则化与正则化都试图在最小化损失函数的同时,让特征权重也尽可能地小。 正则化会导致线性模型具有稀疏解,许多特征权重为零,因此间接实现了特征选择。
例如,Lasso使用 正则化,岭回归使用 正则化。我们可以将原优化问题看做下面的问题
从图中可以看出: 范数会趋向产生少量的特征,其他特征的权重都是0; 会选择更多的特征,这些特征的权值都会接近于0。因此, 范数在特征选择上十分有用,而 范数则具备较强的控制过拟合能力。
特征提取
特征提取(Feature Extraction)被用于将原始特征提取成机器学习算法支持的数据格式,比如文本特征向量化,图像分块等。
降维
当数据的维度很高时,很多机器学习问题变得相当困难。这种现象被称为维度灾难(curse of dimensionality)。缓解维数灾难的一个重要途径是降维(dimension reduction), 亦称维数约简。
常见的降维方法除了特征选择以外,还有维度变换,即将原始的高维特征空间映射到低维子空间(subspace),并尽量保证数据信息的完整性。常见的维度变换方法有
- 主成分分析:(PCA)是一种无监督的降维方法,其目标通常是减少冗余信息和噪声。
- 因子分析:(FA)是找到当前特征向量的公因子,用公因子的线性组合来描述当前的特征向量。
- 奇异值分解:(SVD)可解释性较低,且计算量比PCA大,一般用在稀疏矩阵上降维,例如图片压缩,推荐系统。
- 线性判别分析:(LDA)本身也是一个分类模型,是为了让映射后的样本有最好的分类性能。
- 流行学习:复杂的非线性方法。
样本不平衡
常用方法
现实中,样本(类别)样本不平衡(class-imbalance)是一种常见的现象,如:金融欺诈交易检测,欺诈交易的订单样本通常是占总交易数量的极少部分,而且对于有些任务而言少数样本更为重要。一般地,做分类算法训练时,如果样本类别比例(Imbalance Ratio)(多数类vs少数类)严重不平衡时,分类算法将开始做出有利于多数类的预测。一般有以下几种方法:
-
权重法:是比较简单的方法,我们可以对训练集里的每个类别加一个权重class weight。如果该类别的样本数多,那么它的权重就低,反之则权重就高。如果更细致点,我们还可以对每个样本加权重sample weight,思路和类别权重也是一样,即样本数多的类别样本权重低,反之样本权重高。sklearn中,绝大多数分类算法都有class weight和 sample weight可以使用。
-
采样法:如果权重法做了以后发现预测效果还不好,可以考虑采样法。采样法常用的也有两种思路,一种是对类别样本数多的样本做欠采样,另一种思路是对类别样本数少的样本做过采样,最后再去拟合模型。
-
数据增强(Data Augmentation)是指从原始数据中加工出更多的数据表示,提高原数据的数量和质量,从而提高模型的学习效果。比如SMOTE、Borderline-SMOTE、Adaptive Synthetic Sampling(ADA-SYN)等。
-
损失函数层面的主流就是常用的代价敏感(cost-sensitive)学习,为不同的分类错误给予不同惩罚力度(权重),在调解类别平衡的同时,也不会增加计算复杂度。即对少数类样本给更大的权重系数,对多数类样本给更小的权重系数,通过这种方式可以在一定程度上解决样本不均衡的问题。常用的损失函数有OHEM和Focal Loss。
-
集成方法:解决不均衡问题,更为优秀的是基于采样+集成树模型等方法,可以在类别不均衡数据上表现良好。简单来说,通过重复组合少数类样本与抽样的同样数量的多数类样本,训练若干的分类器进行集成学习。包括利用模型集成(Ensemble)的方法的EasyEnsemble和利用增量训练的思想(Boosting)BalanceCascade。
-
评估指标:分类常用的指标precision、recall、F1、混淆矩阵,对于样本不均衡的不同程度,都会明显改变这些指标的表现。可以采用AUC、AUPRC(更优)评估模型表现,AUC对样本的正负样本比例情况是不敏感。
随机抽样
随机抽样(random sampling)在机器学习领域,是很常见的做法。例如,将原始数据集随机分为训练集和测试集。常用的抽样方法有无放回抽样和有放回抽样。
针对非平衡的数据集,为了使得模型在这个数据集上学习的效果更加好,采样法常用的也有两种思路,一种是对类别样本数多的样本做欠采样,另一种思路是对类别样本数少的样本做过采样,来实现样本均衡。
过采样(over sampling)和欠采样(under sampling)也叫做上采样和下采样。
SMOTE
SMOTE算法通过人工合成的方法来生成少类别的样本。通过这种方法,我们可以得到不改变训练集分布的新样本,让训练集中各个类别的样本数趋于平衡。
主要策略为:
- 首先,对每个少数类样本 ,从它的最近邻中随机选 个样本;
- 然后,在 和近邻样本之间的连线上随机选一点作为新合成的少数类样本。
Focal Loss
OHEM(Online Hard Example Mining)算法的核心是选择一些难样本(多样性和高损失的样本)作为训练的样本,针对性地改善模型学习效果。对于数据的类别不平衡问题,OHEM的针对性更强。
Focal Loss的核心思想是在交叉熵损失函数(CE)的基础上增加了类别的不同权重以及困难(高损失)样本的权重,以改善模型学习效果。
对于二元分类问题,交叉熵(cross entropy)损失函数定义为
其中 为正样本概率函数,用来简化公式:
Focal Loss 函数定义如下:
其中权重因子 根据正负样本的分布设置,用来平衡损失函数分布
称为调制因子(modulating factor),
分解开来
调制因子减少了易于分类(概率高)的样本的贡献。
- 当 的时候,调制因子趋于1,对于总的loss的贡献很大。当的时候,调制因子趋于0,也就是对于总的loss的贡献很小。
- 当 的时候,focal loss就是传统的交叉熵损失,可以通过调整 实现调制因子的改变。
引用作者的话:当 时,与 CE 相比,分类为 的示例的损失将降低 100 倍,而当 时,其损失将降低 1000 倍。减少易于分类的示例的损失,可以让训练更多地关注难以分类的示例。
集成方法
解决不均衡问题,更为优秀的是基于采样+集成树模型等方法,可以在类别不均衡数据上表现良好。简单来说,通过重复组合少数类样本与抽样的同样数量的多数类样本,训练若干的分类器进行集成学习。
EasyEnsemble 是利用模型集成(Ensemble)的方法多次欠采样。核心思路就是将多数类样本集随机分成 N 个子集,且每一个子集样本与少数类样本相同,然后分别将各个多数类样本子集与少数类样本进行组合,产生多个不同的训练集,进而训练多个不同的基分类器,最后bagging集成各基分类器,得到最终模型。
BalanceCascade 是利用增量训练的思想(Boosting)。核心思路就是在每一轮训练时都使用多数类与少数类数量上相等的训练集,然后使用该分类器对全体多数类进行预测,对于那些分类正确的多数类样本不放回,然后对这个更小的多数类样本欠采样产生训练集,然后进入下一轮迭代继续降低多数类数量。
通常,在数据集噪声较小的情况下,可以用BalanceCascade,可以用较少的基分类器数量得到较好的表现(基于串行的集成学习方法,对噪声敏感容易过拟合)。噪声大的情况下,可以用EasyEnsemble,基于串行+并行的集成学习方法,bagging多个Adaboost过程可以抵消一些噪声影响。