特征工程原理(二)

前边文章讲了特征工程的定义、特征处理和特征转换;本节继续特征特征相关的内容,主要讲特征的选择。

四、特征选择

4.1 特征选择的定义

特征选择是在数据分析和建模中最常用的特征降维手段。过程简单粗暴,即映射函数直接将不重要的特征删除,不过这样会造成特征信息的丢失,不利于模型的精度。当然,由于数据分析以抓住主要影响因子为主,变量越少越有利于分析,因此特征选择常用语统计分析模型中;在超高维数据分析或者建模预处理中也会经常使用。

**特征选择的目标 **:

  • 特征是否发散:如果一个特征不发散,也就是方差接近0,这就说明样本在这个特征上基本没差异,这个特征对于样本区分没有作用。
  • 特征与目标的相关性:与目标的相关性越高,特征应该优先选择。

4.2 特征选择的方法

特征选择一般由三种方法:过滤法、包装法、嵌入法

  1. 过滤法:Filter,特征变量与目标变量之间的关系

    按照发散性或者相关性对各个特征进行评分,通过设置阈值或者待选择阈值的个数来选择特征

    相关系数、卡方检验、信息增益、互信息等方法

  2. 包装法:Wrapper,通过目标函数来决定是否加入特征变量

    根据目标函数每次选择若干个特征,或者排除若干个特征

  3. 嵌入法:Embedded,学习器自身自动选择特征

    使用机器学习的某些算法和模型进行训练,得到各个特征的权值系数,并根据系数从大到小选择特征。类似于过滤,区别在于嵌入法是通过模型训练来确定特征的优劣

    正则化、熵、信息增益等方法

4.3 方法举例

我们统一使用iris数据集进行验证

	import pandas as pd
	from sklearn.datasets import load_iris
	import numpy as np
	
	iris = load_iris()
	X = iris.data
	y = iris.target
  1. 卡方检验(过滤法)

    是过滤法的一种,检验定性自变量对定性因变量的相关性。假设自变量有N种取值,因变量有M种取值,考虑自变量等于i且因变量等于j的样本频数的观察值与期望的差距,
    构建统计量: x 2 = ( A − E ) 2 E x^2 = \frac{(A -E)^2}{E} x2=E(AE)2

    这个统计量的含义简而言之就是自变量对因变量的相关性。选择卡方值排在前面的K个特征作为最终的特征选择
    A是实际数量、E是期望的数量

    卡方过滤是专门针对离散型标签(即分类问题)的相关性过滤。卡方检验类 feature_selection.chi2 计算每个非负特征和标签之间的卡方统计量,并依照卡方统计量由高到低为特征排名。

    from sklearn.feature_selection import SelectKBest
    from sklearn.feature_selection import chi2
    
    chi2(X,y)
    #(array([ 10.82,   3.71, 116.31,  67.05]),
    #array([4.48e-03, 1.56e-01, 5.53e-26, 2.76e-15]))
    
    

    卡方检验的本质是推测两组数据之间的差异,其检验的原假设是”两组数据是相互独立的”。卡方检验返回卡方值和P值两个统计量,其中卡方值很难界定有效的范围,而p值,我们一般使用0.01或0.05作为显著性水平,即p值判断的边界。
    我们还可以结合 feature_selection.SelectKBest 这个可以输入”评分标准“来选出前K个分数最高的特征的类,我们可以借此除去最可能独立于标签,与我们分类目的无关的特征。

    chi = SelectKBest(score_func=chi2, k=2)
    chi.fit(X, y)
    chi.scores_
    #array([ 10.82,   3.71, 116.31,  67.05])
    

    从结果可以看出,P值越小的特征,卡方值越大;所以我们既可以根据P值进行过滤也可以根据卡方值的大小进行过滤。

  2. 方差检验(过滤法)
    方差检验是通过特征本身的方差来筛选特征的类。比如一个特征本身的方差很小,就表示样本在这个特征上基本没有差异,可能特征中的大多数值都一样,甚至整个特征的取值都相同,那这个特征对于样本区分没有什么作用。
    scikit-learn中的VarianceThreshold转换器可用来删除特征值的方差达不到最低标准的特征。

    from sklearn.feature_selection import VarianceThreshold
    vt = VarianceThreshold()
    vt.fit(X)
    
    vt.variances_
    #array([0.68, 0.19, 3.1 , 0.58])
    

    得到特征的方差后可以根据需要进行过滤,当然我们也可以直接进行过滤

    VarianceThreshold(threshold = 3).fit_transform(X)
    array([[1.4],
           [1.4],
           [1.3],
           [1.5],
    

    直接根据输入的阈值(threshold )进行过滤

  3. F检验(过滤法)
    F检验,又称ANOVA,方差齐性检验,是用来捕捉每个特征与标签之间的线性关系的过滤方法。它即可以做回归也可以做分类,因此包含feature_selection.f_classif(F检验分类)和feature_selection.f_regression(F检验回归)两个类。其中F检验分类用于标签是离散型变量的数据,而F检验回归用于标签是连续型变量的数据。
    我们只以分类为例,说明一下。

    F检验的本质是寻找两组数据之间的线性关系,其原假设是”数据不存在显著的线性关系“。它返回F值和p值两个统 计量。

    from sklearn.feature_selection import f_classif
    f_classif(X,y)
    #(array([ 119.26,   49.16, 1180.16,  960.01]),
    #array([1.67e-31, 4.49e-17, 2.86e-91, 4.17e-85]))
    

    和卡方过滤一样,我们希望选取p值小于0.05或0.01的特征,这些特征与标签时显著线性相关的,而p值大于 0.05或0.01的特征则被我们认为是和标签没有显著线性关系的特征,应该被删除。

  4. 互信息法(过滤法)
    互信息法是用来捕捉每个特征与标签之间的任意关系(包括线性和非线性关系)的过滤方法。和F检验相似,它既可以做回归也可以做分类,并且包含两个类 feature_selection.mutual_info_classif(互信息分类)和feature_selection.mutual_info_regression(互信息回归)。这两个类的用法和参数都和F检验一模一样,不过互信息法比F检验更加强大,F检验只能够找出线性关系,而互信息法可以找出任意关系。

    互信息法不返回p值或F值类似的统计量,它返回“每个特征与目标之间的互信息量的估计”,这个估计量在[0,1]之间取值,为0则表示两个变量独立,为1则表示两个变量完全相关。

    from sklearn.feature_selection import  mutual_info_regression
    mutual_info_regression(X,y)
    #array([0.47, 0.22, 1.  , 1.  ])
    
  5. RFE(包装法)
    递归消除特征法,是使用一个基模型来进行多伦训练,每轮训练后,消除若干个权值系数的特征,在基于新的特征集进行下一轮训练。

    RFE是一种贪婪的优化算法,旨在找到性能最佳的特征子集。
    它反复创建模型,并在每次迭代时保留最佳特征或剔除最差特征,
    下一次迭代时,它会使用上一次建模中没有被选中的特征来构建下一个模型,直到所有特征都耗尽为止。然后,它根据自己保留或剔除特征的顺序来对所有特征进行排名,最终选出一个最佳子集。
    包装法的效果是所有特征选择方法中最利于提升模型表现的,它可以使用很少的特征达到很优秀的效果。
    除此之外,在特征数目相同时,包装法和嵌入法的效果能够匹敌,不过它比嵌入法算得更快,
    虽然它的计算量也十分庞大,不适用于太大型的数据。但是,包装法任然是最高效的特征选择方法。

    	from sklearn.feature_selection import RFE
    	from sklearn.ensemble import RandomForestClassifier
    	#定义模型
    	RF = RandomForestClassifier(n_estimators=10, random_state=1)
    	RFE = RFE(estimator= RF, n_features_to_select=2, step=50)#n_features_to_select选择特征个数
    	RFE.fit(X,y)
    	#RFE(estimator=RandomForestClassifier(n_estimators=10, random_state=1),n_features_to_select=2, step=50)
    	RFE.ranking_
    	#array([2, 2, 1, 1])
    	RFE.support_
    	#array([False, False,  True,  True])
    	```
    RFE.ranking_:重要性排名矩阵,数值越小重要性越大,越不容易被删除
    
    
  6. SelectFromModel(嵌入法)

    SelectFromModel主要采用基于模型的特征选择法,常见的基于惩罚项的特征选择法和基于树模型的特征选择法。

    • 基于惩罚项的特征选择法,除了能筛选出特征还能进行降维。

    第一种是基于L1的特征选择,使用L1正则化的线性模型会得到稀疏解,当目标是降低维度的时候,可以使用sklearn中的给予L1正则化的线性模型,比如LinearSVC,逻辑回归,或者Lasso。但是要注意的是:在 SVM 和逻辑回归中,参数 C 是用来控制稀疏性的:小的 C 会导致少的特征被选择。使用 Lasso,alpha 的值越大,越少的特征会被选择。

     ```python
     from sklearn.feature_selection import SelectFromModel
     from sklearn.linear_model import LogisticRegression
     
     selector = SelectFromModel(estimator=LogisticRegression( )).fit(X, y)
     selector.get_support()
     #array([False, False,  True,  True])
     selector.transform(X)
     array([[1.4, 0.2],
            [1.4, 0.2],
            [1.3, 0.2],
            [1.5, 0.2],
            [1.4, 0.2],
     ```
    
    • 基于树模型的特征选择法

    Tree类的算法包括决策树,随机森林等会在训练后,得出不同特征的重要程度,我们也可以利用这一重要属性对特征进行选择。

from sklearn.ensemble import GradientBoostingClassifier
selector = SelectFromModel(estimator=GradientBoostingClassifier( )).fit(X, y)
selector.get_support()
#array([False, False,  True,  True])
selector.transform(X)
array([[1.4, 0.2],
       [1.4, 0.2],
       [1.3, 0.2],
       [1.5, 0.2],
       [1.4, 0.2],
       [1.7, 0.4],

你可能感兴趣的:(python,特征工程)