在添加新特征或处理一般的的高维数据集,最好将特征的数量减少到只包含最有用的那些特征,并删除其余特征,这样会得到泛化能力更好更简单的模型。
如何判断每个特征的作用:
3种监督方法
1、单变量统计
2、基于模型的选择
3、迭代选择
1、单变量统计
计算每个特征和目标值之间的关系是否存在统计显著性,并选择最高置信度的特征。
对于分类问题,也被称为方差分析(ANOVA),关键性质就是它是单变量的,即只单独考虑每个特征
计算速得很快,并且不需要构建模型
sklearn中使用单变量特征选择,选择一项测试,确定p值,选择一种舍弃特征的方法
(1)将分类的特征选择应用于cancer数据集,并添加一些噪声数据提高问题难度
from sklearn.datasets import load_breast_cancer
from sklearn.feature_selection import SelectPercentile
from sklearn.model_selection import train_test_split
cancer = load_breast_cancer()
rng = np.random.RandomState(42)
noise = rng.normal(size=(len(cancer.data), 50))
X_w_noise = np.hstack([cancer.data, noise])
X_train, X_test, y_train, y_test = train_test_split(
X_w_noise, cancer.target, random_state=0, test_size=.5)`在这里插入代码片`
select = SelectPercentile(percentile=50)
select.fit(X_train, y_train)
X_train_selected = select.transform(X_train)
print("X_train.shape: {}".format(X_train.shape))
print("X_train_selected.shape: {}".format(X_train_selected.shape))
特殊数量减少
(2)查看哪些特征被选中(get_support)
mask = select.get_support()
print(mask)
plt.matshow(mask.reshape(1, -1), cmap='gray_r')
plt.xlabel("Sample index")
plt.yticks(())
返回所选特征的布尔遮罩
大多数选择的都是原始特征,并且大多数噪声特征都被删除
(3)比较逻辑回归在所有特征上的性能与仅使用所选特征的性能
from sklearn.linear_model import LogisticRegression
X_test_selected = select.transform(X_test)
lr = LogisticRegression()
lr.fit(X_train, y_train)
print("Score with all features: {:.3f}".format(lr.score(X_test, y_test)))
lr.fit(X_train_selected, y_train)
print("Score with only selected features: {:.3f}".format(
lr.score(X_test_selected, y_test)))
在例子中,删除噪声数据可以提高性能
2、基于模型的特征选择
使用一个监督机器学习模型来判断每个特征的重要性,并且保留最重要的特征,特征选择模型为每个特征提供某种重要性度量,用这个度量可以对特征进行排序
1、决策树、基于决策树的模型:feature_importances_属性
2、线性模型:稀疏系数
基于模型的特征选择,需要使用SelecteFromModel变换器
(1)使用中位数作为阈值
from sklearn.feature_selection import SelectFromModel
from sklearn.ensemble import RandomForestClassifier
select = SelectFromModel(
RandomForestClassifier(n_estimators=100, random_state=42),
threshold="median")
(2)拟合模型
select.fit(X_train, y_train)
X_train_l1 = select.transform(X_train)
print("X_train.shape: {}".format(X_train.shape))
print("X_train_l1.shape: {}".format(X_train_l1.shape))
X_train.shape: (284, 80)
X_train_l1.shape: (284, 40)
(3)查看特征
mask = select.get_support()
plt.matshow(mask.reshape(1, -1), cmap='gray_r')
plt.xlabel("Sample index")
plt.yticks(())
除了两个原始特征,其他原始特征都被选中
(4)查看性能
X_test_l1 = select.transform(X_test)
score = LogisticRegression().fit(X_train_l1, y_train).score(X_test_l1, y_test)
print("Test score: {:.3f}".format(score))
Test score: 0.951
利用更好的特征选择, 性能得到了提高
3、迭代特征选择
构建一系列模型,每个模型使用不同数量的特征
两种基本方法:
1、开始时没有特征,然后逐个添加特征,直到满足某个终止条件
2、从所有特征开始,然后逐个删除特征,直到满足某个终止条件
计算成本更高
特殊方法:递归特征消除RFE
(1)使用随机森林分类器模型的递归特征消除选择的特征
from sklearn.feature_selection import RFE
select = RFE(RandomForestClassifier(n_estimators=100, random_state=42),
n_features_to_select=40)
select.fit(X_train, y_train)
mask = select.get_support()
plt.matshow(mask.reshape(1, -1), cmap='gray_r')
plt.xlabel("Sample index")
plt.yticks(())
相比之前的结果更好,但还是漏了一个特征
(2)测试使用RFE做特征选择时逻辑回归模型的精度
X_train_rfe = select.transform(X_train)
X_test_rfe = select.transform(X_test)
score = LogisticRegression().fit(X_train_rfe, y_train).score(X_test_rfe, y_test)
print("Test score: {:.3f}".format(score))
Test score: 0.951
(3)利用RFE内使用的模型进行预测
print("Test score: {:.3f}".format(select.score(X_test, y_test)))
Test score: 0.951
只要选择了正确的特征,线性模型的表现与随机森林一样好
如果不确定何时选用哪些特征作为机器学习算法的输入,那么自动化特征选择可能特别有用