推荐 :使用Python实现机器学习特征选择的4种方法(附代码)
作者:Sugandha?Lahoti;翻译:李洁 ;校对:杨光
本文约3500字,建议阅读13分钟。
本文中,我们将研究从数据集中选择特征的不同方法;同时通过使用Python中Scikit-learn?(sklearn)库实现讨论了特征选择算法的类型。
注:本文节选自Ankit?Dixit所著的《集成机器学习》(Ensemble?Machine?Learning)一书。这本书组合强大的机器学习算法来建立优化模型,可以作为初学者的指南。
在本文中,我们将研究从数据集中选择特征的不同方法;同时通过使用Python中Scikit-learn?(sklearn)库实现讨论了特征选择算法的类型:
单变量选择
递归特征消除(RFE)
主成分分析(PCA)
选择重要特征(特征重要度)
?
我们简要介绍了前三种算法及其实现。然后我们将详细讨论在数据科学社区中广泛使用的选择重要特征(特性重要度)部分的内容。
单变量选择
统计测试可用于选择那些与输出变量关系最强的特征。
scikit-learn库提供了SelectKBest类,它可以与一组不同的统计测试一起使用,以选择特定数量的特征。
下面的例子使用chi?非负性特征的统计测试,从皮马印第安人糖尿病发病数据集中选择了四个最好的特征:
1.?#Feature Extraction with Univariate Statistical Tests (Chi-squared for classification)
2.?#Import the required packages
3.?#Import pandas to read csv import pandas
4.?#Import numpy for array related operations import numpy
5.?#Import sklearn's feature selection algorithm
6.?from?sklearn.feature_selection import?SelectKBest
7.?#Import chi2 for performing chi square test from sklearn.feature_selection import chi2
8.?#URL for loading the dataset
9.?url?="https://archive.ics.uci.edu/ml/machine-learning-databases/pima-indians?diabetes/pima-indians-diabetes.data"
10.?#Define the attribute names
11.?names = ['preg', 'plas', 'pres', 'skin', 'test', 'mass', 'pedi', 'age', 'class']
12.?#Create pandas data frame by loading the data from URL
13.?dataframe = pandas.read_csv(url, names=names
14.?#Create array from data values
15.?array = dataframe.values
16.?#Split the data into input and target
17.?X?=?array[:,??0:8]
18.?Y?=?array[:,8]
19.?#We will select the features using chi square
20.?test = SelectKBest(score_func=chi2, k=4)
21.?#Fit the function for ranking the features by score
22.?fit = test.fit(X, Y)
23.?#Summarize scores numpy.set_printoptions(precision=3) print(fit.scores_)
24.?#Apply the transformation on to dataset
25.?features = fit.transform(X)
26.?#Summarize?selected?features?print(features[0:5,:])
你可以看到每个参数的得分,以及所选择的四个参数(得分最高的):plas、test、mass和age。
每个特征的分数为:
1.??[111.52???1411.887?17.605?53.108 ?2175.565 ??127.669 5.393
2.???181.304]
被选出的特征是:
1.?[[148. 0. 33.6?50. ]
2.?[85. 0. 26.6?31. ]
3.?[183. 0. 23.3?32. ]
4.?[89. 94. 28.1?21. ]
5.?[137. 168. 43.1?33. ]]
递归特征消除(RFE)
RFE的工作方式是递归地删除参数并在保留的参数上构建模型。它使用模型精度来判断哪些属性(以及属性的组合)对预测目标参数贡献最大。你可以在scikit-learn的文档中了解更多关于RFE类的信息。
下面的示例使用RFE和logistic回归算法来选出前三个特征。算法的选择并不重要,只需要熟练并且一致:
1.?#Import the required packages
2.?#Import pandas to read csv import pandas
3.?#Import numpy for array related operations import numpy
4.?#Import sklearn's feature selection algorithm from sklearn.feature_selection import RFE
5.?#Import LogisticRegression for performing chi square test from sklearn.linear_model import LogisticRegression
6.?#URL for loading the dataset
7.?url =
8.?"https://archive.ics.uci.edu/ml/machine-learning-databases/pima-indians-dia?betes/pima-indians-diabetes.data"
9.?#Define the attribute names
10.?names = ['preg', 'plas', 'pres', 'skin', 'test', 'mass', 'pedi', 'age', 'class']
11.?#Create pandas data frame by loading the data from URL
12.?dataframe = pandas.read_csv(url, names=names)
13.?
14.?#Create array from data values
15.?array = dataframe.values
16.?
17.?#Split the data into input and target
18.?X?=?array[:,:8]
19.?Y?=?array[:,8]
20.?#Feature extraction
21.?model = LogisticRegression() rfe = RFE(model, 3)
22.?fit = rfe.fit(X, Y)
23.?print("Num?Features:?%d"%?fit.n_features_)?print("Selected?Features:?%s"%?fit.support_)
24.?print("Feature?Ranking:?%s"%?fit.ranking_)
执行完上述代码后,我们可以得到:
1.?Num?Features:?3
2.?Selected?Features:?[?True?False?False?False?False??True??True?False]
3.?Feature?Ranking:?[1?2?3?5?6?1?1?4]
你可以看到RFE选择了前三个特性,即preg、mass和pedi。这些在support_数组中被标记为True,在ranking_数组中被标记为首选(标记为1)。
主成分分析
PCA使用线性代数将数据集转换为压缩格式。通常,它被认为是一种数据约简技术。PCA的一个属性是,你可以选择转换结果中的维数或主成分的数量。
在接下来的例子中,我们使用PCA并选择了三个主成分:
1.?#Import the required packages
2.?#Import pandas to read csv import pandas
3.?#Import numpy for array related operations import numpy
4.?#Import sklearn's PCA algorithm
5.?from?sklearn.decomposition import?PCA
6.?#URL for loading the dataset
7.?url =
8.?"https://archive.ics.uci.edu/ml/machine-learning-databases/pima-indians?diabetes/pima-indians-diabetes.data"
9.?#Define the attribute names
10.?names = ['preg', 'plas', 'pres', 'skin', 'test', 'mass', 'pedi', 'age', 'class']
11.?dataframe = pandas.read_csv(url, names=names)
12.?#Create array from data values
13.?array = dataframe.values
14.?#Split the data into input and target
15.?X?=?array[:,0:8]
16.?Y?=?array[:,8]
17.?#Feature extraction
18.?pca = PCA(n_components=3) fit = pca.fit(X)
19.?#Summarize components
20.?print("Explained?Variance:?%s")?%?fit.explained_variance_ratio_
21.?print(fit.components_)
你可以看到,转换后的数据集(三个主成分)与源数据几乎没有相似之处:
1.??Explained?Variance:?[?0.88854663???0.06159078??0.02579012]
2.??[[?-2.02176587e-03 ???9.78115765e-02 1.60930503e-02 ???6.07566861e-02
3.?9.93110844e-01 ?????????1.40108085e-02 5.37167919e-04 ??-3.56474430e-03]
4.??[ -2.26488861e-02 ??-9.72210040e-01 ?????????????-1.41909330e-01 ?5.78614699e-02 9.46266913e-02 ??-4.69729766e-02 ??????????????-8.16804621e-04 ?-1.40168181e-01
5.??[ -2.24649003e-02 1.43428710e-01 ????????????????-9.22467192e-01 ?-3.07013055e-01 2.09773019e-02 ??-1.32444542e-01 ???????????????-6.39983017e-04 ?-1.25454310e-01]]
选择重要特征(特性重要度)
特征重要度是一种利用训练好的有监督分类器来选择特征的技术。当我们训练分类器(如决策树)时,我们计算每个参数以创建分割;我们可以使用这个度量作为特征选择器。让我们来详细了解一下。
随机森林由于其相对较好的准确性、鲁棒性和易用性而成为最受欢迎的机器学习方法之一。它们还提供了两种简单易行的特征选择方法——均值降低杂质和均值降低准确度。
随机森林由许多决策树组成。决策树中的每个节点都是一个基于单个特征的条件,其设计目的是将数据集分割成两个,以便相似的响应值最终出现在相同的集合中。选择(局部)最优条件的度量叫做杂质。对于分类问题,它通常是基尼杂质或信息增益/熵,而对于回归树,它是方差。因此,当训练一棵树时,可以通过每个特征减少的树中加权杂质的多少来计算。对于森林,可以对每个特征的杂质减少量进行平均,并根据该方法对特征进行排序。
让我们看一下如何使用随机森林分类器来进行特征选择,并评估特征选择前后分类器的准确性。我们将使用Otto数据集。该数据集可从kaggle免费获得(你需要注册kaggle才能下载该数据集)。你可以从https://www.kaggle.com/c/otto-group-product-?classifics-challenge/data下载训练集train.csv.zip,然后将解压缩的train.csv文件放在你的工作目录中。
这个数据集描述了超过61,000个产品的93个模糊细节,这些产品被分成10个产品类别(例如,时尚类、电子产品类等)。输入参数是某种类型的不同事件的计数。
训练目标是对新产品作为10个类别中每一个类别的概率数组做出预测,并使用多级对数损失(也称为交叉熵)对模型进行评估。
我们将从导入所有库开始:
1.?#Import the supporting libraries
2.?#Import pandas to load the dataset from csv file
3.?from?pandas import?read_csv
4.?#Import numpy for array based operations and calculations
5.?import?numpy as np
6.?#Import Random Forest classifier class from sklearn
7.?from?sklearn.ensemble import?RandomForestClassifier
8.?#Import feature selector class select model of sklearn
9.?????????from sklearn.feature_selection?
10.?????????import?SelectFromModel
11.?????????np.random.seed(1)
定义一个方法用于将我们的数据集分为训练数据和测试数据;我们将在训练数据部分对数据集进行训练,测试数据部分将用于训练模型的评估:
1.?#Function to create Train and Test set from the original dataset
2.?def?getTrainTestData(dataset,split):
3.?????np.random.seed(0)
4.?????training = []
5.?????testing = []
6.?????np.random.shuffle(dataset) shape = np.shape(dataset)
7.?????trainlength = np.uint16(np.floor(split*shape[0]))
8.?????for?i?in?range(trainlength):?
9.?????????training.append(dataset[i])
10.?????for?i?in?range(trainlength,shape[0]):?
11.?????????testing.append(dataset[i])
12.?????training = np.array(training) testing = np.array(testing)
13.?????return?training,testing
还需要添加一个函数来评估模型的准确性;以预测输出和实际输出为输入,计算准确率百分比:
1.?#Function to evaluate model performance
2.?def?getAccuracy(pre,ytest):?
3.?????count = 0
4.?????for?i?in?range(len(ytest)):
5.?????????if?ytest[i]==pre[i]:?
6.?????????????count+=1
7.?????acc = float(count)/len(ytest)
8.?????return?acc
现在要导入数据集。我们将导入train.csv文件;该文件包含61,000多个训练实例。我们的示例将使用50000个实例,其中使用35,000个实例来训练分类器,并使用15,000个实例来测试分类器的性能:
1.?#Load dataset as pandas data frame
2.?data = read_csv('train.csv')
3.?#Extract attribute names from the data frame
4.?feat = data.keys()
5.?feat_labels = feat.get_values()
6.?#Extract data values from the data frame
7.?dataset = data.values
8.?#Shuffle the dataset
9.?np.random.shuffle(dataset)
10.?#We will select 50000 instances to train the classifier
11.?inst = 50000
12.?
13.?#Extract 50000 instances from the dataset
14.?dataset?=?dataset[0:inst,:]
15.?
16.?#Create Training and Testing data for performance evaluation
17.?train,test = getTrainTestData(dataset, 0.7)
18.?
19.?#Split data into input and output variable with selected features
20.?Xtrain?=?train[:,0:94]?ytrain?=?train[:,94]?shape?=?np.shape(Xtrain)
21.?
22.?print("Shape of the dataset ",shape)
23.?
24.?#Print the size of Data in MBs
25.?print("Size?of?Data?set?before?featureselection:?%.2f?MB"%(Xtrain.nbytes/1e6))
26.?
注意下这里的数据大小;由于我们的数据集包含约35000个训练实例,带有94个参数;我们的数据集非常大。让我们来看一下:
1.?Shape of the dataset (35000, 94)
2.?Size?of?Data?set?before?feature?selection:?26.32?MB
如你所见,我们的数据集中有35000行和94列,数据大小超过26MB。
在下一个代码块中,我们将配置我们的随机森林分类器;我们会使用250棵树,最大深度为30,随机特征的数量为7。其他超参数将是sklearn的默认值:
1.?#Lets select the test data for model evaluation purpose
2.?Xtest?=?test[:,0:94]?ytest?=?test[:,94]
3.?
4.?#Create a random forest classifier with the following Parameters
5.?trees = 250
6.?max_feat= 7
7.?max_depth = 30
8.?min_sample = 2
9.?clf = RandomForestClassifier(n_estimators=trees, max_features=max_feat, max_depth=max_depth, min_samples_split= min_sample, random_state=0, n_jobs=-1)
10.?
11.?#Train the classifier and calculate the training time
12.?import?time
13.?start = time.time()
14.?clf.fit(Xtrain, ytrain)
15.?end = time.time()
16.?
17.?#Lets Note down the model training time
18.?print("Execution?time?for?building?the?Tree?is:?%f"%(float(end)-?float(start)))
19.?pre = clf.predict(Xtest)
20.?
21.?#Let's?see?how?much?time?is?required?to?train?the?model?on?the?training?dataset:
22.?Execution?time?for?building?the?Tree?is:?2.913641
23.?
24.?#Evaluate the model performance for the test data
25.?acc = getAccuracy(pre, ytest)
26.?
27.?print("Accuracy of model before feature selection is %.2f"%(100*acc))
模型的精确度是:
1.?Accuracy of model before feature selection is 98.82
正如所看到的,我们获得了非常好的精确度,因为我们将几乎99%的测试数据分类为正确的类别。这意味着我们在15,000个实例中对大概14,823个实例进行了正确的分类。
所以,现在问题是:我们应该进一步改进吗?好吧,为什么不呢?如果可能的话,我们一定需要进行更多的改进;在这里,我们将使用特征重要度来选择特征。如你所知,在树的建造过程中,我们使用杂质度量来选择节点。选择杂质最少的参数值作为树中的节点。我们可以使用类似的标准来选择特征。我们可以给杂质更少的特征更多的重要度,这可以使用sklearn库的feature_importances_函数来实现。让我们来看一下每个特征的重要度:
1.?#Once?we?have?trained?the?model?we?will?rank?all?the?features?for?feature?in?zip(feat_labels,?clf.feature_importances_):
2.??print(feature)
3.??('id',?0.33346650420175183)
4.??('feat_1', 0.0036186958628801214)
5.??('feat_2', 0.0037243050888530957)
6.??('feat_3', 0.011579217472062748)
7.??('feat_4', 0.010297382675187445)
8.??('feat_5', 0.0010359139416194116)
9.??('feat_6', 0.00038171336038056165)
10.??('feat_7', 0.0024867672489765021)
11.??('feat_8', 0.0096689721610546085)
12.??('feat_9', 0.007906150362995093)
13.??('feat_10', 0.0022342480802130366)
14.?
正如你看到的,每个特征都有不同的重要度,这取决于它对最终预测的贡献值。
我们将使用这些重要度评分来对我们的特征进行排序;在接下来的部分中,我们将选取特征重要度大于0.01的特征进行模型训练:
1.?#Select features which have higher contribution in the final prediction
2.?sfm = SelectFromModel(clf, threshold=0.01)
3.?sfm.fit(Xtrain,ytrain)
4.?
这里,我们将根据所选的特征参数转换输入的数据集。在下一个代码块中,我们会转换数据集。然后,我们将检查新数据集的大小和形状:
1.?#Transform input dataset
2.?Xtrain_1 = sfm.transform(Xtrain)
3.?Xtest_1 ?= sfm.transform(Xtest)
4.?
5.?#Let's see the size and shape of new dataset
6.?print("Size?of?Data?set?before?feature?selection:?%.2f?MB"%(Xtrain_1.nbytes/1e6))
7.?shape = np.shape(Xtrain_1)
8.?print("Shape of the dataset ",shape)
9.?
10.?Size?of?Data?set?before?feature?selection:?5.60?MB?
11.?Shape of the dataset (35000, 20)
12.?
看到数据集的形状了吗?经过特征选择后,我们只剩下20个特征,这使得数据库的大小从26MB减少到了5.60?MB,比原来的数据集减少了80%左右。
在下一个代码块中,我们将使用与前面相同的超参数训练一个新的随机森林分类器,并在测试集上进行了测试。我们来看看修改训练集后得到的精确度是多少:
1.?#Model training time
2.?start = time.time() clf.fit(Xtrain_1, ytrain) end = time.time()
3.?print("Execution?time?for?building?the?Tree?is:?%f"%(float(end)-?float(start)))
4.?
5.?#Let's evaluate the model on test data
6.?pre = clf.predict(Xtest_1) count = 0
7.?acc2 = getAccuracy(pre, ytest)
8.?print("Accuracy after feature selection %.2f"%(100*acc2))
9.?
10.?Execution?time?for?building?the?Tree?is:?1.711518?
11.?Accuracy after feature selection 99.97
12.?
看到了吗!使用修改后的数据集,我们获得了99.97%的准确率,这意味着我们把14,996个实例分到了正确的类别,而之前我们只正确地分类了14,823个实例。
这是我们在特征选择过程中取得的巨大进步;我们可以将所有的结果总结如下表:
评估标准 | 特征选择前 | 特征选择后 |
特征数量 | 94 | 20 |
数据集大小 | 26.32MB | 5.60MB |
训练时间 | 2.91?s | 1.71?s |
精确度 | 98.82% | 99.97% |
上表显示了特征选择的实际优势。可以看到我们显著地减少了特征的数量,这减少了模型的复杂性和数据集的维度。在减小维度后,我们需要更少的训练时间,最终我们克服了过拟合的问题,获得了比以前更高的精确度。
本文我们共探讨了机器学习中特征选择的4种方法。
如果你发现这篇文章很有用,请阅读《集成机器学习》一书,了解关于叠加泛化和其他技术的更多信息。
原文标题:
4 ways to implement feature selection in Python for machine learning
原文链接:
https://hub.packtpub.com/4-ways-implement-feature-selection-python-machine-learning/
译者简介:李洁,香港科技大学电信学硕士毕业生,现任北京师范大学香港浸会大学联合学院?数据科学系助教。喜欢数据科学,喜欢阅读,喜欢研究代码和做手工。
END
转自:?数据派THU?公众号;
版权声明:本号内容部分来自互联网,转载请注明原文链接和作者,如有侵权或出处有误请和我们联系。
合作请加QQ:365242293??
数据分析(ID?:?ecshujufenxi?)互联网科技与数据圈自己的微信,也是WeMedia自媒体联盟成员之一,WeMedia联盟覆盖5000万人群。

关注公众号:拾黑(shiheibook)了解更多
[广告]赞助链接:
四季很好,只要有你,文娱排行榜:https://www.yaopaiming.com/
让资讯触达的更精准有趣:https://www.0xu.cn/
关注网络尖刀微信公众号随时掌握互联网精彩
- 1 习近平将发表二〇二六年新年贺词 7904141
- 2 2026年国补政策来了 7808738
- 3 东部战区:开火!开火!全部命中! 7712893
- 4 2026年这些民生政策将惠及百姓 7616985
- 5 小学食堂米线过期2.5小时被罚5万 7519709
- 6 解放军喊话驱离台军 原声曝光 7428214
- 7 为博流量直播踩烈士陵墓?绝不姑息 7327605
- 8 每月最高800元!多地发放养老消费券 7238391
- 9 数字人民币升级 1月1日起将计付利息 7141831
- 10 2026年1月1日起 一批新规将施行 7040675


数据分析
