特征选择(过滤法、包装法、嵌⼊法)
⽂章⽬录
有这么⼀句话在业界⼴泛流传:数据和特征决定了机器学习的上限,⽽模型和算法只是逼近这个上限⽽已。特征⼯程⽬的是最⼤限度地从原始数据中提取特征以供算法和模型使⽤。这⾥主要说的是特征选择。
当数据预处理完成后,我们需要进⾏特征选择,即选择有意义的特征输⼊机器学习的算法和模型进⾏训练。特征选择主要有两个功能:减少特征数量、降维,使模型泛化能⼒更强,减少过拟合。
去掉似是⽽⾮不易判别的特征,提⾼精度。
通常来说,从两个⽅⾯考虑来选择特征:
特征是否发散:如果⼀个特征不发散,例如⽅差接近于0,那么就是说样本在这个特征上基本上没有差异,这个特征对于样本的区分并没有什么⽤。
特征与⽬标的相关性:这点⽐较显⽽易见,与⽬标相关性⾼的特征,应当优选选择。
根据特征选择的形式⼜可以将特征选择⽅法分为3种:
Filter:过滤法,按照发散性或者相关性对各个特征进⾏评分,设定阈值或者待选择阈值的个数,选择特征。
Wrapper:包装法,根据⽬标函数(通常是预测效果评分),每次选择若⼲特征,或者排除若⼲特征。
Embedded:嵌⼊法,先使⽤某些机器学习的算法和模型进⾏训练,得到各个特征的权值系数,根据系数从⼤到⼩选择特征。类似于Filter ⽅法,但是是通过训练来确定特征的优劣。
Filter过滤式⽅法
过滤式⽅法(Filter)通常是独⽴地选择特征,这可能会忽略特征组合之间的相关性。
⽅差选择法
使⽤⽅差选择法,先要计算各个特征的⽅差,然后根据阈值,选择⽅差⼤于阈值的特征。使⽤feature_lection库的VarianceThreshold 类来选择特征的代码如下:
from sklearn.feature_lection import VarianceThreshold
# ⽅差选择法,返回值为特征选择后的数据
# 参数threshold为⽅差的阈值
VarianceThreshold(threshold=3).fit_transform(iris.data)
# iris.data为鸢尾花数据
相关系数法
使⽤相关系数法,先要计算各个特征对⽬标值的相关系数以及相关系数的P值。⽤feature_lection库的SelectKBest类结合相关系数来选择特征的代码如下:
from sklearn.feature_lection import SelectKBest
from scipy.stats import pearsonr
#选择K个最好的特征,返回选择特征后的数据
#第⼀个参数为计算评估特征是否好的函数,该函数输⼊特征矩阵和⽬标向量,输出⼆元组(评分,P值)的数组,数组第i项为第i个特征的评分和P值。在此定义为计算相关系数
#参数k为选择的特征个数
SelectKBest(lambda X, Y: array(map(lambda x:pearsonr(x, Y), X.T)).T, k=2).fit_transform(iris.data, iris.target)
卡⽅检验
经典的卡⽅检验是检验定性⾃变量对定性因变量的相关性。假设⾃变量有N种取值,因变量有M种取值,考虑⾃变量等于i且因变量等于j的样本频数的观察值与期望的差距,构建统计量:
⽤feature_lection库的SelectKBest类结合卡⽅检验来选择特征的代码如下:
from sklearn .feature_lection import SelectKBest
from sklearn .feature_lection import chi2
#选择K 个最好的特征,返回选择特征后的数据
SelectKBest (chi2, k =2).fit_transform (iris .data , iris .target )
互信息法和最⼤信息系数Mutual information and maximal information coefficient (MIC)
经典的互信息也是评价定性⾃变量对定性因变量的相关性的,互信息计算公式如下:
若想把互信息直接⽤于特征选择其实不是太⽅便:1、它不属于度量⽅式,也没有办法归⼀化,在不同数据及上的结果⽆法做⽐较;2、对于连续变量的计算不是很⽅便(X和Y都是集合,x,y都是离散的取值),通常变量需要先离散化,⽽互信息的结果对离散化的⽅式很敏感。最⼤信息系数克服了这两个问题。它⾸先寻找⼀种最优的离散化⽅式,然后把互信息取值转换成⼀种度量⽅式,取值区间在[0,1]。使⽤feature_lection库的SelectKBest类结合最⼤信息系数法来选择特征的代码如下:
from sklearn .feature_lection import SelectKBest
from minepy import MINE
#由于MINE 的设计不是函数式的,定义mic ⽅法将其为函数式的,返回⼀个⼆元组,⼆元组的第2项设置成固定的P 值0.5
def mic (x , y ):
ruixinm = MINE ()
m .compute_score (x , y )
return (m .mic (), 0.5)
#选择K 个最好的特征,返回特征选择后的数据
SelectKBest (lambda X , Y : array (map (lambda x :mic (x , Y ), X .T )).T , k =2).fit_transform (iris .data , iris .target )
Wrapper 封装式⽅法
递归特征消除法Recursive feature elimination (RFE)
递归特征消除的主要思想是反复的构建模型(如SVM或者回归模型)然后选出最差的(或者最好的)的特征(可以根据系数来选),把选出来的特征放到⼀边,然后在剩余的特征上重复这个过程,直到所有特征都遍历了。这个过程中特征被消除的次序就是特征的排序。因此,这是⼀种寻找最优特征⼦集的贪⼼算法。
RFE的稳定性很⼤程度上取决于在迭代的时候底层⽤哪种模型。例如,假如RFE采⽤的普通的回归,没有经过正则化的回归是不稳定的,那么RFE就是不稳定的;假如采⽤的是Ridge,⽽⽤Ridge正则化的回归是稳定的,那么RFE就是稳定的。
使⽤feature_lection库的RFE类来选择特征的代码如下:
from sklearn .feature_lection import RFE
from sklearn .linear_model import LogisticRegression
jlpt官网#递归特征消除法,返回特征选择后的数据
#参数estimator 为基模型
#参数n_features_to_lect 为选择的特征个数
RFE (estimator =LogisticRegression (), n_features_to_lect =2).fit_transform (iris .data , iris .target )
Embedded 过滤式⽅法
基于惩罚项的特征选择法
χ=2E
(A −E )∑2
I (X ;Y )=p (x ,y )log xϵX ∑yϵY ∑p (x )p (y ))
p (x ,y )
基于惩罚项的特征选择法其实是基于正则的特征选择法。正则化就是把额外的约束或者惩罚项加到已有模型(损失函数)上,以防⽌过拟合并提⾼泛化能⼒。损失函数由原来的变为,w是模型系数组成的向量(有些地⽅也叫参数
parameter,coefficients),||·||⼀般是或者范数,是⼀个可调的参数,控制着正则化的强度。当⽤在线性模型上时,正则化和正则化也称为Lasso和Ridge。
正则化Lasso
正则化将系数w的l1范数作为惩罚项加到损失函数上,由于正则项⾮零,这就迫使那些弱的特征所对应的系数变成0。因此正则化往往会使学到的模型很稀疏(系数w经常为0),这个特性使得正则化成为⼀种很好的特征选择⽅法。
L2正则化Ridge regression
正则化将系数向量的范数添加到了损失函数中。由于惩罚项中系数是⼆次⽅的,这使得和有着诸多差异,最明显的⼀点就是,正则化会让系数的取值变得平均。对于关联特征,这意味着他们能够获得更相近的对应系数。以Y=X1+X2为例,假设X1和X2具有很强的关联,如果⽤L1正则化,不论学到的模型是Y=X1+X2还是Y=2X1,惩罚都是⼀样的,都是2 alpha。但是对于L2来说,第⼀个模型的惩罚项
是2,但第⼆个模型的是4*。可以看出,系数之和为常数时,各系数相等时惩罚是最⼩的,所以才有了L2会让各个系数趋于相同的特点。
基于树模型的特征选择法
树模型有准确率⾼、鲁棒性好、易于使⽤等优点,这使得它成为了⽬前最流⾏的机器学习算法之⼀。
平均不纯度减少 mean decrea impurity
随机森林由多个决策树构成。决策树中的每⼀个节点都是关于某个特征的条件,为的是将数据集按照不同的响应变量进⾏分裂。利⽤不纯度可以确定节点基于哪个特征进⾏分裂,对于分类问题,通常采⽤基尼系数或者信息增益 ,对于回归问题,通常采⽤的是⽅差或者最⼩⼆乘拟合。当训练决策树的时候,可以计算出每个特征减少了多少树的不纯度。对于⼀个决策树森林来说,可以算出每个特征平均减少了多少不纯度,并把它平均减少的不纯度作为特征选择的值。
平均精确率减少 Mean decrea accuracy
另⼀种常⽤的特征选择⽅法就是直接度量每个特征对模型精确率的影响。主要思路是打乱每个特征的特征值顺序,并且度量顺序变动对模型的精确率的影响。很明显,对于不重要的变量来说,打乱顺序对模型的精确率影响不会太⼤,但是对于重要的变量来说,打乱顺序就会降低模型的精确率。
决定节点分裂的次数
汉堡包英语单词
查看每个特征作为节点分裂依据的次数,次数越多则认为这个特征越重要。根据次数对特征进⾏排序。
随机森林进⾏特征选择
特征重要性度量
1)对每⼀颗决策树,选择相应的袋外数据(out of bag,OOB)计算袋外数据误差,记为errOOB1。
所谓袋外数据是指,每次建⽴决策树时,通过重复抽样得到⼀个数据⽤于训练决策树,这时还有⼤约1/3的数据没有被利⽤,没有参与决策树的建⽴。这部分数据可以⽤于对决策树的性能进⾏评估,计算模型的预测错误率,称为袋外数据误差。
这已经经过证明是⽆偏估计的,所以在随机森林算法中不需要再进⾏交叉验证或者单独的测试集来获取测试集误差的⽆偏估计。
2)随机对袋外数据OOB所有样本的特征X加⼊噪声⼲扰(可以随机改变样本在特征X处的值),再次计算袋外数据误差,记为errOOB2。
3)假设森林中有N棵树,则特征X的重要性=∑(errOOB2-errOOB1)/N。这个数值之所以能够说明特征的重要性是因为,如果加⼊随机噪声后,袋外数据准确率⼤幅度下降(即errOOB2上升),说明这个特征对于样本的预测结果有很⼤影响,进⽽说明重要程度⽐较⾼。特征选择
在特征重要性的基础上,特征选择的步骤如下:
1)计算每个特征的重要性,并按降序排序
2)确定要剔除的⽐例,依据特征重要性剔除相应⽐例的特征,得到⼀个新的特征集
3)⽤新的特征集重复上述过程,直到剩下m个特征(m为提前设定的值)。
4)根据上述过程中得到的各个特征集和特征集对应的袋外误差率,选择袋外误差率最低的特征集。
决策树进⾏特征选择
加权不纯度的减少
E (X ,Y )E (X ,Y )+α∣∣w ∣∣L 1L 2αL 1L 2L 1L 1L 1L 1L 2L 2L 2L 2L 1L 2αα
import DecisionTreeClassifier
免费试听als.six import StringIO
from sklearn import tree
import pydotplus
clf = DecisionTreeClassifier()
x =[[1,1,1,1,1,2,2,2,2,2,3,3,3,3,3],
[1,1,2,2,1,1,1,2,1,1,1,1,2,2,1],
[1,1,1,2,1,1,1,2,2,2,2,2,1,1,1],
[1,2,2,1,1,1,2,2,3,3,3,2,2,3,1]
facebook是什么]
y =[1,1,2,2,1,1,1,2,2,2,2,2,2,2,1]
x = np.array(x)
ui设计培训学费
x = np.transpo(x)
clf.fit(x,y)
print(clf.feature_importances_)
feature_name =['A1','A2','A3','A4']
target_name =['1','2']
dot_data = StringIO()
class_names=target_name,filled=True,rounded=True,
special_characters=True)
graph = aph_from_dot_data(value())
graph.write_pdf("WineTree.pdf")
print('Visible tree plot saved as pdf.')
XGBoost进⾏特征选择
在XGBoost中提供了三种特征重要性的计算⽅法:
‘weight’ - the number of times a feature is ud to split the data across all trees.‘gain’ - the average gain of the feature when it is ud in trees
‘cover’ - the average coverage of the feature when it is ud in trees
weight就是在所有树中特征⽤来分割的节点个数总和;
gain就是特征⽤于分割的平均增益
cover
import numpy as np
x =[[1,1,1,1,1,2,2,2,2,2,3,3,3,3,3],
[1,1,2,2,1,1,1,2,1,1,1,1,2,2,1],
[1,1,1,2,1,1,1,2,2,2,2,2,1,1,1],
[1,2,2,1,1,1,2,2,3,3,3,2,2,3,1]
]
y =[0,0,1,1,0,0,0,1,1,1,1,1,1,1,0]
x = np.array(x)
x = np.transpo(x)
params ={楔子是什么意思
'max_depth':10,
'subsample':1,
'verbo_eval':True,
'ed':12,
'objective':'binary:logistic'
siyi}
xgtrain = xgb.DMatrix(x, label=y)
bst = ain(params, xgtrain, num_boost_round=10)
fmap ='weight'
importance = _score(fmap ='',importance_type=fmap)
print(importance)
法语考试
_dump(with_stats=Fal))
fmap ='gain'
importance = _score(fmap ='',importance_type=fmap)
print(importance)
_dump(with_stats=True))
fmap ='cover'
importance = _score(fmap ='',importance_type=fmap)
print(importance)
_dump(with_stats=True))
结果如下:
国内英语培训机构#使⽤weight的结果为
{‘f0’:1, ‘f1’:3, ‘f2’:5, ‘f3’:2}
#使⽤gain的结果为
{‘f0’:0.440551, ‘f1’:1.8495799999999998, ‘f2’:1.9555256, ‘f3’:1.492955} #使⽤cover的结果为
{‘f0’:2.89962, ‘f1’:3.34311, ‘f2’:3.2390999999999996, ‘f3’:2.757295}
可以看出,不同的特征重要性度量⽅法得出的结果也是不尽相同的。PCA
LDA