【机器学习应用】预处理与特征工程
✨ 个人主页:在线OJ的阿川
💖文章专栏:机器学习应用入门到进阶
🌏代码仓库:GitHub平台
写在开头
现在您看到的是我的结论或想法,但在这背后凝结了大量的思考、经验和讨论
本文大致思维框架简图:
目录
- 1.相关库
- 2.数据预处理
- 3.特征工程
- 4.百闻不如一见
1.相关库
相关库:Numpy、Pandas、Scikit-learn(sklearn)
- 其中Scikit-learn库
是主流的机器学习库,包含市面上主流的机器学习算法,即分类、回归、聚类、降维、模型选择、数据预处理。
2.数据预处理
数据预处理是从数据中检测,纠正或删除损坏不准确或不适用于模型的记录的过程。
数据预处理的目的是让数据适应模型,匹配模型的需求
2.1 无量纲化处理
1.无量纲化处理是将不同规格的数据转化成同一规格,或者将不同分布的数据转化成某个特定分布的需求。
2.无量纲化处理主要包括中心化(Zero-centered)和缩放处理(Scale)。
-
中心化和缩放:
1.中心化的本质是让所有记录减去一个固定值,让数据样本平移到某个位置。
2.缩放处理的本质是通过除以一个固定值,将数据固定在某个范围之中,特别注意取对数也算作一种缩放处理。 -
无量纲化方法:
1.数据归一化处理(Normalization)是无量纲化处理中常用的一种方式,归一化处理之后的数据服从正态分布,数值范围在[-1~1]。
sklearn.preprocessing.MinMaxScaler可以实现数据归一化这个功能,其中feature_range可以实现将数据归一化到什么范围中。具体归一化公式如下图所示:
2.数据标准化(Standardization)也是无量纲化中常见的一种方式。数据标准化之后的数据会服从均值为0,方差为1的正态分布。
sklearn.preprocessing.StandardScaler可以实现数据标准化这个功能。具体公式如下:
-
注意:
1.不管是数据归一化还是标准化,都需要原始数据为二维数据。
2.大多数机器学习算法中,例如PCA、聚类、逻辑回归、支持向量机、神经网络,这些算法中StandardScaler往往是最好选择。
3.在不涉及距离度量、梯度、协方差计算以及数据需要被压缩到特定区间时,MinMaxScaler往往是最好选择。
4.除了数据标准化和归一化等常见无量纲化处理方式之外,还有一些其他的无量纲化处理方式:
希望压缩数据却不影响数据的稀疏性时,会使用MaxAbsScaler方式
异常值多,噪声非常大时会选分位数来进行无量纲化,即RobustScaler方式
具体可见下图所示:
2.2 缺失值填补
在sklearn当中有一个填补缺失值的impute.simpleImput类
其中missing_values参数
- 明确数据中缺失值为什么值,默认空值nan
其中strategy参数
- 为填补缺失值的策略,默认均值mean。可选参数值有median(中值)、most_frequent(众数)、constant(自选值)搭配fill_value参数中的值
其中fill_value参数
- 当参数strategy为constant时候可用,可输入字符串和数字表示要填充的值
其中copy参数
- 默认为true,将创建特征矩阵的副本,否则缺失值填补将填补到原本的特征矩阵中。
具体可见下图:
2.3 处理特征
特征值中包括文字型和数值型。
其中文字型又包括分类型特征、连续型特征等等,但在大多数算法中,如逻辑回归、支持向量机(SVM)、k近邻算法都只能处理数值型数据,不能处理文字,且在fit的时候全部要求输入数组或矩阵,即数值型特征。
所以往往在预处理阶段,需要将文字型特征转化成数值型特征。
- 处理分类型特征:编码
将分类型数据转换成数值型,往往进行编码处理。常见的编码类有:
1.LabelEncoder类
标签专用,能够将分类转换为分类数值。
重要属性:
classes_属性可以查看标签中究竟有多少类别
2.OrdinalEncoder类
特征专用,能够将分类特征转化成分类数值。若特征间存在关系,但不能通过数学计算互相转换,也可以使用该编码方式。
举个例子:学历特征,特征值有小学、初中、高中,它们之间有相互联系,但是在进行编码之后,不能通过数学计算互相转换。
重要属性:
categories_属性可以查看每个特征中的类别
3.OneHotEncoder类
独热编码,创建哑变量。因为有些特征是相互独立的,彼此之间没有完全联系,若无脑的进行编码,则会出现计算错误。
举个例子:舱门特征,该特征值有A、B、C,它们彼此之间相互独立,无联系,若简单的用1、2、3来进行编码,后续操作中可能错误的当做数学来计算转换。但由于无关系,相互独立,这些数值不能通过数学计算互相转化。
重要属性:
categories_属性可以查看每个特征中的类别
具体如下所示:
- 处理连续性特征:二值化与分段
将连续行特征转化成数值型特征往往使用二值化与分段,二值化,即将特征值设置为0或者1,一般大于阈值的值映射为1,小于或等于阈值的值设为0。二值化的类为Binarizer。分段,即是将连续型变量排序后按顺序分箱后编码。分段的类有KBinsDiscretizer。
1.KBinsDiscretizer类
其中n_bins参数为每个特征中分箱的个数,默认为5。
其中encode参数为编码的方式。"onehot"为默认值,即每一列是一个特征中的一个类别,含有该类别的样本表示为1,不含的表示为0,"ordinal"方式为每个特征的每个箱都被编码为一个整数,返回每一列是一个特征,每个特征下含有不同整数编码的相的矩阵。
其中strategy参数为定义箱宽的方式。"uniform"表示等宽分箱,即每个特征中的每个箱的最大值之间的差值再除以分项的个数,"quantile"表示等位分箱,为默认值,即每个箱内的样本数量都相同,"kmeans"表示按聚类分箱,即每个箱中的值到最近的一维k均值聚类的簇心的距离都相同。
具体如下图所示:
3.特征工程
特征工程是将原始数据转化为更能代表预测模型的潜在问题的特征的过程。
特征工程的目的是降低计算成本,提高模型上限。
特征工程包括三部分,分别为特征提取、特征创造、特征选择,具体如下图所示:
其中最重要的为特征选择,而在做特征选择之前,需要详细的分析原始数据的含义,若能联系到数据提供者,可以和Ta谈一谈。
3.1.特征选择常见四种方式:
1.过滤法
2.嵌入法
3.包裹法
4.数据降维
3.2.过滤法
过滤方法通常用于预处理步骤,通常根据各种统计检验中的分数以及相关性的各项指标来选择特征。
方差过滤(VarianceThreshold类)
因为一个特征本身的方差很小就表示样本在这个特征上基本没有什么差异,这个特征对样本区分没有什么作用,所以我们可以通过特征本身的方差来筛选特征的类。
VarianceThreshold类有个参数threshold表示方差的阈值,表示舍弃所有方差小于threshold的特征。
但由于不知道方差过滤掉的是噪音还是有效特征,所以说只能自己去尝试,先用阈值为0或者阈值很小的方差来过滤。
若发现过滤掉之后,模型稳定性反而有所下降,说明过滤掉了有效特征,此时就放弃使用方差过滤,而选择其他的特征方法来削减特征数量。
方差过滤能大幅度缩短:最近邻算法KNN、单棵决策树、支持向量机、神经网络、回归算法等需要遍历特征或升维来进行运算的算法的时间。但对不需要遍历特征的算法,例如随机森林等,方差过滤对它来说效果平平。
相关性过滤(feature_selection类)
相关性过滤可以选出与标签相关且有意义的特征,若选择的特征与标签无关,只会白白浪费计算内存以及给模型带来噪音。
常见三种方法评判特征与标签之间的相关性:
1.卡方过滤
2.F检验
3.互信息
卡方过滤
卡方过滤是专门针对分类型数据进行的相关性过滤。
其中卡方值越大,说明相关性越高
而feature_selection.chi2计算每个非负特征和标签之间的卡方统计量,并按照卡方统计量由高到低进行排名特征。
而feature_selection.SelectKBest可以输入评分标准,来选出前k个分数最高特征的特征。
若某些特征的卡方统计量值相同,则会使用方差先进行方差过滤。当进行了卡方过滤之后,若模型的效果降低,则说明需要放弃相关性过滤。
卡方检验本质是推测两组数据之间的差异,卡方检验会返回卡方值和P值两个统计量,虽然卡方过滤中会使用卡方值来进行排名筛选,但保留多少个特征的边界值,往往是由P值来决定,对于P值一般使用0.01或0.05作为显著性水平。当p值小于等于0.05或0.01时,两组数据是相关的;大于0.05或0.01时,两组数据是相互独立的。
具体如下图所示:
所以希望选取到的特征的卡方值很大,P值小于0.05,这样的特征是和标签特别相关联的。
F检验
F检验是用来捕捉每个特征与标签之间的线性关系的过滤方法,特别适用于服从正态分布的数据。
F检验包含f_classif(F检验分类)、f_regression(F检验回归)。
f_classif(F检验分类)用于标签是分类型变量的数据。f_regression(F检验回归)用于标签是连续型变量的数据。
F检验,本质是寻找两组数据之间的线性关系,会返回F值和P值两个统计量。F值越大说明特征越显著,P值小于0.05或0.01的特征,说明特征与标签显著线性相关。
互信息
互信息是用来捕捉每个特征与标签之间的任意关系(包括线性和非线性)的过滤方法。
互信息包括mutual_info_classif(互信息分类)、mutual_info_regression(互信息回归)。mutual_info_classif(互信息分类)适用于分类型标签。mutual_info_regression(互信息回归)适用于连续性标签。
互信息返回每个特征与目标之间的互信息量的估计。若返回的互信息量估计大于0,说明所有特征都与标签相关。
总结
根据经验来说,一般都是先使用方差过滤,然后使用互信息法来捕捉相关性进行辅助过滤。当然具体情况以实际为主。过滤方法总结如下图所示:
一些数据类型以及常用的统计量,如下图所示:
3.2.嵌入法
嵌入法是让算法自己决定使用哪些特征的方法。
先使用算法进行训练,得到各个特征的权值系数,根据权值系数从大到小选择特征,因为权值系数代表特征对于模型的贡献/重要性,所以相对于过滤法,嵌入法的结果会更加精确到模型的效用本身。具体如下图所示:
但是模型权值系数的边界选取一般是通过学习曲线来判断,所以说计算时间可能偏大,且由于引入了算法来挑选特征,则一些计算缓慢的算法也会导致嵌入法非常耗时间。
SelectFromModel类
SelectFromModel是一个元变换器
可以与任何具有coef_(例如逻辑回归模型就具有该参数)、feature_importances(例如随机森林和决策树模型就具有该属性)属性或参数的算法的评估器一起使用。
尤其对于有这个feature_importances的模型来说,若重要性低于提供的阈值参数,则认为这些特征不重要被移除,所以阈值的确定往往通过学习曲线来选择。具体参数解释如下:
3.3.包装法
包装法也是通过算法来选择特征。
但该算法是专门的用来选择特征的数据挖掘算法(RFE,是一种贪婪的优化算法),该算法的核心功能就是选取最佳特征子集。
它在初始特征集上训练评估器,然后通过coef_属性或者feature_importances_属性来获得每个特征的重要性,然后从当前的一种特征中修剪最不重要的特征,在修剪的集合上递归的重复该过程,直到最终达到所需数量要选择的特征为止,所以缺点是计算成本较高。
RFE类
其中参数estimator是需要填写实例化后的评估器
其中参数n_features_to_select是想要选择的特征个数(该参数一般通过学习曲线的方式来确定)
其中参数step表示每次迭代中希望移除的特征个数。
support属性是返回所有的特征是否最后被选中的布尔矩阵
ranking属性返回特征的按数次迭代中综合重要性的排名。
3.4.特征选择总结
1.一般来说过滤法更快速,但更粗糙,包装法和嵌入法更精确,比较适合具体到算法去调整,但计算量比较大,运行时间长。
2.所以当数据量很大的时候,优先使用方差过滤和互信息法调整,再加上其他的特征选择方法(例如包装法和嵌入法)。
3.但使用逻辑回归时,优先使用嵌入法,使用支持向量机时优先使用包装法。
4.百闻不如一见
- 1.我已经将相关的练习代码放入了GitHub和csdn资源中,有需要自取哈(若无,则说明过几天上传)。
- 2.相关练习代码主要包括数据预处理和特征选择的有关操作的练习。
5. 夹带私货
若你能看到看到这篇文章且能看到这,则说明你我有缘,留个关注吧,后面还会接着计算机408、底层原理、开源项目、以及数据、后端研发相关、实习、笔试/面试、秋招/春招、各种竞赛相关、简历相关、考研、学术相关……,祝你我变得更强
好的,到此为止啦,祝您变得更强
道阻且长 行则将至 |
---|
个人主页:在线OJ的阿川大佬的支持和鼓励,将是我成长路上最大的动力 |