从数据预处理到特征工程

来源:互联网 发布:ubuntu怎么安装php 编辑:程序博客网 时间:2024/06/11 15:21

参考链接

http://sanwen8.cn/p/5d9xyvY.html
http://www.cnblogs.com/jasonfreak/p/5448385.html

本文大纲

1)数据预处理
2)特征工程

数据预处理

我们通过一个简单的例子,来体会数据的预处理步骤:
这里写图片描述
首先我们观察原始数据,先对数据的类型按照不同的规则进行一个区分。
这里写图片描述
我们通过观察上表格,发现这时的特征可能有以下问题:

1)不属于同一量纲:即特征的规格不一样,不能够放在一起比较。无量纲化可以解决这一问题。2)信息冗余:对于某些定量特征,其包含的有效信息为区间划分,例如学习成绩,假若只关心“及格”或不“及格”,那么需要将定量的考分,转换成“1”和“0”表示及格和未及格。二值化可以解决这一问题。3)定性特征不能直接使用:某些机器学习算法和模型只能接受定量特征的输入,那么需要将定性特征转换为定量特征。最简单的方式是为每一种定性值指定一个定量值,但是这种方式过于灵活,增加了调参的工作。通常使用哑编码的方式将定性特征转换为定量特征:假设有N种定性值,则将这一个特征扩展为N种特征,当原始特征值为第i种定性值时,第i个扩展特征赋值为1,其他扩展特征赋值为0。哑编码的方式相比直接指定的方式,不用增加调参的工作,对于线性模型来说,使用哑编码后的特征可达到非线性的效果。4)存在缺失值:缺失值需要补充5)异常值检测6)信息利用率低:不同的机器学习算法和模型对数据中信息的利用是不同的,之前提到在线性模型中,使用对定性特征哑编码可以达到非线性的效果。类似地,对定量变量多项式化,或者进行其他的转换,都能达到非线性的效果。

  我们使用sklearn中的preproccessing库来进行数据预处理,可以覆盖以上问题的解决方案。

1)单变量分析
这一步,与其说是分析,其实就是先逐个对变量进行观察。对与连续的变量,或者标签的变量,我们采用不同的方式。
*连续变量
我们需要理解连续变量的中心趋势,还有变量的离散程度,看下图。
这里写图片描述
可视化单个变量,
这里写图片描述

单变量分析可以用来帮助解决缺失值,和异常值。后面我们讲到处理方法。
标签变量
对于标签变量我们要分析数据在每个维度上的分布情况,可以通过条形图展示。
这里写图片描述

2) 无量纲化

   无量纲化使不同规格的数据转换到同一规格。常见的无量纲化方法有标准化和区间缩放法。标准化的前提是特征值服从正态分布,标准化后,其转换成标准正态分布。区间缩放法利用了边界值信息,将特征的取值区间缩放到某个特点的范围,例如[0, 1]等。
2.1.1 标准化(standardization)

  
  
标准化需要计算特征的均值和标准差,公式表达为:
   这里写图片描述
使用preproccessing库的StandardScaler类对数据进行标准化的代码如下:

1 from sklearn.preprocessing import StandardScaler2 3 #标准化,返回值为标准化后的数据4 StandardScaler().fit_transform(iris.data)

2.1.2 区间缩放法(normalization)狭义上是指把最小值、最大值调整成0、1或-1、1

  区间缩放法的思路有多种,常见的一种为利用两个最值进行缩放,公式表达为:
  这里写图片描述

  使用preproccessing库的MinMaxScaler类对数据进行区间缩放的代码如下:
 

1 from sklearn.preprocessing import MinMaxScaler2 3 #区间缩放,返回值为缩放到[0, 1]区间的数据4 MinMaxScaler().fit_transform(iris.data)

2.2 对定量特征二值化

定量特征二值化的核心在于设定一个阈值,大于阈值的赋值为1,小于等于阈值的赋值为0,公式表达如下:

这里写图片描述
使用preproccessing库的Binarizer类对数据进行二值化的代码如下

1 from sklearn.preprocessing import Binarizer2 3 #二值化,阈值设置为3,返回值为二值化后的数据4 Binarizer(threshold=3).fit_transform(iris.data)

2.3 对定性特征哑编码

  由于IRIS数据集的特征皆为定量特征,故使用其目标值进行哑编码(实际上是不需要的)。使用preproccessing库的OneHotEncoder类对数据进行哑编码的代码如下:

  1 from sklearn.preprocessing import OneHotEncoder2 3 #哑编码,对IRIS数据集的目标值,返回值为哑编码后的数据4 OneHotEncoder().fit_transform(iris.target.reshape((-1,1)))

2.4 缺失值处理
这里写图片描述
造成数据集中存在缺失值的原因有一下几种,根据缺失值原因的不同,我们会采用不同的缺失值处理方法。
造成缺失值的原因:
(1)数据抽取时的缺失:
我们在从数据库或者文件中抽取数据时候的人工失误,这是一种比较好检测并处理的缺失值。
(2)数据采集阶段的缺失:

完全随机缺失
(missing completely at random,MCAR)指的是数据的缺失是随机的,数据的缺失不依赖于任何不完全变量或完全变量。
随机缺失
(missing at random,MAR)指的是数据的缺失不是完全随机的,即该类数据的缺失依赖于其他完全变量。举一个例子,我们发现女性在年龄上的缺失值要高于男性
完全非随机缺失
(missing not at random,MNAR)指的是数据的缺失依赖于不完全变量自身。

Which are the methods to treat missing values ?

1)删除!
这里写图片描述

一种是把存在缺失值的一个样本完全删掉。
第二中是把对应的缺失值删除。
在数据缺失是完全随机的情况下我们使用删除法。
2)中位数,平均数,众数填充。
一种是直接按列填充,
一种是把样本分类再按照列填充,比如对身高的缺失值,我们按照男女进行分类,然后在每一个类别上用各自的类别均值填补。
3)knn方法进行填补。
把一个样本看成一个向量,然后计算向量之间的距离,根据k个近邻进行缺失值的填补。

这里写图片描述

2.5 异常点检测。
这里写图片描述
异常点有两个:单变量,多变量。
单变量的异常点通过在单个变量的盒图上就能发现。但是出变量必须在多维空间。
看下图。
这里写图片描述

What causes Outliers?

1)人为因素
2)自然存在

这里写图片描述

通过上图可发现,均值和方差收到异常值的影响是很严重的。

How to detect Outliers?

Most commonly used method to detect outliers is visualization. We use various visualization methods, like Box-plot, Histogram, Scatter Plot (above, we have used box plot and scatter plot for visualization).

2特征工程

特征选择(Feature Selection,FS)和特征抽取(Feature Extraction, FE)是特征工程(Feature Engineering)的两个重要的方面。 他们之间最大的区别就是是否生成新的属性。 FS仅仅对特征进行排序(Ranking)和选择, FE更为复杂,需要重新认识事物, 挖掘新的角度, 创新性的创立新的属性(主成分分析,因子分子等等), 而目前深度学习这么火, 一个很重要的原因是缩减了特征提取的任务。 不过, 目前特征工程依然是各种机器学习应用领域的重要组成部分。
1.1特征选择与分类器性能的关系

一般说来,当固定一个分类器的话, 所选择的特征数量和分类器的效果之间会有一个曲线, 在某个x(1<=x<=n)的地方, 会达到最优。那么, 该怎么选这x个特征呢? 这是一个比较难的问题。 深度学习在图像,自然语言上的成功可以归因与,深度学习中的cnn,rnn等新的神经网络结构可以自动的提取特征,在一定意义上已经超出人工提取特征的能力。但是,这并不意味着我们传统特征工程方法将毫无价值。

这里写图片描述
1.2 为什么特征少了不行?

这个比较直观, 特征少了会导致无法区分的情况发生。 如下图所示,仅仅依赖x1或者x2特征, 都无法区分这两类数据, 所以当特征数量过小, 很可能导致数据重叠。进而, 所有分类器都会失效

这里写图片描述
1.3 为什么特征多了也不行?

 那为什么特征多了也不行呢? 如下图所示,明明根据纵轴来判断就可以容易的区分两类, 但是因为引入了横轴的特征, 使得同类数据在空间中距离变远,变稀疏了。 进而使得很多分类器失效。 所以, 特征不是越多越好!

这里写图片描述

特征工程概览

有这么一句话在业界广泛流传:数据和特征决定了机器学习的上限,而模型和算法只是逼近这个上限而已。那特征工程到底是什么呢?顾名思义,其本质是一项工程活动,目的是最大限度地从原始数据中提取特征以供算法和模型使用。通过总结和归纳,人们认为特征工程包括以下方面:

这里写图片描述

特征处理是特征工程的核心部分,sklearn提供了较为完整的特征处理方法,包括数据预处理,特征选择,降维等。首次接触到sklearn,通常会被其丰富且方便的算法模型库吸引,但是这里介绍的特征处理库也十分强大!

 当数据预处理完成后,我们需要选择有意义的特征输入机器学习的算法和模型进行训练。通常来说,从两个方面考虑来选择特征:

1)特征是否发散:如果一个特征不发散,例如方差接近于0,也就是说样本在这个特征上基本上没有差异,这个特征对于样本的区分并没有什么用。2)特征与目标的相关性:这点比较显见,与目标相关性高的特征,应当优选选择。除方差法外,本文介绍的其他方法均从相关性考虑。

特征选择的经典经验总结起来主要有三刀: 飞刀(Filter)弯刀(Wrapper)电刀(Embedded)。 类比起来:

1)Filter:过滤法,按照发散性或者相关性对各个特征进行评分,设定阈值或者待选择阈值的个数,选择特征。2)Wrapper:包装法,根据目标函数(通常是预测效果评分),每次选择若干特征,或者排除若干特征。3)Embedded:嵌入法,先使用某些机器学习的算法和模型进行训练,得到各个特征的权值系数,根据系数从大到小选择特征。类似于Filter方法,但是是通过训练来确定特征的优劣。

3.1 Filter(飞刀)
快速无比, 但是能不能打的准,还得看各自功力。

3.1.1 方差选择法
  

使用方差选择法,先要计算各个特征的方差,然后根据阈值,选择方差大于阈值的特征。使用feature_selection库的VarianceThreshold类来选择特征的代码如下:
1 from sklearn.feature_selection import VarianceThreshold2 3 #方差选择法,返回值为特征选择后的数据4 #参数threshold为方差的阈值5 VarianceThreshold(threshold=3).fit_transform(iris.data)

3.1.2 相关系数法

  使用相关系数法,先要计算各个特征对目标值的相关系数以及相关系数的P值。用feature_selection库的SelectKBest类结合相关系数来选择特征的代码如下:
  

1 from sklearn.feature_selection import SelectKBest2 from scipy.stats import pearsonr3 4 #选择K个最好的特征,返回选择特征后的数据5 #第一个参数为计算评估特征是否好的函数,该函数输入特征矩阵和目标向量,输出二元组(评分,P值)的数组,数组第i项为第i个特征的评分和P值。在此定义为计算相关系数6 #参数k为选择的特征个数7 SelectKBest(lambda X, Y: array(map(lambda x:pearsonr(x, Y), X.T)).T, k=2).fit_transform(iris.data, iris.target)

3.1.3 卡方检验
经典的卡方检验是检验定性自变量对定性因变量的相关性。但是在sklearn中对定量的数据依然可以使用k方检验。

1 from sklearn.feature_selection import SelectKBest2 from sklearn.feature_selection import chi23 4 #选择K个最好的特征,返回选择特征后的数据5 SelectKBest(chi2, k=2).fit_transform(iris.data, iris.target)

3.1.4 互信息法

  经典的互信息也是评价定性自变量对定性因变量的相关性的,互信息计算公式如下:
  

复制代码 1 from sklearn.feature_selection import SelectKBest 2 from minepy import MINE 3  4 #由于MINE的设计不是函数式的,定义mic方法将其为函数式的,返回一个二元组,二元组的第2项设置成固定的P值0.5 5 def mic(x, y): 6     m = MINE() 7     m.compute_score(x, y) 8     return (m.mic(), 0.5) 9 10 #选择K个最好的特征,返回特征选择后的数据11 SelectKBest(lambda X, Y: array(map(lambda x:mic(x, Y), X.T)).T, k=2).fit_transform(iris.data, iris.target)复制代码

上面说到的这些方法,除了方差阀值法之外,都可以看作是对自变量和因变量之间的相关性评分。
对于分类和回归问题,我们使用不同的评分方法。

回归问题:f_regression, mutual_info_regression
分类问题:chi2, f_classif, mutual_info_classif
基于F-test的方法估计两个变量之间的线性依赖性,而互信息可以捕捉两个变量之间任意的统计依赖性,但是互信息是非参数的方法,未了精确的估计它需要更多的估计。
如果数据是稀疏的,我们可以使用如下方法:
chi2, mutual_info_regression, mutual_info_classif
例子一:
F-test 和互信息进行特征选择的区别。
这里写图片描述
我们一共有x1,x2,x3三个变量,而我们的y函数是y = x_1 + sin(6 * pi * x_2) + 0.1 * N(0, 1),我们会发现x3和y没相关性质,而x1和y是线性性质,X2和y是非线性性质,所以f-test会认为x1是最重要的,而互信息认为x2是不重的,而x3在哪个分数上得分都是0。
链接:

http://scikit-learn.org/stable/auto_examples/feature_selection/plot_f_test_vs_mi.html#sphx-glr-auto-examples-feature-selection-plot-f-test-vs-mi-py
例二:第二例子将会展示,怎么把点变量的特征选择通过pipeline使用到svm上,进而提高svm的得分。
http://scikit-learn.org/stable/auto_examples/svm/plot_svm_anova.html#sphx-glr-auto-examples-svm-plot-svm-anova-py

3.2 Wrapper
3.2.1 递归特征消除法

  递归消除特征法使用一个基模型来进行多轮训练,每轮训练后,消除若干权值系数的特征,再基于新的特征集进行下一轮训练。使用feature_selection库的RFE类来选择特征的代码如下:

1 from sklearn.feature_selection import RFE2 from sklearn.linear_model import LogisticRegression3 4 #递归特征消除法,返回特征选择后的数据5 #参数estimator为基模型6 #参数n_features_to_select为选择的特征个数7 RFE(estimator=LogisticRegression(), n_features_to_select=2).fit_transform(iris.data, iris.target)

例子:
http://scikit-learn.org/stable/auto_examples/feature_selection/plot_rfe_with_cross_validation.html#sphx-glr-auto-examples-feature-selection-plot-rfe-with-cross-validation-py
这里写图片描述

通过基本预测器特征数据集山进行交叉验证,然后选择合适合适的特征个数,从上图可以看出,特征多未必能够提高精确率。

3.2.2用SelectFromMode
a coef_ or feature_importances_ attribute after fitting.

0 0
原创粉丝点击