【说明】文章内容来自《机器学习——基于sklearn》,用于学习记录。若有争议联系删除。
特征选择,又称变量选择、属性选择或变量子集选择,是选择相关特征子集用于模型构造的过程。简要地说,通过检测相关特征。摒弃冗余特征,获得特征子集,从而以最小的性能损失更好地描述问题。
特征选择和降维都是防止数据过拟合的有效手段。但是两者又有本质上的区别。降维本质上是从一个维度空间映射到另一个维度空间,在映射的过程中特征值会相应地变化。特征选择就是单纯地从提取到的所有特征中选择部分特征作为训练集特征,特征在选择前和选择后不改变其值,但是选择后的特征维数肯定比选择前小。特征选择注重别除无用特征。
sklearn.feature_selection 模块提供了特征选择方法,如下所示。
方法 | 说明 |
VarianceThreshold | 删除方差小的特征 |
SelectKBest | 返回K个最佳特征,移除那些除了评分最高的K个特征之外的所有特征 |
SelectPercentile | 按指定百分比返回表现最佳的特征 |
特征选择的方法有包装法、过滤法和嵌人法等。
包装法具有递归特征消除和交叉验证递归特征消除两种方法。
递归特征消除(Recursive Feature Elimination, RFE)是常见的特征选择方法。其工作原理是:递归删除特征,并在剩余的特征上构建模型,使用模型准确率来判断哪些特征(或特征组合)对预测结果贡献较大。
Sklearn提供了RFE函数,以实现递归消除特征法。格式如下:
RFE(estimator=svc, n_features_to_select=no_features, step=1)
【参数说明】
示例:
from sklearn.feature_selection import RFE
from sklearn.svm import LinearSVC#线性支持向量机
from sklearn.datasets import load_iris
from sklearn import model_selection
from sklearn.model_selection import GridSearchCV
iris = load_iris()
X = iris.data
y = iris.target
#特征提取
estimator = LinearSVC()
selector = RFE(estimator = estimator, n_features_to_select = 2)
X_t = selector.fit_transform(X,y)
X_train, X_test, y_train, y_test = model_selection.train_test_split(X, y,
test_size = 0.25,random_state = 0,stratify = y)
X_train_t, X_test_t, y_train_t, y_test_t = model_selection.train_test_split(X_t,y,
test_size = 0.25,random_state = 0, stratify = y)
#训练和测试
clf = LinearSVC()
clf_t = LinearSVC()
clf.fit(X_train, y_train)
clf_t.fit(X_train_t, y_train_t)
#print(clf.score(X_test,y_test))
print('original dataset: test score =%s'%(clf.score(X_test, y_test)))
print('selected dataset: test score =%s'%(clf_t.score(X_test_t,y_test_t)))
【运行结果】
【结果分析】
原模型的性能在递归特征消除后确实下降了,这是因为递归特征消除自身的原因。虽然该方法可以较好地进行手动特征选择,但是原模型在去除特征后的数据集上的性能表现要差于其在原数据集上的表现,这是因为去除的特征中包含有效信息。
交叉验证递归特性消除(Recursive Feature Elimination with Cross ValidationRFECV)通过交叉验证来找到最优的特征数量,实现特征选择。该方法分如下两个阶段
(1) RFE 阶段。进行递归特征消除,对特征进行重要性评级。具体步骤如下:
(2) CV阶段在完成特征评级后,通过交叉验证,选择最佳数量的特征。具体步骤如下:
RFEGV用于选取单模型特征的效果相当不错,但是它有如下两个缺陷:
Sklearn提供了RFECV函数,以实现交叉验证递归消除,格式如下:
RFEECV(estimator=svc, step=1, cv=StratifiedKFold(2))
【参数说明】
示例:
#新版本sklearn2.0中grid_score_函数删除
import matplotlib.pyplot as plt
from sklearn.model_selection import StratifiedKFold
from sklearn.feature_selection import RFECV
from sklearn import svm
from sklearn.datasets import make_classification
#使用内置函数生成数据集(1000个样本,25个特征,3个有效特征,共8类)
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)
#创建RFECV,用正确分类比例进行评分
svc = svm.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 feaature selected')
plt.ylabel('Cross validation score(nb of correct classifications)')
plt.plot(range(1, len(rfecv.cv_results_['mean_test_score']) + 1),
rfecv.cv_results_['mean_test_score'])
#plt.plot(range(1, len(rfecv.grid_scores_) + 1), rfecv.grid_scores_)
plt.show()
【运行结果】
Optimal number of features: 3
版本sklearn2.0中grid_score_函数删除
更换cv_results_函数俩获得评分和参数。
过滤法有移除低方差特征法和单变量特征选择两种方法。其中,单变量特征选择根据问题类型不同,其消除的指标不同。对于分类问题,采用卡方检验、f_classif等指标。对于回归问题,采用皮尔森相关系数指标。
从方差的大小考虑,特征方差小是指某个特征的大多数样本的值比较相近,特征方差大是指某个特征很多样本的值有比较大的差别。移除低方差特征又称为方差选择法,用于删除低方差的一些特征。
Sklearn提供VarianceThreshold函数实现此功能,其基本语法如下:
sklearn.feature _selection.VarianceThreshold(threshold)
【参数说明】参数 threshold为移除方差的阈值。在默认情况下,它取值为0,表示移除所有方差为0的特征,也就是移除所有取值相同的特征,保留所有非零方差特征。
示例:
from sklearn.feature_selection import VarianceThreshold
import numpy as np
var = VarianceThreshold(threshold = 1.0)
data = np.array([[0,2,0,3],[0,1,4,3],[0,1,1,3]])
print('data\n',data)
print('data.shape\n', data.shape)
data_new = var.fit_transform(data)
print('data_new\n',data_new)
print('data_new.shape\n', data_new.shape)
【运行结果】
单变量特征选择法又称为相关系数法,它通过计算每个变量的指标,根据重要程度剔除不重要的指标,选择最佳特征。Sklearn 提供了SelectKBest 和 SelectPercentile 两个函数实现单变量特征选择。其中,SelectKBest保留评分最高的K个特征,SelectPercentile保留指定百分比的高分特征。
SelectKBest的语法如下:
sklearn.feature_selection.SelectKBest (score_func=f_classif, k=10)
【参数说明】
SelectPercentile的语法如下:
SelectPercentile(score_ func=f_classif, percentile=90)
【参数说明】
(1)SelectKBest 示例
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
print(X.shape)
#对样本进行一次chi2测试来选择最佳的两相特征
X_new = SelectKBest(chi2, k = 2).fit_transform(X,y)
#SelectKBest(选择chi2评分函数,k=2 选择最优两个)
print(X_new.shape)
(2)SelectPercentile示例:
from sklearn.feature_selection import SelectPercentile, f_classif
def test_SelectKBest():
X = [[1,2,3,4,5],[5,4,3,2,1,],[3,3,3,3,3],[1,1,1,1,1]]
y = [1,0,1,0]
print('before transform:',X)
selector = SelectPercentile(score_func = f_classif, percentile = 90)
selector.fit(X,y)
print('scores_:', selector.scores_)
print('pvalues_:', selector.pvalues_)
print('selected index:', selector.get_support(True))
#如果为true,则返回被选出的特征下标,如果选择False,则
#返回的是一个布尔值组成的数组,该数组只是那些特征被选择
print('after transform:', selector.transform(X))
#调用test_SelectKBest函数
test_SelectKBest()
【运行结果】