【特征选择】包裹式特征选择法

原创博文,转载请注明出处!

      包裹式特征选择法的特征选择过程与学习器相关,使用学习器的性能作为特征选择的评价准则,选择最有利于学习器性能的特征子集。常用的包裹式特征选择法有递归特征消除法RFE。

#  递归特征消除法

  • 递归特征消除法RFE

    递归特征消除法的英文全名为recursive feature elimination,简称RFE。首先设定n_features_to_select( 经过特征选择后,特征集中剩余的特征个数),然后使用一个基模型来进行多轮训练,每轮训练后移除若干权值系数的特征,再基于新的特征集进行下一轮训练,直至特征个数为n_features_to_select。sklearn在feature_selection模块中封装了RFE。sklearn中RFE的主要参数为:

* estimator  -- 基学习器

* n_features_to_select -- 经过特征选择后,特征集中剩余的特征个数

* step -- 默认1,即每次迭代移除一个特征

* verbose -- 默认0,不显示中间过程

  • 结合交叉验证的递归特征消除法RFECV

    RFE设定n_features_to_select时存在一定的盲目性,可能使得模型性能变差。比如,n_features_to_select过小时,相关特征可能被移除特征集,信息丢失;n_features_to_select过大时,无关特征没有被移除特征集,信息冗余。在工程实践中,RFE通过CV寻找最优的n_features_to_select,sklearn封装了结合CV的RFE,即RFECV。在RFECV中,如果减少特征会造成性能损失,那么将不会去除任何特征。RFECV适合选取单模型特征,但是计算量较大。sklearn中RFECV的主要参数为:

* estimator -- 基学习器

* step -- 默认1,即每次迭代移除一个特征

* cv – 默认2,即二折交叉验证的方式进行特征选择

* scoring -- 根据学习目标设定的模型评分标准

* verbose -- 默认0,即不显示中间过程

* n_jobs -- 默认1,即不使用并行计算,单核计算

# 递归特征消除法的工程实践

    下面程序中,分别使用原始特征集、经过RFE特征选择后的特征集、经过RFECV特征选择后的特征集,训练线性支持向量机,结果显示使用RFECV处理后的特征集训练线性支持向量机模型效果最好。

# -*- coding: utf-8 -*-
"""
# author: wanglei5205
# blog:http://cnblogs.com/wanglei5205
# github:http://github.com/wanglei5205
"""
### 生成数据
from sklearn.datasets import make_classification
X, y = make_classification(n_samples=1000,         # 样本个数
                           n_features=25,          # 特征个数
                           n_informative=3,        # 有效特征个数
                           n_redundant=2,          # 冗余特征个数(有效特征的随机组合)
                           n_repeated=0,           # 重复特征个数(有效特征和冗余特征的随机组合)
                           n_classes=8,            # 样本类别
                           n_clusters_per_class=1, # 簇的个数
                           random_state=0)

### 特征选择
# RFE
from sklearn.svm import SVC
svc = SVC(kernel="linear")

from sklearn.feature_selection import RFE
rfe = RFE(estimator = svc,           # 基分类器
          n_features_to_select = 2,  # 选择特征个数
          step = 1,                  # 每次迭代移除的特征个数 
          verbose = 1                # 显示中间过程
          ).fit(X,y)
X_RFE = rfe.transform(X)
print("RFE特征选择结果——————————————————————————————————————————————————")
print("有效特征个数 : %d" % rfe.n_features_)
print("全部特征等级 : %s" % list(rfe.ranking_))
"""
有效特征个数 : 2
全部特征等级 : [6, 1, 13, 20, 16, 7, 18, 2, 3, 22, 24, 12, 17, 11, 14, 23, 9, 15, 1, 21, 8, 10, 4, 5, 19]
"""
# RFECV
from sklearn.svm import SVC
svc = SVC(kernel="linear")

from sklearn.model_selection import StratifiedKFold
from sklearn.feature_selection import RFECV
rfecv = RFECV(estimator=svc,          # 学习器
              step=1,                 # 移除特征个数
              cv=StratifiedKFold(2),  # 交叉验证次数
              scoring='accuracy',     # 学习器的评价标准
              verbose = 1,
              n_jobs = 1
              ).fit(X, y)
X_RFECV = rfecv.transform(X)
print("RFECV特征选择结果——————————————————————————————————————————————————")
print("有效特征个数 : %d" % rfecv.n_features_)
print("全部特征等级 : %s" % list(rfecv.ranking_))
"""
有效特征个数 : 3
全部特征等级 : [5, 1, 12, 19, 15, 6, 17, 1, 2, 21, 23, 11, 16, 10, 13, 22, 8, 14, 1, 20, 7, 9, 3, 4, 18]
"""

### 数据拆分
from sklearn.model_selection import train_test_split
x_a_train,x_a_test,y_a_train,y_a_test = train_test_split(X,y,random_state = 33,test_size = 0.25)
x_b_train,x_b_test,y_b_train,y_b_test = train_test_split(X_RFE,y,random_state = 33,test_size = 0.25)
x_c_train,x_c_test,y_c_train,y_c_test = train_test_split(X_RFECV,y,random_state = 33,test_size = 0.25)

### 效果比较
svc_a = SVC(kernel="linear").fit(x_a_train,y_a_train)
svc_b = SVC(kernel="linear").fit(x_b_train,y_b_train)
svc_c = SVC(kernel="linear").fit(x_c_train,y_c_train)

print("效果比较————————————————————————————————————————————————————————")
print("no feature select",svc_a.score(x_a_test,y_a_test))
print("RFE feature select",svc_b.score(x_b_test,y_b_test))
print("RFECV feature select",svc_c.score(x_c_test,y_c_test))

"""
no feature select 0.74
RFE feature select 0.448
RFECV feature select 0.84
"""
posted @ 2018-05-01 21:08  wanglei5205  阅读(9710)  评论(0编辑  收藏  举报
levels of contents