机器学习中的一些特征提取流程与方法分析

概述:

文章旨在研究利用机器学习方法,在数据预测、分析模型建立过程中,对数据特征提取方法与流程的简单总结分析。主要指出常用的简单提取方法的基本原理与使用该方法的一些注意事项。文章使用示例代码均为Python代码。

故文章主要工作是对已有简单提取方法的概括,并用一些个人理解,使用尽量通俗的语言作归类分析与总结

​ 由于机器学习相关均为自学,在一年不到的学习过程中,知识点学得较零散,可能在系统性、细节点与应用层面上存在偏差,欢迎指正和讨论。

前述

​ 对于一般地一个数据预测、分析工作中,个人总结有以下流程:

(1)确认分析目标;

(2)搜集、清洗数据:包括获取信息、提取有效数据、使得数据变为合适的数据格式;

(3)数据预处理:包括制作数据标签、计算二级数据、处理缺失值、异常值,描述性统计、文本变量处理;

(4)特征处理:包括特征提取、特征的表示方法(例如引入虚拟变量)等;

(5)模型建立:包括选择基本学习算法建模(即选择本次建模的底层模型原理);

(6)模型检验与优化:包括对模型假设的检验和参数设置(例如剪枝等)与利用其他算法提升模型(例如利用集成算法的bagging和boosting等);

(7)可视化与汇报:包括成果的可视化与分析结果的汇报、模型问题和优化方向的总结。

​ 在以上流程中,围绕文章主题,对于步骤(4)中的特征提取,提出以下三个问题:

1.特征提取是什么?

2.为什么要特征提取?

3.如何特征提取?

接下来,本文依次回答三个问题。

一、特征提取是什么?

​ 特征提取,经过个人资料搜寻,说法混乱不一,个人作出如下总结:

​ 总之,顾名思义,就是减少自变量的个数。个人理解为一种提纯,或者个人称之为特征提纯、信息提纯。即通过一定方法,集中提取各自变量对因变量的解释能力,剔除特征空间中解释能力差的部分。

​ 特征提取主要有两种思路,一为特征选择、二为特征降维

​ 特征选择的方法是从我们原本的数据集中,选出若干特征作为我们模型建立的自变量,也就是选择出原本特征的子集,原特征空间不变。

​ 特征降维的方法则会改变原本的特征空间,依据一些函数关系,对原特征重新映射,将数据特征投影后,使得信息更加集中,于是我们便可以选择更低的维度来解释整个特征集的信息。利用这个方法后,原特征空间改变。

​ 最后,个人观点,按提取主体来分,可分为人工提取算法提取

二.为什么要特征提取?

​ 角度一,从分析解决问题的实际需求出发。

​ 我们既然要分析处理问题,那自然希望抓住问题的主要矛盾,把主要精力拿去解决主要问题。而特征提取,便能帮助我们将特征提纯,筛去多余、重复的信息,让我们更加清楚地发现,到底是哪些变量在影响我们研究的因变量,从而抓住问题本质,提高我们在处理实际问题中的精准度,为高层决策提供更加明确的方向,节省调查多余信息的人力物力财力。

​ 从这个角度,其实我们也能发现,特征提取其实也是在整个数据分析流程中非常重要的一步,是整个数据分析汇报流程的方向标。可以说,当我们从搜集的信息中提取出关键信息后,我们至此为止的工作已经具有一定的价值,**这意味着我们已经可以告诉决策者处理问题的出发点。**而接下来的模型建立分析工作主要也是在我们确立特征的基础上,分析所提取的特征与因变量究竟是何种关系,从而告诉决策者,在这些方向上,应该如何着手,最终解决问题。

​ 角度二,从算法的计算复杂度和模型的稳定性出发。

​ 首先,我们可以确定,特征数是不能太少的,就像处理问题不能光听一个人的一面之词,过少的特征会影响模型预测的准确度,即提高估计的有偏性。那么特征是不是就是越多越好呢?答案是否定的。

​ 从“维数灾难”的观点来看,随着维数的增加,向量计算的计算量呈指数倍增长,故算法的计算复杂度也会大幅上升。

​ 同时,维数增多也会带来高维空间数据的稀疏化,影响模型的预测能力。下面举一个认为比较好的例子来解释这样的稀疏化表现:(以下距离均定义为欧氏距离)

​ 当维度 d = 1 d=1 d=1,假设我们在 [ 0 , 1 ] [0,1] [0,1]直线上按均匀分布N个样本点,那么两点之间的平均距离为 1 N \frac{1}{N} N1

​ 当维度 d = 2 d=2 d=2,假设我们在边长为1的正方形内按均匀分布N个样本点,那么两点之间的平均距离此时为 1 N \sqrt{\frac{1}{N}} N1 ,距离变大,而我们若想恢复成1中的平均距离,此时则需要 N 2 N^2 N2个点。

​ 故当维度 d = p d=p d=p,我们在一单位中均匀分布N个样本点,则平均距离为 N − 1 p N^{-\frac{1}{p}} Np1,恢复为1中距离需要 N p N^p Np个样本点。我们考察平均距离会发现,当p越大,平均距离也会随之变大,并且趋向于1,即撑满整个1单位的空间。换句话讲,维度越高,相同数量的样本点分布将会越稀疏,并逐渐趋向整个样本空间的边缘。

​ 因为数据的样本点在高维非常分散,这也将导致数据集离散程度增加,即方差的增加,并且无论是参数估计的方差,还是模型残差的方差和预测结果的方差,都会随着维度增加而增加。若不对应地以指数级方式增加数据样本,就容易导致模型拟合时发生过拟合,模型稳定性降低,预测能力变差。

三、如何特征提取?

​ 首先,特征提取在思路上,个人人为主要考察两点。

​ 第一点相关程度。无论是因变量与自变量,抑或是自变量之间,我们首先会考虑利用相关程度来筛选变量,这个理由十分符合实际经验,相关程度越高,代表变量之间联系越大,筛选特征中一定少不了对相关程度的考虑。

​ 第二点模型选择。在具备相关性的同时,我们往往也希望所选特征能比较好地符合模型算法的假设,发挥模型的最大性能,因此我们在筛选特征时也会利用交叉验证的方式来依据模型筛选特征,依此来提高模型的分析、预测性能。

​ 下面说明具体的流程和一些简单提取方法,并对每个方法做些简明扼要的介绍,对部分方法附加些简单示例。

​ 这里要指出,特征提取的方法就目前个人查阅资料的情况来看,并不存在什么固定流程。且不同问题、不同模型,也有更为精细针对化的特征提取方法与技术,特征提取技术本身也在不断发展,有诸多的算法和学术理论研究,同时主要受限于我个人的水平,故本段只能尽量做到一些已有的、常用的、基本的方法和基本流程的概括介绍。

​ 个人总结特征提取基本流程如下:

第一步,数据预处理过程

​ 这一步个人也将其理解为人工提取,思路上属于特征选择。特征提取的第一步往往在数据预处理过程中便有涉及,这一步同时也十分考察个人的相关业务能力,本文将其分为以下几小步:

​ 1.根据个人有关的业务理解,在理解每个特征的含义、来源、性质的基础上,首先对特征按个人理解进行初步筛选。

​ 2.单变量分析,考察该特征本身的数据特征,比如对于缺失值个数较多的特征、PSI(特征稳定性)较低的特征,或者是对于集中程度较高,即方差相对较低的特征等,我们都可以删除。

​ 3.双变量分析,考察每个特征与因变量的相关性,对于回归问题可以绘制散点图,对于分类问题可以绘制频数图,以此删去与因变量明显不相关的特征。

​ 4.多变量分析,考察特征内部是否具有相关性,可以利用Pearson相关矩阵、Spearman相关矩阵绘制热图等可视化方法,以此删除相关性高的特征降低信息重复度。

第二步,算法提取过程

​ 这一步开始,特征提取流程便已经不再固定,对于不同的模型,我们可以选择不同的算法来提取特征,对于相同的模型,不同的提取算法也可能有不同的效果,这需要我们在学习、理解不同的提取算法后进行综合的分析和对比。

​ 对于算法提取过程,接下来按前文分为“特征选择”和“特征降维“两种思路来介绍一些算法。

一、特征选择

​ 先介绍特征选择算法的一般逻辑:

​ 首先按一定逻辑算法搜集并生成特征子集。然后会使用一个评价函数来给这个子集一个数值评定,例如在线性回归中,经常使用的F值。当我们所设置的数值评定达到阈值,也就是我们所设置的标准后,则停止子集的搜索。最后在验证集上测试我们所选择子集的有效性。

​ 其中, 当特征集维数较高时,子集搜索复杂度将上升,这方面尚未有比较好的应用理论以高效处理高维特征子集的搜索。

​ 接下来按特征选择的分类介绍几个特征选择算法,我们按形式可分为三大类:过滤法、包装法、嵌入法。

1.Filter(过滤法):

​ 按照特征的相关性或集中趋势等信息对每个特征逐个进行评分,然后通过设定阈值或特征的个数筛选特征。该方法的原理类似于人工筛选变量中的单、双、多变量分析,无非是在描述相关性时,使用了不同的统计方法。

描述相关程度来筛选特征是一种非常自然也有效的方法,因此有许多的筛选算法均可以归类为过滤法。当然,我们在进行特征筛选中,运用过滤法筛选,也可以说是必经的一步

​ 这里仅介绍3种过滤方法:

a.卡方检验

​ 该方法原理上属于非参数统计中的相关性检验,数理统计教材中也称之为列联表检验。主要用于检验两个分类变量的相关性,属于双变量检验法。卡方检验的原假设为两变量独立,我们假设样本总数为 N N N,自变量为 X X X,因变量为 Y Y Y,定义 E i E_i Ei为自变量取值为 X i X_i Xi样本频数和, E j E_j Ej为自变量取值为 Y j Y_j Yj样本频数和,下面构造卡方统计量:
χ 2 = ∑ ( A − E ) 2 E \chi^2=\sum\frac{(A-E)^2}{E} χ2=E(AE)2
其中, A A A ( X i , Y j ) (X_i,Y_j) (Xi,Yj)的出现频数, E = E i ∗ E j N E=\frac{E_i*E_j}{N} E=NEiEj。该统计量服从一个自由度为 N − 1 N-1 N1的卡方分布,假设置信度为 α \alpha α,可以依据其分布计算出其分位点,随后与分位点做比较来检验假设。或者依照其分布计算事件发生的概率,也就是 p p p值,将其与置信度比较后来检验两变量是否独立。我们通常使用 p p p值来刻画相关性程度, p p p值越低,说明两变量独立的概率越低,即相关性越显著。

代码实例:

from sklearn.datasets import load_iris
from sklearn.feature_selection import SelectKBest#导入sklearn中的SelectKBest
from sklearn.feature_selection import chi2
iris = load_iris()
X, y = iris.data, iris.target  #iris数据集

#参数k为选择特征数
X_chi= SelectKBest(chi2, k=2).fit_transform(X, y)
b.互信息和最大信息系数 Mutual information and maximal information coefficient (MIC)

​ 在过滤法中,我们重点介绍该方法。因为该方法适用性较广且稳定性较高

​ 首先介绍互信息的概念,类似于相关系数、卡方统计量等概念,互信息本身也可以理解为一种描述分类变量之间相关性的统计量。假设存在两个分类随机变量 X , Y X,Y X,Y,则互信息的计算公式为:
I ( x , y ) = ∑ X ∑ Y p ( x , y ) log ⁡ p ( x , y ) p ( x ) p ( y ) I(x,y)=\sum_X\sum_Yp(x,y)\log \frac{p(x,y)}{p(x)p(y)} I(x,y)=XYp(x,y)logp(x)p(y)p(x,y)
我们可以发现,互信息的公式和熵的公式非常类似,其可以通过数学变化,转换为如下利用熵表现的形式:
I ( x , y ) = H ( Y ) − H ( Y ∣ X ) = H ( X ) − H ( X ∣ Y ) I(x,y)=H(Y)-H(Y|X)=H(X)-H(X|Y) I(x,y)=H(Y)H(YX)=H(X)H(XY)
证明过程此处省略。

​ 通过以上表示,我们可以发现互信息对于两个变量 X , Y X,Y X,Y具有对称性。而两个变量的相关性越强,对应的互信息值也会越高,比如当我们取两个相同的变量 X , X X,X X,X,此时 H ( X ∣ X ) = 0 H(X|X)=0 H(XX)=0,故 I ( x , y ) = H ( X ) I(x,y)=H(X) I(x,y)=H(X),为最大值,而当两个变量完全独立时, p ( x , y ) = p ( x ) p ( y ) p(x,y)=p(x)p(y) p(x,y)=p(x)p(y),此时,由互信息的概率形式公式,我们可以发现互信息值此时为0.

​ 经过以上分析,我们可以发现互信息的本质是熵的变化,当处理连续变量时,对于离散化时的区间划分十分敏感,划分方式对熵的影响很大,因此直接用于选择特征并不方便。于是引入最大信息系数 M I C MIC MIC

​ 我们首先确定,将 X X X Y Y Y各自划分的份数,我们假设将他们分别划分成 a a a份和 b b b份,利用网格划分二维平面后,我们定义 M I C MIC MIC的计算公式为:
M I C ( x , y ) = max ⁡ a ∗ b < B I ( x , y ) log ⁡ 2 min ⁡ { a , b } MIC(x,y)=\max_{a*b<B}\frac{I(x,y)}{\log_2 \min \{a,b\}} MIC(x,y)=ab<Bmaxlog2min{a,b}I(x,y)

​ 为方便说明这个公式,我们暂设分成了2*2的网格,此时平面分为四份 ( X , Y ) ∈ ( 0 , 0 ) , ( 0 , 1 ) , ( 1 , 0 ) , ( 1 , 1 ) (X,Y)\in{(0,0),(0,1),(1,0),(1,1)} (X,Y)(0,0),(0,1),(1,0),(1,1),我们统计四类各自的频数后即可计算出此时的互信息值。注意,对平面的划分不是唯一的,在这若干划分中,因为样本是有限的,所以划分对应的每一个互信息值都能计算,存在一种划分使得互信息值最大。

​ 接下来对于最大的互信息,我们将其除以 log ⁡ 2 min ⁡ { a , b } \log_2 \min \{a,b\} log2min{a,b}以归一化,关于这一步,可以简单理解为对于熵来说,变量个数越少,熵相对应越低,变量个数越多,熵相对于越大,因此除以较小的变量频数以达到一种归一化的效果。究其本质与互信息公式有关,即去推导 X X X Y Y Y通常情况下的互信息值的上界,然而此时互信息值并不存在上界,需要对其附加一些分析条件,故此处不再往下讨论而直接使用已有结论。

​ 最后,以上都是在假设了 a a a b b b情况下的推导。我们最后在分布比较不同的 a , b a,b ab假设,最好取其中最大的值,设定为MIC值。而其中的** B B B为人为设定**,在查阅文献中,通常设定为样本量的0.6次方左右。

代码示例:

from minepy import MINE
import sklearn
import numpy as np
from sklearn import datasets
iris = datasets.load_iris()

mine = MINE(alpha=0.6,c=15)
x = np.random.uniform(-1, 1, 10000)
mine.compute_score(x, np.sin(x))#拟合非线性的相关性,从结果我们也能看出上界是经过条件优化的
print(mine.mic())

n,m=np.shape(iris.data)#可以利用MIC表现相关性并筛选
for i in range(0,m):
    mine.compute_score(iris.data[:,i], iris.target)
    print(mine.mic())

输出结果为:

1.0000000000000033
0.6421958994290488
0.4082465214581726
0.9182958340544889
0.9182958340544889
c.方差法

​ 顾名思义,考察一个分类变量特征的特征,计算其方差后设定阈值,筛选掉方差小于阈值的特征,也就是筛选掉变化幅度小,分类较为集中的特征。

​ 假设对于一个二分类变量,1(或0)的频数为p那我们可以估计其方差为 V ^ a r ( X ) = p ( 1 − p ) \hat Var(X)=p(1-p) V^ar(X)=p(1p),若我们准备对于数据集中, 90 % 90\% 90%都是1(或0)的数据予以删除,则可以将阈值设置为 0.9 ∗ 0.1 = 0.09 0.9*0.1=0.09 0.90.1=0.09.

​ 注意,方差法使用时通常针对分类变量。当对连续变量处理时,需要归一化消除量纲。

调用实例:

from sklearn.feature_selection import VarianceThreshold
# 参数threshold为方差的阈值,默认为0
sel = VarianceThreshold(threshold=(.9 * (1 - .9)))
print(sel.fit_transform(X))#X为自变量集

​ 最后指出,若选择的算法不需要遍历特征,例如随机森林,那么通常过滤法所能发挥的效果也有限。但是,过滤法本身依然还是在特征提取中十分有必要的一步,对于那些需要遍历特征的计算量很大的模型,例如,线性回归、逻辑回归、SVM、KNN、神经网络等,过滤法可以有效减少计算量并且提高稳定性。而且即使是对于随机森林,由于其基分类器是决策树模型,决策树运行时依然需要遍历随机选择的所有特征,故过滤法对随机森林模型依然是提升的。

2.Wrapper(包装法):

​ 包装法首先会要求选定算法模型,选定算法后,每次选择若干特征后,在训练集上训练模型,最后根据一个评价标准,例如误差来评价特征子集。

​ 因为包装法依据算法选定特征,因此选出的特征相比于过滤法往往可以更有效地提升模型本身的效果。

​ 下面介绍3种包装算法:

a.最优子集法:

​ 首先我们假设数据集中有m个特征,每个特征有选择和不选择两种可能,所以这个特征集一共有 2 m 2^m 2m个子集。最优子集法便是粗暴地遍历这些子集,最后按评价准测输出最优子集。

​ 所以,我们可以直接发现该方法的一个严重缺点,也就是计算量大小是指数级的,对于高维特征将直接失效。鉴于该子集搜索思路的实践性一般,故主要列举3个特征选择准则作为参考:调整后R方、AIC和BIC准则、 C p C_p Cp统计量。

​ 这三个准则此处不加叙述,感兴趣内容或使用示例的话可以搜寻网上资料或者参考书籍《应用回归分析(第五版)——中国人民出版社》。

b.前进法、后退法和步进法:

​ 前进法在选择特征子集中,每次会从剩余未选中的特征中,选人一个进入特征子集,直到设定的评价函数达到阈值或者特征个数达到预设最大值n,最后,从这些子集中选择最优的,例如,若以线性回归中的F值为指标,则输出F值最低的特征子集。

​ 后退法则与前进法则在子集选择中采取相反的顺序,即初始全选整个特征子集,然后逐个减少特征子集中的个数。

​ 前进法具体流程如下,后退法原理上类似,流程上对称,不再叙述。假设有m个特征,评价函数为均方误差。

​ 第一步,记不含任何特征的模型为 M 0 M_0 M0(不含任何特征可以简单理解为用一个平行x轴的直线拟合数据点),计算其均方误差。

​ 第二步,先从m个特征中把每个特征拿出来,计算这m个子集的训练模型的均方误差,并选择这其中均方误差最低的一个特征放入特征集合 M 1 M_1 M1

​ 第三步,从剩余的m-1个特征中把每个特征拿出来,放进 M 1 M_1 M1中,计算这m-1个子集的训练模型的均方误差,选择其中均方误差最低的一个子集记为 M 2 M_2 M2

​ 依次反复,知道特征子集 M k M_k Mk的均方误差小于预定阈值或者所选特征达到预设的个数 K K K

​ 接下来说明一下两种方法的缺陷,首先以上两种方法每次都需要搜索较多的子集并训练比较,复杂度为 o ( 1 + M + ( M − 1 ) + ⋯ + ( M − K + 1 ) ) = o ( K 2 ) o(1+M+(M-1)+\dots +(M-K+1))=o(K^2) o(1+M+(M1)++(MK+1))=o(K2)。另外,对于前进法,当某个自变量引入后,它可能最初是显著的,但是在别的自变量引入后却变得不在显著,然而“终身制”的筛选机制却不再会将他删除。而对于后退法,因为一开始就要引入所有变量,计算量相对就会大很多,有些变量最开始就没必要放入特征集,而且,他的剔除也是“终身制”,一旦剔除就不会再进入特征集。

​ 于是为了弥补上述两种计算方法只进不出或者只出不进的缺陷,于是引入步进法,也叫逐步回归法。它的基本思想是有进有出。其原理是,首先利用前进法筛选两个变量,然后再利用后退法删去一个变量,如此往复。其中,需要设置进入特征值和删除特征值的显著水平,我们假设为 α e n t r y \alpha_{entry} αentry α r e m o v a l \alpha_{removal} αremoval。其中,这两个变量需要满足关系:
α e n t r y < α r e m o v a l \alpha_{entry}<\alpha_{removal} αentry<αremoval
否则,若存在变量,其显著性 p p p满足 α r e m o v a l ≤ p ≤ α e n t r y \alpha_{removal}\le p \le \alpha_{entry} αremovalpαentry,则该特征就会因为显著性小于 α e n t r y \alpha_{entry} αentry而进入特征集,随后又因为显著性达不到小于 α r e m o v a l \alpha_{removal} αremoval的要求而被删除,如此反复而陷入死循环。

​ 最后说明对于步进法,需要注意的是,计算量的大小并没有减少,甚至会更多。并且,其搜索方式其实也具有局部性,大部分时候,步进法并不会考察所有特征都入样的情况。它主要只是改变了前两种方法“只进不出”和“只出不进”的缺点。

​ 由于没有找到python中有直接调用前进法、后退法和步进法,故此处暂不作示例。需要的话可以搜索python实现前向搜索、后向搜索。

c.递归特征消除法(Recursive feature elimination)

​ 递归特征消除法,属于一种比较典型的包装算法。它本身是一种贪婪的(局部的)优化算法,主要步骤与后退法类似。我们假设每次筛去变量数设定为1,首先将所有特征放入集合中再训练集上按照选定算法训练拟合,但是,后退法在这一步是不会删除变量的,而RFE则会计算此时每个特征的权值并删除权值最低的一个特征,反复直到特征集合中特征个数达到我们的预设。因此RFE的计算量会比后退法小很多。

​ 但要注意的是,该方法单纯依据权重删除变量,而权重并非显著性,不能直接刻画相关性,所以依然可能删除有效信息导致拟合效果甚至不如原数据集。这点与方差法类似。

​ 另外,在我们设置参数时,往往不知道到底选取多少个变量是最好的。因此引入“交叉验证”的方式,即对于N个特征的特征集,首先利用上述算法计算出N个特征子集,随后每个特征子集在训练集上,通过将训练集划分为训练集和验证集的方式,计算正确率并对比,得出最优的子集合。

​ 代码示例:

import matplotlib.pyplot as plt
from sklearn.svm import SVC
from sklearn.model_selection import StratifiedKFold
from sklearn.feature_selection import RFECV
from sklearn.datasets import make_classification

X, y = make_classification(n_samples=1000, n_features=25, n_informative=3,#设置3个有效特征
                           n_redundant=2, n_repeated=0, n_classes=8,
                           n_clusters_per_class=1, random_state=666)

svc = SVC(kernel="linear")
rfecv = RFECV(estimator=svc, step=1, cv=StratifiedKFold(5)
              ,scoring='accuracy')
#划分四个训练集和一个验证集,将四个训练集在验证集上的均分输出

rfecv.fit(X, y)

print("推荐特征数: %d" % rfecv.n_features_)#从下图中,我们可以发现当特征数约为3时每个集合基本都达到一个较好的效果
print("特征排名 : %s" % rfecv.ranking_)	#而综合最高点则在8个特征数的位置
print("选择特征: %s" % rfecv.support_)

plt.figure()
plt.xlabel("Number of features selected")
plt.ylabel("Cross validation score (nb of correct classifications)")
plt.plot(range(1, len(rfecv.grid_scores_) + 1), rfecv.grid_scores_)
plt.show()

最后结果为:

推荐特征数: 8
特征排名 : [ 1 10  8 13  1 11 18  1 17  2 14  1  3  5  1  7  9  6  1 12  1 16  1 15
  4]
选择特征: [ True False False False  True False False  True False False False  True
 False False  True False False False  True False  True False  True False
 False]

在这里插入图片描述

3.Embedded(嵌入法):

​ 与包装法类似,嵌入法依然要求首先选择算法模型,然后选择所有特征在训练集上训练模型,得到各个特征的权值系数,根据系数从大到小选择特征。另外,嵌入法也会使用 L 1 L_1 L1 L 2 L_2 L2正则项来调节特征系数,例如利用 L 2 L_2 L2正则项的岭回归和利用 L 1 L_1 L1正则项的套索回归。

​ 因此相比于包装法,两者相同点在于它们都会依据算法来选择特征;不同点在于,包装法每次训练使用的是特征子集,依据评价指标来决定是否使用该子集,因为子集个数往往较多,计算量相对较大,然而嵌入法,仅使用所有特征进行一次训练,计算量由此便相对于包装法降低很多。

​ 但因为其使用的评价标准为权重,所以有同递归特征消除法一样的缺点,它依然可能删除掉有效信息而导致模型效果反而变差。

​ 下面介绍sklearn库中的SelectFromModel作为嵌入法筛选器。SelectFromModel有如下几个重要参数:

(1)estimator,选择模型,要求模型具有 c o e f _ coef\_ coef_, f e a t u r e _ i m p o r t a n c e s _ feature\_importances\_ feature_importances_属性和 L 1 L_1 L1 L 2 L_2 L2正则项;

(2)threshold,设定权重阈值,权重小于设定值的话该特征便会被删除;

(3)max_features,设定最大特征数,不能与阈值同时使用。若要使用该参数则需要设定threshold=-np.inf。

下面给出代码示例:

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.ensemble import RandomForestClassifier # 随机森林分类器
from sklearn.model_selection import cross_val_score # 交叉验证
from sklearn.feature_selection import SelectFromModel # sklearn的嵌入法模块
from sklearn.datasets import load_iris#导入iris数据集
iris = load_iris()
X, y = iris.data, iris.target

rfc = RandomForestClassifier(n_estimators=50, random_state=666)

max_importance = (rfc.fit(X, y).feature_importances_).max()#计算特征重要性最大值,注意若为线性算法,改为coef_
print('最大特征重要性为:',max_importance)

#绘画阈值学习曲线以寻找合适的阈值
thresholds = np.linspace(0, max_importance, 20)
rough_scores = []

for i in thresholds :
    X_new = SelectFromModel(rfc, threshold=i).fit_transform(X, y)
    rough_scores.append(cross_val_score(rfc, X_new, y, cv=2).mean())

plt.figure(figsize=(15, 7))
plt.plot(thresholds, rough_scores)
plt.xticks(thresholds)
plt.show()

#依照绘图我们选择0.4167为阈值
select = SelectFromModel(rfc, threshold=0.4167)
X_embeded = select.fit_transform(X, y)

#交叉验证模型表现
score_embeded = cross_val_score(rfc, X_embeded, y, cv=3).mean()
print("交叉验证得分为:",score_embeded)#此处验证集得分效果较好

得到结果:

最大特征重要性为: 0.4657016213870365
交叉验证得分为: 0.9666666666666667

在这里插入图片描述

​ 总结一下以上三种方法。首先就必要性上,个人认为直接从相关程度入手的过滤法是一定要考虑的,其中较为优秀的是互信息法。当然,除了本文介绍的几种描述相关性程度的方法,其实还有诸如利用KNN聚类算法来刻画相关程度等诸多方法,本文难以收纳完全。

​ 在首先使用过滤法后,接下来再使用包装法或者嵌入法来依据模型筛选特征。而对比包装法和嵌入法,我们可以发现嵌入法因其选择权重系数而非显著性为依据,并且并未考虑子特征集上的模型情况,故特征筛选的精度上并不如包装法。然而,在计算的复杂度上嵌入法则明显优于包装法。最后,对于后两种方法的使用,通常要结合交叉验证。在三种方法的使用顺序上,可以粗略总结为过滤法 ⇒ \Rightarrow 嵌入法 ⇒ \Rightarrow 包装法。

二、特征降维

​ 现实的数据集中,特征与特征之间往往存在着相关性,这点难以避免,而这种相关性会导致提供的有效信息有重复,最后导致模型做出了多余的计算,或者估计的一些特征系数发生异常。

​ 降维的主要思路是,通过类似于将对称矩阵对角化的一个映射,使原本的解释信息得到集中,也就是消除变量间的相关性。最后选择能解释大部分信息的几个变换后特征进行建模。

​ 特征降维种最重要的内容就是选择的“映射”,依据映射的不同,特征降维也有了不同的分类。如按照映射是否线性,可以分为线性映射和非线性映射,而非线性映射又可以分为基于核函数或者基于特征值的映射。

​ 本文介绍2种特征降维算法。

a.PCA主成分分析

​ 一种非常经典的线性降维算法,其具体的原理和方法在许多网络资料或者教材中都有说明,本文仅作简介。

​ 首先就PCA的内核思路来讲,主要是逐步寻找维度方向,假设一个m维数据集,我们首先寻找第一个维度,这个维度有说明特点呢?若将数据集的m个向量均投影到该维度,则此时数据集在此维度上的方差将达到最大,也就是区分度将达到最大。然后依照此法寻找第二个维度方向,并使得第二个维度与第一个维度达到垂直。如此反复,最多生成m个维度。

​ 就代数角度来看,其实就是把这m维数据集的相关系数矩阵或者协方差矩阵计算出来(取决于是否有对特征标准化),随后将对称矩阵变换为一个对角阵即可。注意,因为我们用特征之间的相关矩阵表示特征的之间的方差信息,所以此时特征变量需要满足Gauss—Markov条件误差项服从一个指数族分布(也就是要求数据不存在系统误差)的假设。否则,统计学上,数据的均值和方差的组合将不足以作为特征方差的充分统计量。另外,模型一般为线性模型时,使用PCA可以有较好的效果。

​ 总体来讲,PCA的普适性还是很高的,它最大程度地保留了数据集信息。而且PCA使用也非常简单,不需要我们设置参数。

代码示例:

from sklearn.datasets import load_iris#导入iris数据集
iris = load_iris()
X, y = iris.data, iris.target
#Bartlett's球状检验,检验变量的相关矩阵是否满秩,即检查是否满足变量间相对独立的假设,p值越低越合适因子分析
from factor_analyzer.factor_analyzer import calculate_bartlett_sphericity 
chi_square_value, p_value = calculate_bartlett_sphericity(X)
print( p_value)

#KMO检验,考察变量间相关性和偏相关性的相对大小,若值大于0.6则适合因子分析
from factor_analyzer.factor_analyzer import calculate_kmo
kmo_all, kmo_model = calculate_kmo(X)
print(kmo_all)

from sklearn.decomposition import PCA
pca = PCA(n_components= 0.90).fit(X)#选用解释90%的方差信息的特征数
pca.fit(X)#这里个人也推荐使用SPSS,可以查看得分矩阵,python个人没有找到得分矩阵如何输出。
b.LLE局部线性嵌入

​ LLE(Local Linear Embedding),是一种非线性映射的方法。其思想内核基于流形学习,模型要求数据集符合流形假设。受限于个人目前只学习到实变函数基础的大三数学水平,还不是很理解其中的映射关系到底时如何构建的,此处暂时难以附上LLE的原理说明。

​ 代码示例:

import matplotlib.pyplot as plt
from sklearn.datasets import make_classification
X, y = make_classification(n_samples=1000, n_features=25, n_informative=3,
                           n_redundant=2, n_repeated=0, n_classes=8,
                           n_clusters_per_class=1, random_state=666)

from sklearn.manifold import LocallyLinearEmbedding
lle = LocallyLinearEmbedding(n_components=3, #降维到的维数
                             n_neighbors=5, #k近邻算法选取的最近邻个数
                             neighbors_algorithm='auto',#选择k近邻算法,auto为自动选择
                             random_state=666)
X_lle= lle.fit_transform(X)#降维后的特征集

fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')

ax.scatter(X_lle[:, 0], X_lle[:, 1],X_lle[:, 2], c=y, cmap=plt.cm.hot)
ax.set_xlabel("$X_1$", fontsize=18)
ax.set_ylabel("$X_2$", fontsize=18)
ax.set_zlabel("$X_3$", fontsize=18)
#plt.grid(True)#网格线

plt.show()

输出结果为:

在这里插入图片描述

四.参考文章与书籍

1.特征选择与特征提取

2.机器学习中的特征——特征选择的方法以及注意点

3.怎样理解 Curse of Dimensionality(维数灾难)? - 微调的回答 - 知乎

4.sklearn中的特征工程(过滤法、嵌入法和包装法)

5.Maximal Information Coefficient (MIC)最大互信息系数详解与实现 - FontTian的文章 - 知乎

6.特征降维方法

7.【机器学习】数据降维(Dimensionality Reduction) - 稷殿下的文章 - 知乎

8.局部线性嵌入算法(LLE)与其Python实现

3.怎样理解 Curse of Dimensionality(维数灾难)? - 微调的回答 - 知乎

4.sklearn中的特征工程(过滤法、嵌入法和包装法)

5.Maximal Information Coefficient (MIC)最大互信息系数详解与实现 - FontTian的文章 - 知乎

6.特征降维方法

7.【机器学习】数据降维(Dimensionality Reduction) - 稷殿下的文章 - 知乎

8.局部线性嵌入算法(LLE)与其Python实现

9.《应用回归分析(第五版)——中国人民出版社》

  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值