社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Python

推荐 :使用Python实现机器学习特征选择的4种方法(附代码)

数据分析 • 6 年前 • 494 次点击  

作者: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万人群。

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/31606
 
494 次点击