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
#与没有单变量选择的SVM对比
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import MinMaxScaler
from sklearn.svm import LinearSVC
clf=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
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
plt.figure(figsize=(20,10))
plt.matshow(ranking,cmap=plt.cm.Blues)
plt.colorbar()
plt.title('Ranking of pixels with RFE')
plt.show()
exampe3
一个递归特征消除示例,自动调整用交叉验证选择的特征数量。
from sklearn.svm import SVC
from sklearn.model_selection import StratifiedKFold
from sklearn.feature_selection import RFECV
from sklearn.datasets import make_classification
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:Anacondalibsite-packagessklearnutilsdeprecation.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。
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 参数。
#加载数据
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 level
Note: 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.html
For 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 np
ridge=RidgeCV(alphas=np.logspace(-6,6,num=5)).fit(X,y)
importance=np.abs(ridge.coef_)#获得权重向量
from sklearn.feature_selection import SelectFromModel
import time
threshold=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
from sklearn.feature_selection import SequentialFeatureSelector
from time import time
tic_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
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 的结构。此外,设计矩阵必须显示某些特定的属性,例如不要太相关。
from sklearn.ensemble import ExtraTreesClassifier
from sklearn.datasets import load_iris
from sklearn.feature_selection import SelectFromModel
X,y=load_iris(return_X_y=True)
clf=ExtraTreesClassifier(n_estimators=50)
clf=clf.fit(X,y)
from sklearn.ensemble import RandomForestClassifier
feature_names=[f'feature{i}'for i in range(X.shape[1])]
forest=RandomForestClassifier(random_state=0)
forest.fit(X_train,y_train)
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 plt
fig=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()
SFS 与 RFE 和 SelectFromModel 的不同之处在于,它不需要底层模型来公开一个 coef _ or Feature _ important _ 属性。而,考虑到与其他方法相比,需要评估更多的模型,这可能会比较慢。例如在反向选择中,使用 k 折叠交叉验证从 m 特征到 m-1特征的迭代需要对 m * k 模型进行拟合,而 RFE 只需要一次拟合,而 SelectFromModel 总是只进行一次拟合,不需要迭代。