点击上方
“
小白学视觉
”,选择加"
星标
"或“
置顶
”
重磅干货,第一时间送达
链接:https://towardsdatascience.com/feature-selection-techniques-1bfab5fe0784
著作权归作者所有,本文仅作学术分享,若侵权,请联
系后台删文处理
据《福布斯》报道,每天大约会有 250 万字节的数据被产生。然后,可以使用数据科学和机器学习技术对这些数据进行分析,以便提供分析和作出预测。尽管在大多数情况下,在开始任何统计分析之前,需要先对最初收集的数据进行预处理。有许多不同的原因导致需要进行预处理分析,例如:
-
收集的数据格式不对(如 SQL 数据库、JSON、CSV 等)
-
-
-
减少数据集中存在的固有噪声(部分存储数据可能已损坏)
-
在本文中,我将通俗介绍如何使用 python 减少 kaggle Mushroom Classification 数据集中的特性数量。
减少统计分析期间要使用的特征的数量可能会带来一些好处,例如:
事实上,统计上证明,当执行机器学习任务时,存在针对每个特定任务应该使用的最佳数量的特征(图 1)。如果添加的特征比必要的特征多,那么我们的模型性能将下降(因为添加了噪声)。真正的挑战是找出哪些特征是最佳的使用特征(这实际上取决于我们提供的数据量和我们正在努力实现的任务的复杂性)。这就是特征选择技术能够帮到我们的地方!
1.过滤方法=过滤我们的数据集,只取包含所有相关特征的子集(例如,使用 Pearson 相关的相关矩阵)。
2.遵循过滤方法的相同目标,但使用机器学习模型作为其评估标准(例如,向前/向后/双向/递归特征消除)。我们将一些特征输入机器学习模型,评估它们的性能,然后决定是否添加或删除特征以提高精度。因此,这种方法可以比滤波更精确,但计算成本更高。
3.嵌入方法。与过滤方法一样,嵌入方法也使用机器学习模型。这两种方法的区别在于,嵌入的方法检查 ML 模型的不同训练迭代,然后根据每个特征对 ML 模型训练的贡献程度对每个特征的重要性进行排序。
在本文中,我将使用 Mushroom Classification 数据集,通过查看给定的特征来尝试预测蘑菇是否有毒。在这样做的同时,我们将尝试不同的特征消除技术,看看它们会如何影响训练时间和模型整体的精度。
数据下载:
https://github.com/ffzs/dataset/blob/master/
mushrooms
.csv
图 3:Mushroom Classification 数据集
在将这些数据输入机器学习模型之前,我决定对所有分类变量进行 one hot 编码,将数据分为特征(x)和标签(y),最后在训练集和测试集中进行。
X = df.drop(['class'], axis = 1)
Y = df['class']
X = pd.get_dummies(X, prefix_sep='_')
Y = LabelEncoder().fit_transform(Y)
X2 = StandardScaler().fit_transform(X)
X_Train, X_Test, Y_Train, Y_Test = train_test_split(X2, Y, test_size = 0.30, random_state = 101)
基于集合的决策树模型(如随机森林)可以用来对不同特征的重要性进行排序。了解我们的模型最重要的特征对于理解我们的模型如何做出预测(使其更易于解释)是至关重要的。同时,我们可以去掉那些对我们的模型没有任何好处的特征。
start = time.process_time()
trainedforest = RandomForestClassifier(n_estimators=700).fit(X_Train,Y_Train)
print(time.process_time() - start)
predictionforest = trainedforest.predict(X_Test)
print(confusion_matrix(Y_Test,predictionforest))
print(classification_report(Y_Test,predictionforest))
如下图所示,使用所有特征训练一个随机森林分类器,在大约 2.2 秒的训练时间内获得 100% 的准确率。在下面的每个示例中,每个模型的训练时间都将打印在每个片段的第一行,供你参考。
一旦我们的随机森林分类器得到训练,我们就可以创建一个特征重要性图,看看哪些特征对我们的模型预测来说是最重要的(图 4)。在本例中,下面只显示了前 7 个特性。
figure(num=None, figsize=(20, 22), dpi=80, facecolor='w', edgecolor='k')
feat_importances = pd.Series(trainedforest.feature_importances_, index= X.columns)
feat_importances.nlargest(7).plot(kind='barh')
现在我们知道了哪些特征被我们的随机森林认为是最重要的,我们可以尝试使用前 3 个来训练我们的模型。
X_Reduced = X[['odor_n','odor_f', 'gill-size_n','gill-size_b']]
X_Reduced = StandardScaler().fit_transform(X_Reduced)
X_Train2, X_Test2, Y_Train2, Y_Test2 = train_test_split(X_Reduced, Y, test_size = 0.30, random_state = 101)
start = time.process_time()
trainedforest = RandomForestClassifier(n_estimators=700).fit(X_Train2,Y_Train2)
print(time.process_time() - start)
predictionforest = trainedforest.predict(X_Test2)
print(confusion_matrix(Y_Test2,predictionforest))
print(classification_report(Y_Test2,predictionforest))
正如我们在下面看到的,仅仅使用 3 个特征,只会导致准确率下降 0.03%,训练时间减少一半。
我们还可以通过可视化一个训练过的决策树来理解如何进行特征选择。
start = time.process_time()
trainedtree = tree.DecisionTreeClassifier().fit(X_Train, Y_Train)
print(time.process_time() - start)
predictionstree = trainedtree.predict(X_Test)
print(confusion_matrix(Y_Test,predictionstree))
print(classification_report(Y_Test,predictionstree))
树结构顶部的特征是我们的模型为了执行分类而保留的最重要的特征。因此,只选择顶部的前几个特征,而放弃其他特征,可能创建一个准确度非常可观的模型。
import graphviz
from sklearn.tree import DecisionTreeClassifier, export_graphviz
data = export_graphviz(trainedtree,out_file=None,feature_names= X.columns,
class_names=['edible', 'poisonous'],
filled=True, rounded=True,
max_depth=2,
special_characters=True)
graph = graphviz.Source(data)
graph
递归特征消除(RFE)将机器学习模型的实例和要使用的最终期望特征数作为输入。然后,它递归地减少要使用的特征的数量,采用的方法是使用机器学习模型精度作为度量对它们进行排序。
创建一个 for 循环,其中输入特征的数量是我们的变量,这样就可以通过跟踪在每个循环迭代中注册的精度,找出我们的模型所需的最佳特征数量。使用 RFE 支持方法,我们可以找出被评估为最重要的特征的名称(rfe.support 返回一个布尔列表,其中 true 表示一个特征被视为重要,false 表示一个特征不重要)。
from sklearn.feature_selection import RFE
model = RandomForestClassifier(n_estimators=700)
rfe = RFE(model, 4)
start = time.process_time()
RFE_X_Train = rfe.fit_transform(X_Train,Y_Train)
RFE_X_Test = rfe.transform(X_Test)
rfe = rfe.fit(RFE_X_Train,Y_Train)
print(time.process_time() - start)
print("Overall Accuracy using RFE: ", rfe.score(RFE_X_Test,Y_Test))