%config Completer.use_jedi = False

Removing features with low variance

VarianceThreshold 是一种简单的基线特征选择方法。它删除所有方差不满足某个阈值的特征。默认情况下,它删除所有零方差特特征,即在所有样本中具有相同值的特征。

作为一个例子,假设我们有一个布尔特性的数据集,并且我们希望删除超过80% 的样本中的所有特性,这些特性要么是1,要么是0(开或关)。布尔特征是伯努利随机变量,这些变量的方差由 V a r [ X ] = p ( 1 − p ) Var[X]=p(1-p) Var[X]=p(1−p) ,设定p=0.8

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(0.8*(1.0-0.8))

VarianceThreshold移除第1列,因为包含0的概率p=5/6大于0.8

VarianceThreshold函数

去除所有低方差特性的特性选择器。这个特征选择算法只看特征(X) ,而不是期望的输出(y) ,因此可以用于非监督式学习

参数:

  • threshold:训练集方差低于此阈值的特征将被删除。默认值是保留所有具有非零方差的特性,即删除在所有样本中具有相同值的特性。

Univariate feature selection

单变量特征选择通过基于单变量统计检验的最佳特征选择来实现。它可以被看作是估计器的一个预处理步骤。Scikit-learn 公开了特征选择例程作为实现转换方法的对象:

  • SelectKBest删除了所有特征,处理k个得分最高的特征
  • SelectPercentile 去除了所有特征,除了用户指定的最高得分百分比的特征
  • 对每个特征使用常见的单变量统计检验: 假阳性率 SelectFpr、假发现率 SelectFdr 或家族误差 SelectFwe。
  • GenericUnivariateSelect 允许使用可配置策略执行单变量特性选择。这允许用超参数搜索估计器选择最佳的单变量选择策略。

例如,我们可以对样本进行 χ2检验,只检索以下两个最佳特征:

from sklearn.datasets import load_iris
from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import chi2
X,y=load_iris(return_X_y=True)
X.shape
(150, 4)
X_new=SelectKBest(chi2,k=2).fit_transform(X,y)
X_new.shape
(150, 2)

这些对象接受一个评分函数作为输入,该函数返回单变量得分和 p 值(或者只返回 SelectKBest 和 SelectPercentle 的得分) :

  • For regression: f_regression, mutual_info_regression
  • For classification: chi2, f_classif, mutual_info_classif

基于 F 检验的方法估计两个随机变量之间的线性相关程度。另一方面,互信息方法可以捕获任何类型的统计相关性,但由于是非参数的,因此需要更多的样本来进行精确估计。

注意:当心不要使用回归评分函数对于分类问题,你会得到无用的结果。

2.1例子:单变量特征选择

this notebook是一个例子,使用单变量特征选择,以提高分类准确性,在噪声数据集上。

在这个例子中,一些噪声(非信息性)特征被添加到鸢尾花数据集中。支持向量机(SVM)是用来在应用单变量特征选择之前和之后对数据集进行分类的。对于每个特征,我们绘制单变量特征选择的 p 值以及支持向量机的相应权值。在此基础上,我们将比较模型的精度,并研究单变量特征选择对模型权重的影响。

#生产样本数据
import numpy as np
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split#导入数据
X,y=load_iris(return_X_y=True)#产生噪声
E=np.random.RandomState(42).uniform(0,0.1,size=(X.shape[0],20))#拼接
X=np.hstack((X,E))#划分训练集和测试集
X_train,X_test,y_train,y_test=train_test_split(X,y,stratify=y,random_state=0)

基于 F 检验的单变量特征选择算法。我们使用默认的选择函数来选择四个最重要的特性。

#单变量特征选择
from sklearn.feature_selection import SelectKBest,f_classif
selector=SelectKBest(f_classif,k=4)
selector.fit(X_train,y_train)
scores = -np.log10(selector.pvalues_)
scores /=scores.max()
scores.shape
(24,)

f_calssif返回两个变量,一个是f值,还有一个是pvalue,这个pvalue就是用于检验特征与变量之间相关性的,假设你给出α值(常常取0.05,0.01),如果你的pvalue小于α,那就有把握认为,这个特征和预测变量y之间,具有相关性。比方说你取α=0.05,这就意味着你有95%(也就是1-α)的把握认为,这个特征和预测变量y之间存在相关性

scores
array([3.72189526e-01, 1.92112431e-01, 9.98924450e-01, 1.00000000e+00,1.61525527e-02, 1.78421693e-03, 3.36072503e-02, 9.34126229e-04,8.38039241e-03, 4.46122522e-03, 2.47289009e-03, 3.04121968e-03,4.16671859e-03, 6.37306186e-03, 2.79418271e-03, 5.46727836e-03,9.36025883e-04, 8.67509750e-03, 2.39127975e-03, 6.33147019e-04,1.10538184e-03, 7.61511411e-03, 1.15995689e-03, 2.40400211e-02])

SelectKbest

参数:

  • score_func:函数接受两个数组 X 和 y,并返回一对数组(scores、 pvalue)或一个包含得分的array。默认值是f_classif
  • k:Number of top features to select.

f_classif:计算所提供样本的 ANOVA F 值。

p值:p值表示在原假设(零假设)的条件下,样本发生或观测值出现的概率。若p值小于小概率事件的阈值即alpha,那么拒绝原假设。否则接受原假设。

p 值取对数然后加负号。因为 p 值一般都很小,所以一般取对数做图。然后又因为一般 p < 1 所以取对数都是负值,我们为了作图方便所以加个负号。

X.shape
(150, 24)
import matplotlib.pyplot as plt
X_indices=np.arange(X.shape[1])
plt.bar(X_indices,scores,width=0.2)plt.title('Feature univariate score')
plt.xlabel('Feature number')
plt.ylabel(r'Univariate score($ -log(p_{value})$)')
Text(0, 0.5, 'Univariate score($ -log(p_{value})$)')

在所有特性中,只有原始特性中的4个是重要的。我们可以看到,他们的单变量特征选择得分最高。

#与没有单变量选择的SVM对比from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import MinMaxScaler
from sklearn.svm import LinearSVCclf=make_pipeline(MinMaxScaler(),LinearSVC())
clf.fit(X_train,y_train)
print("Classification accuracy without selecting features:%.3f"%clf.score(X_test,y_test))
Classification accuracy without selecting features:0.789
clf[-1].coef_.sum(axis=0)
array([-0.70218947, -1.31643483,  1.28790201,  0.57508358, -0.01230533,-0.14713904, -0.09645719, -0.13342564,  0.32116893, -0.09813465,-0.25981795, -0.16661493,  0.22493638, -0.1361782 , -0.39830228,-0.18961366,  0.14455047, -0.47917281,  0.02690776,  0.01552195,0.06613667, -0.3242161 ,  0.15179789, -0.2870809 ])
clf[-1].coef_.shape
(3, 24)
svm_weights = np.abs(clf[-1].coef_).sum(axis=0)
svm_weights /= svm_weights.sum()
#经过单变量选择
clf_selected=make_pipeline(SelectKBest(f_classif,k=4),MinMaxScaler(),LinearSVC())
clf_selected.fit(X_train,y_train)
print('Classification accuracy after univariate feature selection:%.3f'%clf_selected.score(X_train,y_train))
Classification accuracy after univariate feature selection:0.938
svm_weights_selected = np.abs(clf_selected[-1].coef_).sum(axis=0)
svm_weights_selected /= svm_weights_selected.sum()
#绘图
plt.bar(X_indices-0.45,scores,width=0.2,label=r'Univariate score ($-Log(p_{value})$')plt.bar(X_indices-0.5,svm_weights,width=0.2,label='SVM weight')plt.bar(X_indices[selector.get_support()]-0.05,svm_weights_selected,width=0.2,label='SVM weights after selection')plt.title('comparing feature selection')
plt.xlabel('feaure number')
plt.yticks(())
plt.legend(loc='best')
plt.show()

在没有单变量特征选择的情况下,支持向量机对前4个原始重要特征赋予较大的权重,但也选择了许多非信息性特征。在支持向量机之前应用单变量特征选择,增加了重要特征对支持向量机的权重,从而改善了分类效果。

2.2F- 检验与互信息的比较

这个例子说明了单变量 F- 检验统计量和互信息之间的区别。

我们考虑在[0,1]上均匀分布的3个特征 x _ 1,x _ 2,x _ 3,目标对它们的依赖如下:y = x_1 + sin(6 * pi * x_2) + 0.1 * N(0, 1),即第三个特征完全无关。

下面的代码绘制了 y 与单个 x _ i 的依赖关系,以及单变量 F- 检验统计量和互信息的归一化值

由于 F- 检验只捕获线性相关性,因此它将 x _ 1作为最具有鉴别力的特征。另一方面,互信息可以捕捉变量之间的任何依赖关系,并且它将 x _ 2作为最具区分性的特征,这可能更符合我们对这个例子的直观感知。两种方法都正确地将 x _ 3标记为不相关。

import numpy as np
import matplotlib.pyplot as plt
from sklearn.feature_selection import f_regression,mutual_info_regression
#生产随机向量
np.random.seed(0)
X = np.random.rand(1000, 3)
y = X[:, 0] + np.sin(6 * np.pi * X[:, 1]) + 0.1 * np.random.randn(1000)
#返回单变量线性回归
f_test,_=f_regression(X,y)
f_test/=np.max(f_test)
f_test
array([1.        , 0.28024353, 0.00252204])
mi=mutual_info_regression(X,y)
mi/=np.max(mi)
mi
array([0.36448455, 1.        , 0.        ])
plt.figure(figsize=(15,5))
for i in range(3):plt.subplot(1,3,i+1)plt.scatter(X[:,i],y,edgecolor='black',s=20)plt.xlabel(r'$X_{%d}$'%(i+1),fontsize=20)if i==0:plt.ylabel('y',fontsize=20)plt.title('F_test=%.3f,MI=%.3f'%(f_test[i],mi[i]))plt.show()

Recursive feature elimination

给定一个给特征赋权的外部估计器(例如,线性模型的系数) ,递归特征消除(RFE)的目标是通过递归地考虑越来越小的特征集合来选择特征。首先,对特征的初始集合进行训练,通过任意特定属性(如 coef _、 Feature _ important _)或可调用属性获得每个特征的重要性。然后,从当前的特征集合中删除最不重要的特征。该过程在修剪后的集合上递归地重复,直到最终达到所需要选择的特性数量。

RFECV 在一个交叉验证循环中执行 RFE,以找到最佳的特性数量。

sklearn.feature_selection.RFECV

递归特征消除与交叉验证选择特征的数量。

参数:

  • estimator:使用fit方法的监督式学习估计器,可以通过 coef _ 属性或者通过 Feature _ important _ 属性提供关于特征重要性的信息。
  • step:如果大于或等于1,则步长对应于每次迭代时要删除的特征的(整数)个数。如果在(0.0,1.0)之内,则步长对应于每次迭代时要删除的特性的百分比(四舍五入)。请注意,最后一次迭代可能会删除少于step的特性,以达到 min _ properties _ to _ select。
  • cv:决定交叉验证的分割策略,可能的cv输入如下:
    • None, to use the default 5-fold cross-validation,
    • integer, 指定folds次数.
    • CV splitter,
    • 一个可迭代的 yielding(训练,测试)作为数组的索引
    • 注意:对于 迭代器或者没有输入(None), 如果 y 是 二进制 或者 多类,则使用 sklearn.model_selection.StratifiedKFold. 如果学习器是个分类器 或者 如果 y 不是 二进制 或者 多类,使用 sklearn.model_selection.KFold.
  • min_features_to_select:要选择的最小特性数。即使原始特性计数和 min _ Features _ to _ select 之间的差异不能被step整除,这些特性的数量总是会得到评分

methods:

  • fit(X,y):fit RFE 模型并自动调整所选特性的数量。

attributes:

  • support_:选定特征的掩码。
  • ranking:特征排名,使得ranking_[i]对应于第 i 个特征的排名位置。选定的(即,估计的最好的)特征被分配排名1
  • n_features_in_:在fit时看到的特性数量。只有当底层估计器在fit时公开这样一个属性时才定义。

example1

下面的示例演示如何检索 Friedman # 1数据集中的先验未知5个信息特征。

from sklearn.datasets import make_friedman1
from sklearn.feature_selection import RFECV
from sklearn.svm import SVR
X,y=make_friedman1(n_samples=50,n_features=10,random_state=0)
estimator=SVR(kernel='linear')
selector=RFECV(estimator,step=1,cv=5)
selector.fit(X,y)
RFECV(cv=5, estimator=SVR(kernel='linear'))
selector.support_
array([ True,  True,  True,  True,  True, False, False, False, False,False])
selector.ranking_
array([1, 1, 1, 1, 1, 6, 4, 3, 2, 5])

RFE函数

参数:

  • estimator:使用fit方法的监督式学习估计器,可以通过 coef _ 属性或者通过 Feature _ important _ 属性提供关于特征重要性的信息。
  • step:如果大于或等于1,则步长对应于每次迭代时要删除的特征的(整数)个数。如果在(0.0,1.0)之内,则步长对应于每次迭代时要删除的特性的百分比(四舍五入)。请注意,最后一次迭代可能会删除少于step的特性,以达到 min _ properties _ to _ select。
  • n_features:要选择的特性数。如果没有,则选择一半的特性。如果是整数,则参数是要选择的特性的绝对数量。如果浮动在0和1之间,那么它就是要选择的特性的分数。

example 2

一个递归特征消除的例子,显示在一个数字分类任务中像素的相关性。

from sklearn.svm import SVC
from sklearn.datasets import load_digits
from sklearn.feature_selection import RFE
#加载数据
digits=load_digits()
X = digits.images.reshape((len(digits.images), -1))
y = digits.target
X.shape
(1797, 64)

#创建RFE对象和排列pixel
svc=SVC(kernel='linear',C=1)
rfe=RFE(estimator=svc,n_features_to_select=1,step=1)
rfe.fit(X,y)
ranking=rfe.ranking_.reshape(digits.images[0].shape)
rfe.ranking_
array([64, 50, 31, 23, 10, 17, 34, 51, 57, 37, 30, 43, 14, 32, 44, 52, 54,41, 19, 15, 28,  8, 39, 53, 55, 45,  9, 18, 20, 38,  1, 59, 63, 42,25, 35, 29, 16,  2, 62, 61, 40,  5, 11, 13,  6,  4, 58, 56, 47, 26,36, 24,  3, 22, 48, 60, 49,  7, 27, 33, 21, 12, 46])
digits.images[0].shape
(8, 8)
plt.figure(figsize=(20,10))
plt.matshow(ranking,cmap=plt.cm.Blues)
plt.colorbar()
plt.title('Ranking of pixels with RFE')
plt.show()
<Figure size 1440x720 with 0 Axes>

exampe3

一个递归特征消除示例,自动调整用交叉验证选择的特征数量。

from sklearn.svm import  SVC
from sklearn.model_selection import  StratifiedKFold
from sklearn.feature_selection import RFECV
from sklearn.datasets import  make_classification
#使用3个信息特征构建一个分类任务
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,
)
#创建 RFE 对象并计算交叉验证得分。
svc=SVC(kernel='linear')#准确性”评分显示了正确分类的比例
min_features_to_select=1
rfecv=RFECV(estimator=svc,step=1,cv=StratifiedKFold(2),scoring='accuracy',min_features_to_select=min_features_to_select)
rfecv.fit(X,y)
RFECV(cv=StratifiedKFold(n_splits=2, random_state=None, shuffle=False),estimator=SVC(kernel='linear'), scoring='accuracy')
print("Optimal number of features : %d" % rfecv.n_features_)
Optimal number of features : 3
#Plot number of features VS. cross-validation scores
plt.plot(range(min_features_to_select,len(rfecv.grid_scores_)+1),rfecv.grid_scores_)
plt.xlabel('Number of features vs cross-validation scores')
plt.ylabel('cross validation score')
E:\Anaconda\lib\site-packages\sklearn\utils\deprecation.py:103: FutureWarning: The `grid_scores_` attribute is deprecated in version 1.0 in favor of `cv_results_` and will be removed in version 1.2.warnings.warn(msg, category=FutureWarning)Text(0, 0.5, 'cross validation score')

交叉验证的得分使 grid _ score _ [ i ]对应于特征的第 i 子集的 CV 得分。

why is the score different for grid_scores_ and score(X,y)?

grid _ score _ 是一个交叉验证分数的数组。grid _ score _ [ i ]是第 i 次迭代的交叉验证得分。这意味着第一个得分是所有特性的得分,第二个得分是删除一组特性时的得分,依此类推。每个步骤中删除的特性数等于步骤参数的值。默认情况下是 = 1。

Score (X,y)选择特征的最佳数量并返回这些特征的得分。

why are the scores sometimes negative?

这取决于您使用的估计器和计分器。如果没有设置计分器,则 RFECV 将使用默认的计分函数作为估计器。一般来说,这是准确的,但在您的特定情况下,可能是返回负值的值。

Feature selection using SelectFromModel

SelectFromModel 是一个元转换器,它可以与任何通过特定属性(例如 coef _,Feature _ important _)或者通过fit后可调用的 important _ getter 来赋予每个特征重要性的估计器一起使用。如果特征值的相应重要性低于所提供的阈值参数,则认为特征不重要并将其移除。除了用数字指定阈值之外,还有一些内置的启发式方法用于使用字符串参数查找阈值。可用的启发式方法是“均值”、“中值”和浮点数倍,比如“0.1 * 均值”。结合threshold条件,可以使用 max_features参数设置要选择的特性数量的限制。

sklearn.feature_selection.SelectFromModel

基于重要性权重的特征选择元变换器。

参数:

  • estimator:构造transfomer的基本估计器。这既可以是一个合适的(如果prefit设置为真)或non-fitted estimator.。在fitting之后,估计器应该有一个 Feature _ important _ or coef _ Attribute。否则,应该使用 important _ getter 参数。
  • threshold:用于特征选择的阈值。重要性较大或相等的特性被保留,而其他特性被丢弃。如果“中位数”(相当于。“均值”) ,然后threshold是特征重要性的中位数(相当于平均值)。也可以使用比例因子(例如“1.25 * 均值”)。如果 None 和估计器的参数惩罚设置为 l1(显式或隐式)(例如 Lasso) ,则使用的阈值为1e-5。否则,默认使用“ mean”。
  • prefit:预估值模型是否应该直接传递给构造函数。如果为True,则estimator 必须是拟合的估计器。如果为 False,则分别通过调用 fit 和 part _ fit 对estimator进行拟合和更新。

methods:

  • get_support 获取所选特性的掩码或整数索引。

    • returns:从特征向量中选择保留特征的索引。如果 indices 为 False,这是一个布尔型数组形状[ # input Features ] ,其中一个元素为 True,如果它的相应特征被选中保留的话。如果 indices为 True,那么这是一个形状[ # 输出特征]的整数数组,它的值是输入特征向量的索引。
  • transform:用于特征选择的阈值。

    • returns:只有选定特性的输入样本。

example1

这个例子说明并比较了两种特征选择方法: 基于特征重要性的 SelectFromModel 和基于贪婪方法的 SequentialFeatureSelection。我们使用糖尿病数据集,其中包括从442名糖尿病患者收集的10个特征。

#加载数据
from sklearn.datasets import  load_diabetes
diabetes=load_diabetes()
X,y=diabetes.data,diabetes.target
print(diabetes.DESCR)
.. _diabetes_dataset:Diabetes dataset
----------------Ten baseline variables, age, sex, body mass index, average blood
pressure, and six blood serum measurements were obtained for each of n =
442 diabetes patients, as well as the response of interest, a
quantitative measure of disease progression one year after baseline.**Data Set Characteristics:**:Number of Instances: 442:Number of Attributes: First 10 columns are numeric predictive values:Target: Column 11 is a quantitative measure of disease progression one year after baseline:Attribute Information:- age     age in years- sex- bmi     body mass index- bp      average blood pressure- s1      tc, total serum cholesterol- s2      ldl, low-density lipoproteins- s3      hdl, high-density lipoproteins- s4      tch, total cholesterol / HDL- s5      ltg, possibly log of serum triglycerides level- s6      glu, blood sugar levelNote: Each of these 10 feature variables have been mean centered and scaled by the standard deviation times `n_samples` (i.e. the sum of squares of each column totals 1).Source URL:
https://www4.stat.ncsu.edu/~boos/var.select/diabetes.htmlFor more information see:
Bradley Efron, Trevor Hastie, Iain Johnstone and Robert Tibshirani (2004) "Least Angle Regression," Annals of Statistics (with discussion), 407-499.
(https://web.stanford.edu/~hastie/Papers/LARS/LeastAngle_2002.pdf)
系数的特征重要性

为了了解特征的重要性,我们将使用 RidgeCV 估计器。具有最高绝对 coef _ value 的特性被认为是最重要的。我们可以直接观察系数而不需要缩放它们(或缩放数据) ,因为从上面的描述,我们知道特征已经标准化了。

from sklearn.linear_model import RidgeCV
import numpy as npridge=RidgeCV(alphas=np.logspace(-6,6,num=5)).fit(X,y)
importance=np.abs(ridge.coef_)#获得权重向量
feature_names = np.array(diabetes.feature_names)
feature_names
array(['age', 'sex', 'bmi', 'bp', 's1', 's2', 's3', 's4', 's5', 's6'],dtype='<U3')
plt.bar(feature_names,importance)
plt.title('Feature importances via coefficients')
plt.show()

基于重要性选择特征

现在我们要根据系数来选择最重要的两个特征。SelectFromModel 就是为此而设计的。SelectFromModel 接受一个threshold 参数,并将选择重要性(由系数定义)高于该阈值的特性。

因为我们只想选择2个特性,所以我们将设置这个阈值略高于第三个最重要特性的系数。

from sklearn.feature_selection import  SelectFromModel
import timethreshold=np.sort(importance)[-3]+0.01
tic=time.time()
sfm=SelectFromModel(ridge,threshold=threshold).fit(X,y)
toc=time.time()print(f"Features selected by SelectFromModel: {feature_names[sfm.get_support()]}")
print(f"Done in {toc - tic:.3f}s")
Features selected by SelectFromModel: ['s1' 's5']
Done in 0.002s
基于序列特征选择的特征选择

选择特性的另一种方法是使用 SequentialFeatureSelector (SFS)。SFS 是一个贪婪的过程,在每次迭代中,我们根据交叉验证分数选择最好的新特性添加到我们选择的特性中。也就是说,我们从0个特性开始,选择得分最高的最佳单个特性。重复这个过程,直到我们达到所需的特征数量选定。

我们也可以反其道而行之(向后 SFS) ,即从所有特性开始,贪婪地选择特性一个接一个地删除。我们在这里举例说明这两种方法。

from sklearn.feature_selection import  SequentialFeatureSelector
from time import  timetic_fwd = time()
sfs_forward = SequentialFeatureSelector(ridge, n_features_to_select=2, direction="forward").fit(X, y)
toc_fwd = time()tic_bwd = time()
sfs_backward = SequentialFeatureSelector(ridge, n_features_to_select=2, direction="backward").fit(X, y)
toc_bwd = time()print("Features selected by forward sequential selection: "f"{feature_names[sfs_forward.get_support()]}"
)
print(f"Done in {toc_fwd - tic_fwd:.3f}s")
print("Features selected by backward sequential selection: "f"{feature_names[sfs_backward.get_support()]}"
)
print(f"Done in {toc_bwd - tic_bwd:.3f}s")
Features selected by forward sequential selection: ['bmi' 's5']
Done in 0.151s
Features selected by backward sequential selection: ['bmi' 's5']
Done in 0.673s

有趣的是,向前和向后选择都选择了相同的一组特征。一般来说,情况并非如此,这两种方法会导致不同的结果。

我们还注意到,SFS 选择的特性与通过特性重要性选择的特性不同: SFS 选择 bmi 而不是 s1。不过这听起来很合理,因为根据系数,bmi 对应于第三个最重要的特征。考虑到 SFS 根本没有使用系数,这是非常值得注意的。

最后,我们应该注意到 SelectFromModel 比 SFS 快得多。事实上,SelectFromModel 只需要fit一个模型一次,而 SFS 需要为每次迭代交叉验证许多不同的模型。然而,SFS 可以处理任何模型,而 SelectFromModel 需要底层的估计器来得到coef_ attribute 或 feature_importances_ Attribute。前向 SFS 比后向 SFS 快,因为它只需要执行 n_features_to_select = 2次迭代,而后向 SFS 需要执行 n_features_to_select = 8次迭代。

基于 L1的特征选择

用 L1范数处罚的线性模型具有稀疏解: 它们的许
多估计系数为零。当目标是降低数据的维数以便与另一个分类器一起使用时,它们可以与 SelectFromModel 一起用来选择非零系数。特别是,用于这一目的的稀疏估计量是用于lasso回归,以及用于分类的 Logistic 回归和 LinearSVC:

from sklearn.datasets import  load_iris
from sklearn.feature_selection import  SelectFromModel
X,y=load_iris(return_X_y=True)
X.shape
(150, 4)
lsvc = LinearSVC(C=0.01, penalty="l1", dual=False).fit(X, y)
model = SelectFromModel(lsvc, prefit=True)#拟合完了,所以为true
X_new=model.transform(X)
X_new.shape
(150, 3)

使用支持向量机和逻辑回归,参数 C 控制稀疏度: C 越小,选择的特征越少。使用 Lasso 时,alpha 参数越高,选择的特性就越少。

L1恢复和压缩传感

对于一个选择好的alpha,使用很少的观察情况下,lasso可以完全恢复精确的非零变量集,只要满足某些特定的条件。具体而言,样本数量应为“足够大”,即 L1模型将随机执行,其中“足够大”取决于非零系数的数量、特征数量的对数、噪音量、非零系数的最小绝对值以及设计矩阵 X 的结构。此外,设计矩阵必须显示某些特定的属性,例如不要太相关。

没有一般的规则来选择用于恢复非零系数的 alpha 参数。它可以通过交叉验证(LassoCV 或 LassoLarsCV)来设定,尽管这可能会导致欠缺惩罚模型: 包括少量非相关变量不会损害预测得分。相反,BIC (LassoLarsIC)倾向于设置高的 alpha 值。

基于树的特征选择

基于树的估计器(参见 skLearn.tree 模块和 sklearn.ensemble 模块中的树的森林)可以用来计算基于杂质的特征重要性,这反过来又可以用来丢弃不相关的特征(当与 SelectFromModel 元转换器结合时) :

from sklearn.ensemble import  ExtraTreesClassifier
from sklearn.datasets import  load_iris
from sklearn.feature_selection import SelectFromModelX,y=load_iris(return_X_y=True)clf=ExtraTreesClassifier(n_estimators=50)
clf=clf.fit(X,y)
X.shape
(150, 4)
clf.feature_importances_
array([0.0927286 , 0.05197754, 0.42599508, 0.42929878])
model=SelectFromModel(clf,prefit=True)
X_new=model.transform(X)
X_new.shape
(150, 2)

ex:随机森林评估特征重要性

这个例子展示了使用随机森林来评估特征在人工分类任务中的重要性。蓝色条是森林的特征重要性,以及由error bars表示的树之间的可变性。

我们生成一个合成数据集,只有3个信息特征。我们将明确地不重组数据集,以确保信息特性将对应于 X 的前三列。此外,我们将把数据集划分为训练和测试子集。

X,y=make_classification(n_samples=1000,n_features=10,n_informative=3,n_redundant=0,n_repeated=0,n_classes=2,random_state=0,shuffle=False)
X_train,X_test,y_train,y_test=train_test_split(X,y,stratify=y,random_state=0)

随机森林分类器将会被fit来计算特征重要性

from sklearn.ensemble import  RandomForestClassifierfeature_names=[f'feature{i}'for i in range(X.shape[1])]
forest=RandomForestClassifier(random_state=0)
forest.fit(X_train,y_train)
RandomForestClassifier(random_state=0)

基于杂质平均减少的特征重要性:

特征重要度由fitted attribute feature_importances_ 提供,计算方法为每棵树内杂质减少的积累量的平均值和标准差。

importances=forest.feature_importances_#feature_importances_基于杂质的特征重要性。
std=np.std([tree.feature_importances_ for tree in forest.estimators_],axis=0)#每个特征的标准差
import pandas as pd
import matplotlib.pyplot as pltfig=plt.figure(figsize=(10,9))
forest_importances=pd.Series(importances,index=feature_names)
plt.bar(yerr=std,x=forest_importances.index,height=forest_importances.values)#yerr画垂直误差
plt.title("Feature importances using MDI")
plt.ylabel("Mean decrease in impurity")
fig.tight_layout()

我们观察到,正如预期的那样,前三个特征被认为是重要的。

基于特征置换的特征重要性:

置换排列特征重要性克服了基于杂质的特征重要性的局限性: 它们不偏向于高基数特征,并且可以在省略的测试集上计算。

from sklearn.inspection import permutation_importanceresult = permutation_importance(forest, X_test, y_test, n_repeats=10, random_state=42, n_jobs=2
)forest_importances = pd.Series(result.importances_mean, index=feature_names)
fig, ax = plt.subplots()
forest_importances.plot.bar(yerr=result.importances_std, ax=ax)
ax.set_title("Feature importances using permutation on full model")
ax.set_ylabel("Mean accuracy decrease")
fig.tight_layout()
plt.show()

Sequential Feature Selection

顺序特征选择(SFS)在 SequentialFeatureSelector transformer中可用。SFS 可以是向前的,也可以是向后的:

Forward-SFS 是一个贪婪的过程,它迭代地找到要添加到所选特性集中的最佳新特性。具体来说,我们首先从零特征开始,找到一个特征,使交叉验证得分最大化时,估计器是对这个单一的特征训练。一旦选择了第一个特性,我们通过向选定的特性集添加一个新特性来重复这个过程。当达到所需的选定特性数量时,过程停止,这由n_features_to_select参数决定。

Backward-SFS 遵循相同的思路,但是工作方向相反: 我们不是从没有特性开始并贪婪地添加特性,而是从所有特性开始并贪婪地从集合中删除特性。dierction参数控制是否使用向前或向后 SFS。

一般来说,向前和向后选择不会产生等效的结果。另外,一个可能比另一个快得多,这取决于所要求的选定特性的数量: 如果我们有10个特性并要求7个选定特性,向前选择将需要执行7次迭代,而向后选择只需要执行3次。

SFS 与 RFE 和 SelectFromModel 的不同之处在于,它不需要底层模型来公开一个 coef _ or Feature _ important _ 属性。而,考虑到与其他方法相比,需要评估更多的模型,这可能会比较慢。例如在反向选择中,使用 k 折叠交叉验证从 m 特征到 m-1特征的迭代需要对 m * k 模型进行拟合,而 RFE 只需要一次拟合,而 SelectFromModel 总是只进行一次拟合,不需要迭代。

Feature selection as part of a pipeline

特征选择通常被用作实际学习前的一个预处理步骤。在 scikit-learn 中推荐的方法是使用管道:

# from sklearn.pipeline import  Pipeline
# clf = Pipeline([
#   ('feature_selection', SelectFromModel(LinearSVC(penalty="l1"))),
#   ('classification', RandomForestClassifier())])
# clf.fit(X, y)

在这个片段中,我们使用一个 LinearSVC 和 SelectFromModel 相结合来评估特性的重要性并选择最相关的特性。然后,对转换后的输出(即仅使用相关的特征)训练一个随机森林分类器。您可以使用其他特征选择方法和分类器执行类似的操作,这些分类器当然提供了一种评估特征重要性的方法。


sklearn_feature_selection相关推荐

最新文章

  1. 项目管理深入理解08--成本管理
  2. CVPR 2021:记一次神奇的 Rebuttal 经历
  3. ctrl键一直自动按住了_用好Ctrl键,效率快一半
  4. 计算机领域认知个人陈述,计算机专业个人陈述十九
  5. journal of systems science and complexity
  6. 在CentOS 7系统里使用465端口发送邮件
  7. linux环境编程 学习,学习linux环境高级编程首先学习的是文件的操作。因为有.pdf...
  8. caffe学习笔记25-过拟合原因及分析
  9. xutils找id空指针_xUtils更新到3.0后的基本使用规则
  10. sql程序实现事物锁表和解锁_怎样用SQL给SQL2880特定表加锁解锁
  11. Android XML解析之PULL及单元测试
  12. 【PMP】项目整合管理
  13. Win11这个界面你肯定没见过
  14. [TSP-FCOS]Rethinking Transformer-based Set Prediction for Object Detection
  15. 易优CMS插件-站长必备易优CMS插件
  16. 到底什么是CE、C++、C+L波段?
  17. Android之模仿微信登陆界面(一)
  18. SVN 查看用户名密码
  19. Linux root管理员权限
  20. JQuery模板 :(六)JsViews - 基于JsRender并具有动态绑定功能的模板

热门文章

  1. 神经网络的正向传递与反向传播
  2. proxychains配置终端代理
  3. 浪涌抑制专题-压敏电阻/TVS管/浪涌抑制介绍
  4. 第十四届蓝桥杯三月真题刷题训练——第 8 天
  5. Matlab使用符号对象求二元函数积分并做图
  6. TKmapper的更新方法updateByPrimaryKey()与updateByPrimaryKeySelective()
  7. 携程算法岗笔试【20230525】
  8. 证件照半身照合成服装PNG素材-463张
  9. Chrome Google绿色便携制作(可更新自定义模式)
  10. windows安全警报怎么关闭_永久关闭WIN10自动杀毒(windows安全中心)