机器学习算法:特征工程

通常说“数据决定了机器学习的上限,而算法只是逼近这个上限。”这里所说的数据指的就是特征工程得到的数据。Andrew Ng说过:“创造新的特征是一件十分困难的事情,需要丰富的专业知识和大量的时间。机器学习应用的本质基本上就是特征工程。”由此可见,特征工程在机器学习中占有相当重要的地位。

特征是指从原始数据中抽取出对结果预测更有用或表达更充分的信息。更好的特征意味着“更强的灵活性+更简单的模型+更好的结果”

特征工程是指利用数据领域的相关知识和技巧处理数据,使得特征能能在机器学习算法达到最佳性能的过程。

1、特征工程的处理步骤

使用机器学习算法解决问题的过程是这样的:

a.数据采集(Data Collection):整合数据,将数据规范化成一个数据集,收集起来。

b.数据预处理(Data Preprocessing):数据清洗、数据标准化及归一化等。

c.数据转换(Data Transformation):特征构造、特征提取、特征选择。

d.数据建模(Data Modeling):建立模型,评估模型并逐步优化。

在上述步骤中,数据预处理和数据转换均属于特征工程的工作。事实上,特征工程是一个迭代过程,我们需要不断的设计特征、选择特征、建立模型、评估模型,然后才能得到最终的模型。下面是特征工程的一个迭代过程:

a.头脑风暴式特征:从原始数据中提取特征,暂时不考虑其重要性,对应于特征构建。

b.设计特征:根据需解决的问题,可以使用自动地特征提取,或者手工特征构造,或者两者混合使用。

c.选择特征:使用不同的特征重要性评分和特征选择方法进行特征选择。

d.评估模型:使用选择的特征进行建模,同时使用未知的数据来评估模型精度。

综上所述,特征工程应包含数据预处理、特征构造、特征提取、特征选择等步骤

2、数据预处理

1)数据清洗

数据清洗(Data Cleaning)是对数据进行重新审查和校验的过程,目的在于删除重复信息、纠正存在的错误,并提供数据一致性。

数据清洗包括格式内容清洗逻辑错误清洗异常值清洗缺失值清洗非需求数据清洗等内容。

数据清洗内容

a.格式内容清洗

时间、日期格式不一致清洗:根据实际情况,把时间/日期数据库转换成统一的表示方式。例如:日期格式不一致,2019-07-20、20190720、2019/07/20、20/07/2019;时间戳单位不一致,有的用秒表示,有的用毫秒表示;使用无效时间表示,时间戳使用0表示,结束时间戳使用FFFF表示。

数值格式不一致清洗:根据实际情况,把数值转换成统一的表示方式。例如:1、2.0、3.21E3、四等。

全半角等显示格式不一致清洗:这个问题在人工录入数据时比较容易出现。

内容中有不该存在的字符清洗:某些内容可能只包括一部分字符,比如身份证号是数字+字母,中国人姓名是汉字。最典型的就是头、尾、中间的空格,也可能出现姓名中存在数字符号、身份证号出现汉字等问题。

内容与该字段应有内容不符清洗:姓名写了性别,身份证号写了手机号等等,均属这种问题。但该问题特殊性在于:并不能简单的以删除来处理,因为成因有可能是人工填写错误,也有可能是前端没有校验,还有可能是导入数据时部分或全部存在列没有对齐的问题,因此要详细识别问题类型。

数据类型不符清洗:由于人为定义错误、转存、加载等原因,数据类型经常会出现数据类型不符的情况。例如,金额特征是字符串类型,实际上应该转换成int/float型。

b.逻辑错误清洗

重复数据清洗:存在各个特征值完全相同的两条/多条数据;数据不完全相同,但从业务角度看待数据是同一个数据。

不合理值清洗:根据业务常识,或者使用但不限于箱型图(Box-plot)发现数据中不合理的特征值。例如:年龄200岁;个人年收入100000万;

矛盾内容修正:有些字段是可以互相验证的,举例:身份证号是1101031980XXXXXXXX,然后年龄填18岁。在这种时候,需要根据字段的数据来源,来判定哪个字段提供的信息更为可靠,去除或重构不可靠的字段。

c.异常值清洗

异常值是数据分布的常态,处于特定分布区域或范围之外的数据通常被定义为异常或噪声。异常分为两种:“伪异常”,由于特定的业务运营动作产生,是正常反应业务的状态,而不是数据本身的异常;“真异常”,不是由于特定的业务运营动作产生,而是数据本身分布异常,即离群点。

异常值检查方法

基于统计分析:通常用户用某个统计分布对数据点进行建模,再以假定的模型,根据点的分布来确定是否异常。例如,如通过分析统计数据散度情况,即数据变异指标,来对数据的总体特征有更进一步的了解,对数据的分布情况有所了解,进而通过数据变异指标来发现数据中的异常点数据。常用的数据变异指标有极差、四分位数间距、均差、标准差、变异系数等,变异指标的值大表示差异大、散步广;值小表示离差小,较密集。

3σ原则:若数据服从正态分布,在3σ原则下,异常值为一组测定值中与平均值的偏差超过3倍标准差的值。距离平均值3σ之外的值出现的概率为

3σ原则

属于极个别的小概率事件。如果数据不服从正态分布,也可以用远离平均值的多少倍标准差来描述。

正态分布

箱式图分析:箱线图提供了识别异常值的一个标准,如果一个值满足

箱式图异常值判别准则

的值,则被称为异常值。其中,QL为下四分位数,表示全部观察值中有四分之一的数据取值比它小;QU为上四分位数,表示全部观察值中有四分之一的数据取值比它大;IQR为四分位数间距,是上四分位数QU与下四分位数QL的差值,包含了全部观察值的一半。箱型图判断异常值的方法以四分位数四分位距为基础,四分位数具有鲁棒性:25%的数据可以变得任意远并且不会干扰四分位数,所以异常值不能对这个标准施加影响。因此,箱型图识别异常值比较客观,在识别异常值时有一定的优越性

箱式图分布

基于模型检测:首先建立一个数据模型,异常是那些同模型不能完美拟合的对象;如果模型是簇的集合,则异常是不显著属于任何簇的对象。优点是,有坚实的统计学理论基础,当存在充分的数据和所用的检验类型的知识时,这些检验可能非常有效。缺点是,对于多元数据,可用的选择少一些,并且对于高维数据,这些检测可能性很差。

基于距离:基于距离的方法是基于下面这个假设,即若一个数据对象和大多数点距离都很远,那这个对象就是异常。通过定义对象之间的临近性度量,根据距离判断异常对象是否远离其他对象,主要使用的距离度量方法有绝对距离(曼哈顿距离)、欧氏距离和马氏距离等方法。优点是,基于距离的方法比基于统计类方法要简单得多,因为一个数据集合定义一个距离的度量要比确定数据集合的分布容易得多。缺点是,基于邻近度的方法需要O(m2)时间,大数据集不适用;该方法对参数的选择也是敏感的;不能处理具有不同密度区域的数据集,因为它使用全局阈值,不能考虑这种密度的变化。

基于密度:考察当前点周围密度,可以发现局部异常点,离群点的局部密度显著低于大部分近邻点,适用于非均匀的数据集。优点是,给出了对象是离群点的定量度量,并且即使数据具有不同的区域也能够很好的处理。缺点是,与基于距离的方法一样,这些方法必然具有O(m2)的时间复杂度,对于低维数据使用特定的数据结构可以达到O(mlogm);参数选择困难,虽然算法通过观察不同的k值,取得最大离群点得分来处理该问题,但是,仍然需要选择这些值的上下界。

基于聚类:对象是否被人为是异常点可能依赖于簇的个数(如k很大时的噪声簇)。该问题也没有简单的答案。一种策略是对于不同的簇个数重复该分析。另一种方法是找出大量小簇,其想法是:较小的簇倾向于更加凝聚;如果存在大量小簇时,一个对象是异常点,则它多半是一个真正的异常点,不利的一面是一组异常点可能形成小簇而逃避检测。优点是,基于线性和接近线性复杂度(k均值)的聚类技术来发现离群点可能是高度有效的;簇的定义通常是离群点的补,因此可能同时发现簇和离群点。缺点是,产生的离群点集和它们的得分可能非常依赖所用的簇的个数和数据中离群点的存在性;聚类算法产生的簇的质量对该算法产生的离群点的质量影响非常大。

在数据处理阶段将离群点作为影响数据质量的异常点考虑,而不是作为通常所说的异常检测目标点,因而楼主一般采用较为简单直观的方法,结合箱线图和MAD的统计方法判断变量的离群点。

异常值处理方法

对异常值处理,需要具体情况具体分析,异常值处理的常用方法有4种:

一是删除含有异常值的记录。某些筛选出来的异常样本是否真的是不需要的异常特征样本,最好找懂业务的再确认一下,防止我们将正常的样本过滤掉了。

二是将异常值视为缺失值,交给缺失值处理方法来处理。

三是使用均值/中位数/众数来修正。

四是不处理。

数据光滑处理

除了检测出异常值然后再处理异常值外,还可以使用以下方法对异常数据进行光滑处理。

分箱方法:通过考察数据的“近邻”(即周围的值)来光滑有序数据的值,有序值分布到一些“桶”或箱中。由于分箱方法考察近邻的值,因此进行局部光滑。一是用箱均值光滑,箱中每一个值被箱中的平均值替换。二是用箱中位数平滑,箱中的每一个值被箱中的中位数替换。三是用箱边界平滑,箱中的最大和最小值同样被视为边界,箱中的每一个值被最近的边界值替换。

分箱方法数据光滑处理

回归方法:可以用一个函数(如回归函数)拟合数据来光滑数据。线性回归涉及找出拟合两个属性(或变量)的“最佳”线,使得一个属性可以用来预测另一个。多元线性回归是线性回归的扩展,其中涉及的属性多于两个,并且数据拟合到一个多维曲面。

d.缺失值清洗

缺失值处理

缺失值产生的原因:

客观原因,比如数据存储的失败、存储器损坏、机械故障导致某段时间数据未能收集(对于定时数据采集而言)。

人为原因,由于人的主观失误(如:数据录入人员失误漏录了数据)、历史局限(如:数据在早期尚无记录)、有意隐瞒数据(如:在市场调查中被访人拒绝透露相关问题的答案,或者回答的问题是无效的)导致数据未能收集。

缺失值处理有3种方法:

一是直接使用含有缺失值的数据。某些算法可以直接使用含有缺失值的情况,如决策树算法可以直接使用含有缺失值的数据。优点是直接使用原始数据,排除了人工处理缺失值带来的信息损失。缺点是只有少量的算法支持这种方式。

二是删除含有缺失值的数据。优点是简单、高效。缺点是如果样本中的缺失值较少,则直接丢弃会损失大量的有效信息。这是对信息的极大浪费。

三是缺失值补全。用最可能的值来插补缺失值,这也是在实际工程中应用最广泛的技术,常见方法有:均值插补同类均值插补建模预测高维映射多重插补压缩感知及矩阵补全优点是保留了原始数据。缺点是计算复杂,而且当插补的值估计不准确时,会对后续的模型引入额外的误差。

均值插补和同类均值插补

均值插补:如果样本的属性是连续值,则该属性的缺失值就以该属性有效值的平均值来插补。如果样本的属性是离散值,则该属性的缺失值就以该属性有效值的众数(出现频率最高的值)来插补。

同类均值插补:首先,将样本进行分类;然后,以该类中的样本的均值来插补缺失值。

建模预测插补

思想是,将缺失的属性作为预测目标,通过建立模型来预测。给定数据集:

数据集

假设属性j含有缺失值,将数据集划分为:

根据缺失值有无划分数据集

将D1中的样本作为新的训练集,标签值重新定义为属性j的值,通过建模来完成属性j的学习。将D2中的样本作为测试集,通过学得的模型来预测其属性j的值。

这种方法的效果相对较好,但是该方法有个根本缺陷:如果其他属性和属性j无关,则预测的结果无意义。如果预测结果相当准确,则又说明属性j可以由其它属性计算得到,于是属性j信息冗余,没有必要纳入数据集中。

高维映射插补

思想是,将缺失的属性映射到高维空间。给定数据集,假设属性j的取值为离散值

K个离散值

一共K个离散值,则将该属性扩展为K+1个属性

扩展为K+1个属性

其中,若样本在属性j上的取值为ak,则样本在新的属性jk上的取值为1,在其他属性上的取值为0;若样本在属性j上缺失,则样本在新的属性jk+1上的取值为1,在其他属性上的取值为0。

对于连续特征,高维映射无法直接处理。可以在连续特征离散化之后,再进行高维映射。

高维映射是最精确的做法,它完全保留了所有的信息,也未增加任何额外的信息。比如广告CTR预估模型,预处理时会把所有变量都这样处理,达到几亿维。优点是,完整保留了原始数据的全部信息。缺点是,计算量大大提升。而且只有在样本量非常大的时候效果才好,否则会因为过于稀疏,效果很差。

多重插补

多重插补(Multiple Imputation: MI)认为待插补值是随机的,来自于已观测到的值。具体实践中,通常是估计出待插补值,然后再加上不同噪声,形成多组可选插补值。然后根据某种选择依据,选取最合适的插补值。

多重插补法的步骤:一是通过变量之间的关系对缺失数据进行预测,利用蒙特卡洛方法生成多个完整的数据集。二是在每个完整的数据集上进行训练,得到训练后的模型以及评价函数值。三是对来自各个完整的数据集的结果,根据评价函数值进行选择,选择评价函数值最大的模型,其对应的插值就是最终的插补值。

压缩感知及矩阵补全

在现实任务中,希望根据部分信息来恢复全部信息。压缩感知和矩阵补全就是用于完成这个任务。

主要思想
压缩感知方法
矩阵补全方法

2)数据标准化及归一化

数据一般都是有单位的,比如身高的单位有米、厘米等。需要对此类数值型特征进行无量纲化处理,即是使不同规格的数据转换到同一规格。常见的无量纲化方法有标准化归一化

a.数据标准化(Standardization)

为什么使用数据标准化?

一是某些算法要求样本具有0均值和1方差。

二是需要消除样本不同属性具有不同量级时的影响。例如,数量级的差异将导致量级较大的属性占据主导地位,从而与实际情况相悖(比如这时实际情况是值域范围小的特征更重要);当使用梯度下降法寻求最优解时,很有可能走“之字型”路线(垂直等高线走),从而导致需要迭代很多次才能收敛;依赖于样本距离的算法对于数据的数量级非常敏感。

数据标准化定义

数据标准化公式如下:

数据标准化公式

标准化的前提是特征值服从正态分布,标准化后,其转换成标准正态分布。均值和标准差都是在样本集上定义的,而不是在单个样本上定义的。标准化是针对某个属性的,需要用到所有样本在该属性上的值。

实现代码

from sklearn.preprocessing import StandardScaler

#标准化,返回值为标准化后的数据

standardScaler  = StandardScaler().fit(X_train)

standardScaler.transform(X_train)

b.数据归一化

MinMax归一化

区间缩放法利用了边界值信息,将属性缩放到[0,1]。计算公式如下:

MinMax归一化计算公式

这种方法有一个缺陷就是当有新数据加入时,可能导致max和min的变化,需要重新定义;另外,MinMaxScaler对异常值的存在非常敏感。

实现代码如下:

from sklearn.preprocessing import MinMaxScaler

#区间缩放,返回值为缩放到[0, 1]区间的数据

minMaxScaler  = MinMaxScaler().fit(X_train)

minMaxScaler.transform(X_train)

MaxAbs归一化

单独地缩放和转换每个特征,使得训练集中的每个特征的最大绝对值将为1.0,将属性缩放到[-1,1]。它不会移动/居中数据,因此不会破坏任何稀疏性。

MaxAbs归一化计算公式

c.标准化与归一化对比

标准化与归一化的异同

相同点:它们的相同点在于都能取消由于量纲不同引起的误差;都是一种线性变换,都是对向量X按照比例压缩再进行平移。

不同点:一是目的不同,归一化是为了消除纲量压缩到[0,1]区间;标准化只是调整特征整体的分布。二是归一化与最大,最小值有关;标准化与均值,标准差有关。三是归一化输出在[0,1]之间,标准化无限制。

什么时候用归一化?什么时候用标准化?

如果对输出结果范围有要求,用归一化。

如果数据较为稳定,不存在极端的最大最小值,用归一化。

如果数据存在异常值和较多噪音,用标准化,可以间接通过中心化避免异常值和极端值的影响。

归一化与标准化的应用场景

在分类、聚类算法中,需要使用距离来度量相似性的时候(如SVM、KNN)、或者使用PCA技术进行降维的时候,标准化(Z-score standardization)表现更好

在不涉及距离度量、协方差计算、数据不符合正太分布的时候,可以使用第一种方法或其他归一化方法。比如图像处理中,将RGB图像转换为灰度图像后将其值限定在[0, 255]的范围。

基于树的方法不需要进行特征的归一化。例如随机森林,bagging与boosting等方法。

基于参数的模型或者基于距离的模型需要归一化。因为基于参数的模型或者基于距离的模型,需要对参数或者距离进行计算,都需要进行归一化。

一般来说,建议优先使用标准化。对于输出有要求时再尝试别的方法,如归一化或者更加复杂的方法。很多方法都可以将输出范围调整到[0, 1],如果我们对于数据的分布有假设的话,更加有效的方法是使用相对应的概率密度函数来转换。

除了上面介绍的方法外,还有一些相对没这么常用的处理方法:RobustScalerPowerTransformerQuantileTransformerQuantileTransformer等。

3)分箱(Binning)

数据分箱(Binning)是一种数据预处理技术,用于减少轻微观察错误的影响。落入给定小间隔bin的原始数据值由代表该间隔的值(通常是中心值)代替。这是一种量化形式。 统计数据分箱是一种将多个或多或少连续值分组为较少数量的“分箱”的方法。例如,如果您有关于一组人的数据,您可能希望将他们的年龄安排到较小的年龄间隔。对于一些时间数据可以进行分箱操作,例如一天24小时可以分成早晨[5,8),上午[8,11),中午[11,14),下午[14,19),夜晚[10,22),深夜[19,24)和[24,5)。因为比如中午11点和12点其实没有很大区别,可以使用分箱技巧处理之后可以减少这些“误差”。

4)独热编码(One-Hot Encoding)

独热编码(One-Hot Encoding)是一种数据预处理技巧,它可以把类别数据变成长度相同的特征。例如,人的性别分成男女,每一个人的记录只有男或者女,那么我们可以创建一个维度为2的特征,如果是男,则用(1,0)表示,如果是女,则用(0,1)。即创建一个维度为类别总数的向量,把某个记录的值对应的维度记为1,其他记为0即可。对于类别不多的分类变量,可以采用独热编码。

5)特征哈希(Hashing Trick)

对于类别数量很多的分类变量可以采用特征哈希(Hashing Trick),特征哈希的目标就是将一个数据点转换成一个向量。利用的是哈希函数将原始数据转换成指定范围内的散列值,相比较独热模型具有很多优点,如支持在线学习,维度减小很多灯。具体参考数据特征处理之特征哈希(Feature Hashing)。

6)嵌套法(Embedding)

嵌套法(Embedding)是使用神经网络的方法将原始输入数据转换成新特征,嵌入实际上是根据您想要实现的任务将您的特征投影到更高维度的空间,因此在嵌入空间中,或多或少相似的特征在它们之间具有小的距离。 这允许分类器更好地以更全面的方式学习表示。例如,word embedding就是将单个单词映射成维度是几百维甚至几千维的向量,在进行文档分类等,原本具有语义相似性的单词映射之后的向量之间的距离也比较小,进而可以帮助我们进一步进行机器学习的应用,这一点比独热模型好很多。

7)取对数(Log Transformation)

取对数就是指对数值做log转换,可以将范围很大的数值转换成范围较小的区间中。Log转换对分布的形状有很大的影响,它通常用于减少右偏度,使得最终的分布形状更加对称一些。它不能应用于零值或负值。对数刻度上的一个单位表示乘以所用对数的乘数。在某些机器学习的模型中,对特征做对数转换可以将某些连乘变成求和,更加简单,这不属于这部分范围了。

如前所述,log转换可以将范围很大的值缩小在一定范围内,这对某些异常值的处理也很有效,例如用户查看的网页数量是一个长尾分布,一个用户在短时间内查看了500个和1000个页面都可能属于异常值,其行为可能差别也没那么大,那么使用log转换也能体现这种结果。

8)特征交互(Feature Interaction)

在回归模型中加入交互项是一种非常常见的处理方式。它可以极大的拓展回归模型对变量之间的依赖的解释。具体参见回归模型中的交互项简介(Interactions in Regression)。

3、特征构造

待完善。。。

4、特征提取

待完善。。。

5、特征选择

1)特征选择介绍

a.特征重要性分类

对于一个学习任务,给定属性集,其中某些属性可能对于学习来说是很关键的,但有些属性可能就意义不大。

一是相关特征。对当前学习任务有用的属性成为相关特征。

二是无关特征。对当前学习任务无用的属性称为无关特征。

三是冗余特征。不会对我们的算法带来新的信息,或者这种特征的信息可以由其他的特征推断出。

b.特征选择目的

从给定的特征集合中选出相关特征子集的过程称作特征选择(Feature Selection)。特征选择应获取尽可能小的相关特征子集,不显著降低分类精度、不影响分类分布以及特征子集应具有稳定、适应性强等特点。

特征选择可能会导致模型预测能力的降低。因为被剔除的特征中可能包含了有效的信息,抛弃了这部分信息会一定程度上降低预测准确率。这是计算复杂度和预测能力之间的折衷:如果保留尽可能多的特征,则模型的预测能力会有所提升,但是计算复杂度会上升。如果剔除尽可能多的特征,则模型的预测能力会有所下降,但是计算复杂度会下降。

2)特征选择方法

a.Filter方法(过滤式)

先进行特征选择,然后去训练学习器,特征选择过程与后续学习算法无关。相当于先对特征进行过滤操作,然后用特征子集来训练分类器。

主要思想是:对每一维特征“打分”,即给每一维的特征赋予权重,这样的权重就代表着该特征的重要性,然后依据权重排序。

主要方法有:Chi-squared test(卡方检验);Information gain(信息增益);Correlation coefficient scores(相关系数)。

主要优点是:运行速度快,是一种非常流行的特征选择方法。

主要缺点是:无法提供反馈。特征选择的标准/规范制定是在特征搜索算法中完成,学习算法无法给特征搜索算法传递对特征的需求。另外,可能处理某个特征时由于任意原因表示该特征不重要,但是该特征与其它特征结合起来则可能变得很重要。

b.Wrapper方法(包裹式)

直接把最后要使用的分类器作为特征选择的评价函数,对于特定的分类器选择最优的特征子集。

主要思想是:将子集的选择看作是一个搜索寻优问题,生成不同的组合,对组合进行评价,再与其他的组合进行比较。这样就将子集的选择看作是一个优化问题,这里有很多的优化算法可以解决,尤其是一些启发式的优化算法,如GA、PSO(如:优化算法-粒子群算法)、DE、ABC(如:优化算法-人工蜂群算法)等。

主要方法有:递归特征消除(Recursive Feature Elimination, RFE)算法。

主要优点是:对特征进行搜索时围绕学习算法展开的,对特征选择的标准/规范是在学习算法的需求中展开的,能够考虑学习算法所属的任意学习偏差,从而确定最佳子特征,真正关注的是学习问题本身。由于每次尝试针对特定子集时必须运行学习算法,所以能够关注到学习算法的学习偏差/归纳偏差,因此包裹式方法能够发挥巨大的作用。

主要缺点是:运行速度远慢于过滤算法,实际应用包裹式方法没有过滤方法流行。

c.Embedded方法(嵌入式)

将特征选择嵌入到模型训练中,其训练可能是相同模型,但是特征选择完成后,还能给予特征选择完成的特征和模型训练出的超参数,再次训练优化。

主要思想是:在模型既定情况下学习出对提高模型准确性最好的特征。也就是在确定模型的过程中,挑选出那些对模型的训练有重要意义的特征。

主要方法有:用带有L1的正则化项完成特征选择(也可以结合L2惩罚项来优化)、随机森林平均不纯度减少法、平均精确度减少法。

主要优点是:对特征进行搜索时围绕学习算法展开的,能够考虑学习算法所属的任意学习偏差。对训练模型的次数小于Wrapper方法,比较节省时间。

主要缺点是:运行速度慢。

3)代码实现——过滤式

a.Pearson相关系数

Pearson相关系数是一种最简单的,能帮助理解特征和响应变量之间关系的方法,该方法衡量变量之间的线性相关性。主要用于连续型特征的筛选,不适用于离散型特征的筛选。

优点是:相关系数计算速度快、易于计算,经常在拿到数据(经过清洗和特征提取之后的)之后第一时间就执行。Pearson相关系数能够表征丰富的关系,符合表示关系的正负,绝对值能够表示强度。

缺点是:相关系数作为特征排序机制,它只对线性关系敏感,如果关系是非线性的,即便两个变量具有一一对应的关系,相关系数也可能接近0。

代码实现如下:

import numpy as np

from scipy.stats import pearsonr

np.random.seed(2019)

size=1000

x = np.random.normal(0, 1, size)

# 计算两变量间的相关系数

print("Lower noise{}".format(pearsonr(x, x + np.random.normal(0, 1, size))))

print("Higher noise {}".format(pearsonr(x, x + np.random.normal(0, 10, size))))

b.最大信息系数(maximal information coefficient)

如果变量不是独立的,那么我们可以通过考察联合概率分布与边缘概率分布乘积之间的Kullback-Leibler散度来判断它们是否“接近”于相互独立。

代码实现如下:

x = np.random.normal(0,10,300)

z = x * x

pearsonr(x, z)

# 输出-0.1

from minepy import MINE

m = MINE()

m.compute_score(x, z)

print(m.mic())

# 输出1.0

c.距离相关系数(Distance correlation

距离相关系数是为了克服Pearson相关系数的弱点而生的。距离相关系数计算公式如下:

距离相关系数计算公式

代码实现如下:

from scipy.spatial.distance importpdist, squareform

import numpy as np

from numbapro import jit, float32

def distcorr(X, Y):

   X = np.atleast_1d(X)

   Y = np.atleast_1d(Y)

   if np.prod(X.shape) == len(X):

       X = X[:, None]

   if np.prod(Y.shape) == len(Y):

       Y = Y[:, None]

   X = np.atleast_2d(X)

   Y = np.atleast_2d(Y)

   n = X.shape[0]

   if Y.shape[0] != X.shape[0]:

       raise ValueError('Number of samples must match')

   a = squareform(pdist(X))

   b = squareform(pdist(Y))

   A = a - a.mean(axis=0)[None, :] - a.mean(axis=1)[:, None] + a.mean()

   B = b - b.mean(axis=0)[None, :] - b.mean(axis=1)[:, None] + b.mean()

   dcov2_xy = (A * B).sum()/float(n * n)

   dcov2_xx = (A * A).sum()/float(n * n)

   dcov2_yy = (B * B).sum()/float(n * n)

   dcor = np.sqrt(dcov2_xy)/np.sqrt(np.sqrt(dcov2_xx) * np.sqrt(dcov2_yy))

    return dcor

d.卡方检验

卡方检验是一种用途很广的计数资料的假设检验方法,由卡尔-皮尔逊提出。卡方值描述两个事件的独立性,或者描述实际观察值与期望值的偏离程度。

卡方值越大,说明两个变量越不可能是独立无关的,也就是说卡方值越大,两个变量的相关程度也越高。选择合适的阈值,大于阈值的特征留下,小于阈值的特征删除。这样筛选出一组特征子集就是输入模型训练的特征。只适用于分类问题中离散型特征筛选,不能用于分类问题中连续型特征的筛选,也不能用于回归问题的特征筛选

代码实现如下:

#导入sklearn库中的SelectKBest和chi2

from sklearn.feature_selection importSelectKBest ,chi2

#选择相关性最高的前5个特征

X_chi2 = SelectKBest(chi2,k=5).fit_transform(X, y)

X_chi2.shape

输出:(27, 5)

e.基于学习模型的特征排序(Model based ranking)

这种方法的思路是直接使用机器学习算法,针对每个单独的特征和响应变量建立预测模型。如果特征与响应变量之间的关系是非线性的,则有许多替代方案,例如基于树的方法(决策树和随机森林)、扩展的线性模型等。基于树的方法是最简单的方法之一,因为它们可以很好地模拟非线性关系,无需太多调整。但是要避免的主要是过度拟合,因此树的深度应该相对较小,并且应该应用交叉验证。

代码实现如下:

from sklearn.cross_validation import cross_val_score,ShuffleSplit

from sklearn.datasets importload_boston

from sklearn.ensemble importRandomForestRegressor

#Load boston housing dataset as anexample

boston = load_boston()

X = boston["data"]

Y = boston["target"]

names = boston["feature_names"]

rf =RandomForestRegressor(n_estimators=20, max_depth=4)

scores = []

# 使用每个特征单独训练模型,并获取每个模型的评分来作为特征选择的依据。

for i in range(X.shape[1]):

    score = cross_val_score(rf, X[:, i:i+1], Y, scoring="r2", cv=ShuffleSplit(len(X), 3, .3))

    scores.append((round(np.mean(score), 3), names[i]))

print(sorted(scores, reverse=True))

# 输出:[(0.636, 'LSTAT'), (0.59, 'RM'), (0.472, 'NOX'), (0.369,'INDUS'), (0.311, 'PTRATIO'), (0.24, 'TAX'),(0.24, 'CRIM'), (0.185, 'RAD'), (0.16, 'ZN'), (0.087, 'B'), (0.062, 'DIS'), (0.036, 'CHAS'), (0.027, 'AGE')]

4)代码实现——包裹式

a.线性模型与正则化

当所有特征在相同尺度上时,最重要的特征应该在模型中具有最高系数,而与输出变量不相关的特征应该具有接近零的系数值。即使使用简单的线性回归模型,当数据不是很嘈杂(或者有大量数据与特征数量相比),并且特征(相对)独立时,这种方法也能很好地工作。

b.随机森林选择

随机森林算法具有准确率高、鲁棒性好、易于使用等优点,这使得它成为了目前最流行的机器学习算法之一。随机森林提供了两种特征选择的方法:mean decrease impurity和mean decrease accuracy。

平均不纯度减少(mean decrease impurity)

工作原理如下:

一是随机森林由多颗CART决策树构成,决策树中的每一个节点都是关于某个特征的条件,为的是将数据集按照不同的响应变量一分为二。

二是CART利用不纯度可以确定节点(最优条件),对于分类问题,通常采用基尼不纯度;对于回归问日,通常采用的是方差或者最小二乘拟合。

三是当训练决策树的时候,可以计算出每个特征减少了多少树的不纯度。对于一个决策树森林来说,可以算出每个特征平均减少了多少不纯度,并把它平均减少的不纯度作为特征选择的标准。

四是随机森林基于不纯度的排序结果非常鲜明,在得分最高的几个特征之后的特征,得分急剧下降。

代码实现如下:

from sklearn.datasets importload_boston

from sklearn.ensemble importRandomForestRegressor

import numpy as np

#Load boston housing dataset as anexample

boston = load_boston()

X = boston["data"]

Y = boston["target"]

names =boston["feature_names"]

# 训练随机森林模型,并通过feature_importances_属性获取每个特征的重要性分数。

rf = RandomForestRegressor()

rf.fit(X, Y)

print("Features sorted by theirscore:")

print(sorted(zip(map(lambda x: round(x, 4), rf.feature_importances_), names), reverse=True))

平均精确度减少(mean decrease accuracy)

工作原理如下:

一是通过直接度量每个特征对模型精确率的影响来进行特征选择。

二是主要思路是打乱每个特征的特征值顺序,并且度量顺序变动对模型的精确率的影响。对于不重要的变量来说,打乱顺序对模型的精确率影响不会太大;对于重要的变量来说,打乱顺序就会降低模型的精确率。

代码实现如下:

from sklearn.cross_validation importShuffleSplit

from sklearn.metrics import r2_score

from collections import defaultdict

X = boston["data"]

Y = boston["target"]

rf = RandomForestRegressor()

scores = defaultdict(list)

#crossvalidate the scores on a numberof different random splits of the data

for train_idx, test_idx inShuffleSplit(len(X), 100, .3):

   X_train, X_test = X[train_idx], X[test_idx]

   Y_train, Y_test = Y[train_idx], Y[test_idx]

   #使用修改前的原始特征训练模型,其acc作为后续混洗特征值后的对比标准。

    r = rf.fit(X_train, Y_train)

    acc = r2_score(Y_test, rf.predict(X_test))

    #遍历每一列特征

   for i in range(X.shape[1]):

       X_t = X_test.copy()

       #对这一列特征进行混洗,交互了一列特征内部的值的顺序

       np.random.shuffle(X_t[:, i])

       shuff_acc = r2_score(Y_test, rf.predict(X_t))

       #混洗某个特征值后,计算平均精确度减少程度。

       scores[names[i]].append((acc-shuff_acc)/acc)

print("Features sorted by theirscore:")

print(sorted([(round(np.mean(score), 4), feat) for feat, score in scores.items()], reverse=True))

5)代码实现——嵌入式

a.稳定性选择(Stability Selection)

稳定性选择常常是一种既能够有助于理解数据,又能够挑选出优质特征的这种选择。

工作原理如下:

第一,稳定性选择是一种基于二次抽样和选择算法相结合较新的方法,选择算法可以是回归、SVM或其他类似的方法。

第二,它的主要思想是在不同的数据子集和特征子集上运行特征选择算法,不断的重复,最终汇总特征选择结果。比如可以统计某个特征被认为是重要特征的频率(被选为重要特征的次数除以它所在的子集被测试的次数)。

第三,理想情况下,重要特征的得分会接近100%。稍微弱一点的特征得分会是非0的数,而最无用的特征得分将会接近于0。

代码实现如下:

from sklearn.linear_model importRandomizedLasso

from sklearn.datasets importload_boston

boston = load_boston()

#using the Boston housing data.

#Data gets scaled automatically bysklearn's implementation

X = boston["data"]

Y = boston["target"]

names =boston["feature_names"]

rlasso = RandomizedLasso(alpha=0.025)

rlasso.fit(X, Y)

print("Features sorted by theirscore:")

print(sorted(zip(map(lambda x: round(x, 4), rlasso.scores_), names), reverse=True))

b.递归特征消除(Recursive Feature Elimination,RFE)

原理介绍如下:

第一,递归特征消除的主要思想是反复构建模型(如SVM或者回归模型),然后选出最好的(或者最差的)的特征(可以根据系数来选),把选出来的特征放到一边,然后在剩余的特征上重复这个过程,直到所有特征都遍历了。

第二,这个过程中特征被消除的次序就是特征的排序。因此,这是一种寻找最优特征子集的贪心算法。

第三,RFE的稳定性很大程度上取决于在迭代的时候底层用哪种模型。假如RFE采用的普通回归,没有经过正则化的回归是不稳定的,那么RFE就是不稳定的。假如RFE采用的是Ridge,而用Ridge正则化的回归是稳定的,那么RFE就是稳定的。

代码实现如下:

from sklearn.feature_selection import RFE

from sklearn.linear_model import LinearRegression

boston = load_boston()

X = boston["data"]

Y = boston["target"]

names =boston["feature_names"]

# use linear regression as the model

lr = LinearRegression()

# rank all features, i.e continue the elimination until the last one

rfe = RFE(lr, n_features_to_select=1)

rfe.fit(X,Y)

print("Features sorted by their rank:")

print(sorted(zip(map(lambda x: round(x,4), rfe.ranking_), names)))

结果输出:

Features sorted by their rank:

[(1, 'NOX'), (2, 'RM'), (3, 'CHAS'), (4, 'PTRATIO'), (5, 'DIS'),(6, 'LSTAT'), (7, 'RAD'), (8, 'CRIM'), (9, 'INDUS'), (10, 'ZN'),(11, 'TAX'), (12, 'B'), (13, 'AGE')]

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,711评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,932评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,770评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,799评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,697评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,069评论 1 276
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,535评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,200评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,353评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,290评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,331评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,020评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,610评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,694评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,927评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,330评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,904评论 2 341