利用scikit-learn进行机器学习:特征工程(二)特征选择
特征选择
1 概述
2 特征选择之Filter
2.1 方差选择法
2.2 卡方检验法
2.3 互信息法
3 特征选择之Wrapper
3.1 递归式特征消除法
4 特征选择之Embedded
4.1 基于惩罚项的特征选择法
4.2 基于树模型的特征选择法
1 概述
相信有打过kaggle比赛的筒子们一定不会小看特征工程这个工作。既然机器学习界早有“数据和特征决定模型上限的说法”,那么特征工程就必须是我们学习机器学习必须重视的过程。在上一节推送中,小编跟大家介绍了特征工程中数据预处理的基本方法,在对数据进行预处理之后,我们就需要从数据中选取相应的特征来进行训练了。所以,特征选择简单而言就是从数据中选取一些特征来进行建模。
当然你可能也猜到了,事情并没有那么简单。在选取特征的时候,并不是说我们看哪个特征比较顺眼或者主观臆测某些特征丢入模型中跑一下,然后效果不好再踢出来换一些特征。特征选择的本质在于如何从数据集中选到一个最优的子集,如果这个选出来的子集在我们使用的机器学习算法上有着相对较好的表现的话,那么可以认为我们的特征选择工作做得还算可以。所以,关于特征选择的核心内容就是如何选取能够在一些算法上表现还算可以的数据子集。
在特征工程中,特征选择有着一套较为完整的方法论。总结起来主要包括 Filter(过滤法)、Wrapper(包装法)、Embedded(嵌入法),在使用上这些方法在Python的sklearn中都有相应的模块来实现,sklearn中的feature_selection是特征选择的一把好手。
2 特征选择方法之Filter
即过滤法,按照发散性或者相关性对各个特征进行评分,通过设定一些阈值或者待选择阈值的个数来选择特征。在scikit-learn中过滤法具体包括方差选择法、卡方检验法和互信息法,在feature_selection模块中均可轻易实现。 2.1 方差选择法 所谓方差选择法,就是剔除那些零方差或者低方差的特征,如果一个特征方差为零或者很低,即样本在这个特征上表现基本一致,差异性较小,这样的特征对于我们做预测并无用处。假设数据集中有一个特征为布尔值,现在我们想移除一些在整个数据中特征值为0或者1的比例超过80%的特征,我们可以通过0.8*(1-0.8)这样一个阈值在sklearn中进行选择:
from sklearn.feature_selection import VarianceThreshold
X = [[0, 0, 1], [0, 1, 0], [1, 0, 0], [0, 1, 1], [0, 1, 0], [0, 1, 1]]
sel = VarianceThreshold(threshold=(.8 * (1 - .8)))
sel.fit_transform(X)
array([[0, 1],
[1, 0],
[0, 0],
[1, 1],
[1, 0],
[1, 1]])
第一列值为0的比例超过了80%,在结果中VarianceThreshold剔除这一列。
2.2 卡方检验法
在统计学中,卡方检验量用来检验定性变量之间相关下的统计量。在sklearn中,卡方检验法除了通过检验定性变量自变量对因变量的相关性来筛选特征之外,还可以用于稀疏数据的特征选择。在feature_selection模块中,卡方检验法筛选特征模块为chi2.具体应用实例如下:
from sklearn.datasets import load_iris
from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import chi2
iris = load_iris()
X, y = iris.data, iris.target
X.shape
(150, 4)
X_new = SelectKBest(chi2, k=2).fit_transform(X, y)
X_new.shape
(150, 2)
2.3 互信息法
和卡方检验法一样,互信息法也是用于定性变量之间相关性的统计方法。互信息法通过信息计算公式来表示定性自变量对定性因变量的相关性,但该方法也可用于筛选定量数据特征,featureselection 模块中的 mutualinforegression 和 mutualinfoclassif 通常结合起来利用可以计算两个随机变量之间的线性相关程度。具体应用可参考代码:http://sklearn.apachecn.org/cn/0.19.0/modules/generated/sklearn.featureselection.mutualinfoclassif.html
以上便是Filter方法进行特征选择,总体而言,Filter方法并不复杂,但想运用得当还需一番功力。
3 特征选择方法之Wrapper
Wrapper方法可取名为包裹式方法,就是选定一些算法,根据算法在数据上的表现来选择特征集合,一般选用的算法包括随机森林、支持向量机和k近邻等常用算法。 3.1 递归式特征消除法 递归式特征消除法,听起来就感觉很复杂,简单来说就是在给定一个外部评估器的条件下,对数据特征赋予一定的权重,通过考虑越来越小的特征集合来递归的选择特征。首先评估器在初始的特征集合上面训练且特征的重要程度由一个featureimportance属性获得。然后从当前的特征集合中提出最不重要的特征,不断重复递归这个步骤,直到达到所需要的特征数量为止。如此可见,递归式特征消除法开始关键的一步在于指定一个性能较优的评估器。具体应用实例如下,该例中通过递归式特征消除来自动调整交叉验证中选择的特征数。
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,n_redundant=2, n_repeated=0, n_classes=8,
n_clusters_per_class=1, random_state=0)
svc = SVC(kernel="linear")
rfecv = RFECV(estimator=svc, step=1, cv=StratifiedKFold(2),
scoring='accuracy')
rfecv.fit(X, y)
print("Optimal number of features : %d" % rfecv.n_features_)
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()
Optimal number of features : 3
4 特征选择方法之Embedded
Embedded方法即嵌入法,在三大经典特征选择方法中难度系数最高,考验的是各位少侠的机器学习内功程度。嵌入式特征选择方法主要包括基于惩罚项和基于树模型的特征选择方法。
4.1 基于惩罚项的特征选择法
熟悉机器学习正则化理论方法的筒子一定了解L0、L1和L2正则化算子。而基于惩罚项的特征选择方法就是利用正则化思想将一些特征属性的权重变为零,除了上面提到的三大正则化算子,常用的正则化方法还包括Elastic Net、多任务弹性网络、最小角回归等。例如基于L1范数的正则化方法可以实现稀疏,实现稀疏的好处除了模型的可解释增强之外就是还可以进行特征选择。 当我们的目标是降低训练数据的维度时,L1范数可以与SelectFromModel一起使用来选择非零系数:
from sklearn.svm import LinearSVC
from sklearn.datasets import load_iris
from sklearn.feature_selection import SelectFromModel
iris = load_iris()
X, y = iris.data, iris.target
X.shape
(150, 4)
lsvc = LinearSVC(C=0.01, penalty="l1", dual=False).fit(X, y)
model = SelectFromModel(lsvc, prefit=True)
X_new = model.transform(X)
X_new.shape
(150, 3)
4.2 基于树模型的特征选择方法
基于树模型的评估器也是计算特征重要性的利器,目前为广大kaggler所喜爱的XGBoost就可以给出数据集的特征重要程度。基于树模型的特征选择例子如下:
from sklearn.ensemble import ExtraTreesClassifier
from sklearn.datasets import load_iris
from sklearn.feature_selection import SelectFromModel
iris = load_iris()
X, y = iris.data, iris.target
X.shape
(150, 4)
clf = ExtraTreesClassifier()
clf = clf.fit(X, y)
clf.feature_importances_
array([ 0.04..., 0.05..., 0.4..., 0.4...])
model = SelectFromModel(clf, prefit=True)
X_new = model.transform(X)
X_new.shape
(150, 2)
除了特征选择方法之外,有时候我们还需要从已有的特征中构造出一些新的特征,这种特征构造的方法也叫做特征提取,除了需要我们掌握必要的机器学习方法之外,对数据集的理解和相关的领域知识都是我们最后模型的预测准确率好坏的因素之一。
参考资料:
http://scikit-learn.org/stable/modules/preprocessing.html#preprocessing
http://www.cnblogs.com/jasonfreak/p/5448385.html
往期精彩:
利用scikit-learn进行机器学习:特征工程(一)数据预处理
利用pandas进行数据分析(一):Series和DataFrame数据结构
使用jupyter notebook搭建数据科学最佳交互式环境
一个数据科学热爱者的学习历程