花费了很长时间整理编辑,转载请联系作者授权,违者必究。
特征选择(Feature selection)是在构建预测模型的过程中减少输入变量的一个过程。它是机器学习中非常重要的一步并在很大程度上可以提高模型预测精度。这里我总结了一些机器学习中常见的比较有用的特征选择方法并附上相关python实现code。希望可以给大家一些启发。
首先,我们为什么要进行特征选择呢?它有以下几个优点:减少过拟合:冗余数据常常会给模型训练产生噪声,去掉这些噪声更有利于进行决策。
提高准确性:减少误导性数据意味着提高了建模准确性。
减少训练时间:更少的数据点降低了算法复杂度,并使训练速度更快。
减低模型复杂性:降低了模型的复杂性,并使其更易于解释。
Topic 1:变量排名(Variable Ranking)
变量排名是通过某些评分函数的值对要素进行排序的过程,通常会测量要素相关性。通常我们可以通过常见的统计检验来选择与输出变量关系最密切的那些特征。scikit-learn中的SelectKBest就是根据不同的统计测试选取k个分数最高的变量。
整个程序都是以sklearn自带的波士顿房价数据为例,进行变量选择。通过load_boston(),我们可以调取所需数据。下面的程序是对训练数据的提取。
import pandas as pd
#load sklearn built-in Boston dataset
from sklearn.datasets import load_boston
#Loading the dataset
x = load_boston()
data = pd.DataFrame(x.data, columns = x.feature_names)
data["MEDV"] = x.target
X = data.drop("MEDV",1) #Remove Target Variable to Get Feature Matrix
y = data["MEDV"] #Target Variable
data.head()数据样本
以下通过线性回归的F值来对各输入变量进行排序,并选出前五个预测效果最好的变量。我们可以看出,LSTAT分数最高,预测能力最好:
from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import f_regression
#apply SelectKBest class to extract top 5 best features
bestfeatures = SelectKBest(score_func=f_regression, k=5)
fit = bestfeatures.fit(X,y)
dfscores = pd.DataFrame(fit.scores_)
dfcolumns = pd.DataFrame(X.columns)
#concat two dataframes for better visualization
featureScores = pd.concat([dfcolumns,dfscores],axis=1)
featureScores.columns = ['Specs','Score'] #naming the dataframe columns
print(featureScores.nlargest(5,'Score')) #print 5 best features通过SelectKBest选出的前五个最优变量
Topic 2:相关性矩阵及热图(Correlation Matrix with Heatmap)
我们也可以通过要素之间或者要素和目标变量之间的相关性来做变量选择。要素之间的相关性越低越好,要素和目标函数之间的相关性越高越好。相关性可以通过热图(Heatmap)来视觉化。以下代码计算各个变量之间的相关性并通过seaborn的heatmap功能实现热图。热图中,数值越大,相关性越高。并且我们可以通过颜色的不同,直观的看出变量之间的相关性。
import seaborn as sns
from matplotlib import pyplot as plt
#get correlations of each features in dataset
corrmat = data.corr()
top_corr_features = corrmat.index
plt.figure(figsize=(20,20))
#plot heat map
g=sns.heatmap(data[top_corr_features].corr(),annot=True,cmap="RdYlGn")变量相关性热图
Topic 3:模型嵌入特征重要性属性(Built-in Feature Importance)
很多机器学习算法自带特征重要性属性。特征重要性(Feature Importance)提供数据中每个特征的得分,得分越高,该特征对输出变量的重要性或相关性就越高。最常见的就是基于树的回归器自带的特征重要性属性。这里以随机森林(Random Forest)预测方法为例,来选取最优的五个变量。下图中,RM预测能力最好,LSTAT预测能力第二。
from sklearn.ensemble import RandomForestRegressor
model = RandomForestRegressor ()
model.fit(X,y)
print(model.feature_importances_) #use inbuilt class feature_importances
#plot graph of feature importances for better visualization
feat_importances = pd.Series(model.feature_importances_, index=X.columns)
feat_importances.nlargest(5).plot(kind='barh')
plt.show()基于随机森林的特征重要性
Topic 4:递归式特征消除 (Recursive Feature Elimination)
递归式特征消除是通过不断递归地删除特征并根据剩余的特征建立模型的方法来优化模型。递归式特征消除根据特征消除的顺序对特征进行排序。在最坏的情况下,如果数据集包含N个要素,则RFE会对2N个要素组合进行贪婪搜索。下面的代码展示了个特征。以下以random forest为基础模型,实现递归式特征消除方法。这里我们选择最优的五个特征:
from sklearn.feature_selection import RFE
# Feature extraction
model = RandomForestRegressor()
rfe = RFE(model, 5)
fit = rfe.fit(X, y)
print("Num Features:%s" % (fit.n_features_))
print("Selected Features:%s" % (fit.support_))
print("Feature Ranking:%s" % (fit.ranking_))
我们还可以通过交叉验证(cross validation)让模型自主选择最优特征数,可以看到,11个变量是使模型预测效果最优:
from sklearn.svm import SVC
from sklearn.feature_selection import RFECV
# Instantiate RFECV visualizer with a random forest regressor
rfecv = RFECV(RandomForestRegressor())
rfecv.fit(X, y) # Fit the data to the visualizer
print("Optimal number of features :%d" % rfecv.n_features_)
# Plot number of features VS. cross-validation scores
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()
Topic 5: 特征序列选择 (Sequential Feature Selection)
特征序列选择可以分为以下三种:前向选择:该过程从一个空的特性集合开始,并逐个添加最优特征到集合中。
向后消除:该过程从所有特征集开始。通过逐步删除集合中剩余的最差特征。
前向选择和后向消除的组合:将前向选择和后向消除方法进行组合,在每个步骤中,选择最佳特征,并从其余特征中消除最差的。
以下是前向选择的例子
from mlxtend.feature_selection import SequentialFeatureSelector as sfs
from mlxtend.plotting import plot_sequential_feature_selection as plot_sfs
# Build RF regressor to use in feature selection
clf = RandomForestRegressor()
# Sequential Forward Selection
sfs = sfs(clf,
k_features=5,
forward=True,
floating=False,
verbose=2,
scoring='neg_mean_squared_error',
cv=5)
sfs = sfs.fit(X, y)
print('\nSequential Forward Selection (k=5):')
print(sfs.k_feature_idx_)
print('CV Score:')
print(sfs.k_score_)
fig = plot_sfs(sfs.get_metric_dict(), kind='std_err')
plt.title('Sequential Forward Selection (w. StdErr)')
plt.grid()
plt.show()
Topic 6:置换特征重要性(Permutation importance)
在训练好模型后,对其中一个特征变量进行随机置换顺序,如下图。如果单个变量的顺序打乱后导致模型预测精度降低,那说明这个变量是重要的。我们可以看出,LSTAT预测能力最好,RM预测能力排第二。
from sklearn.inspection import permutation_importance
rf = RandomForestRegressor()
rf.fit(X, y)
result = permutation_importance(rf, X, y, n_repeats=10,
random_state=42, n_jobs=2)
sorted_idx = result.importances_mean.argsort()
fig, ax = plt.subplots()
ax.boxplot(result.importances[sorted_idx].T,
vert=False, labels=X.columns[sorted_idx])
ax.set_title("Permutation Importances (test set)")
fig.tight_layout()
plt.show()
我们也可以将数据集分为training和validation:
from sklearn.model_selection import train_test_split
import eli5
from eli5.sklearn import PermutationImportance
train_X, val_X, train_y, val_y = train_test_split(X, y, random_state=1)
my_model = RandomForestRegressor().fit(train_X, train_y)
perm = PermutationImportance(my_model, random_state=1).fit(val_X, val_y)
eli5.show_weights(perm, feature_names = val_X.columns.tolist())
以上是我平时做机器学习,发现的比较好用的几类特征选择方法。我们可以看出,不同的特征选择方法对特征的选取会有不同的结果。这里我使用的数据相对简单。实际应用中,可能会有成百上千的特征,特征之间的关系也相对复杂。所以,多对比几种特征选择的方法,有助于我们挖掘特征与目标变量之间的真正联系。