在递归特征消除的每个折叠中对估计器进行超参数估计

时间:2015-04-09 12:19:01

标签: python machine-learning scikit-learn feature-selection rfe

我正在使用sklearn使用RFECV模块通过交叉验证执行递归功能消除。 RFE涉及在全套特征上重复训练估计器,然后移除信息量最少的特征,直到收敛到最佳数量的特征。

为了通过估算器获得最佳性能,我想为每个要素数量的选择最佳超参数(为清晰起见而编辑)。估计器是一个线性SVM,因此我只关注C参数。

最初,我的代码如下。但是,这只是在开始时对C进行了一次网格搜索,然后在每次迭代时使用相同的C.

from sklearn.cross_validation import StratifiedKFold
from sklearn.feature_selection import RFECV
from sklearn import svm, grid_search

def get_best_feats(data,labels,c_values):

    parameters = {'C':c_values}

    # svm1 passed to clf which is used to grid search the best parameters
    svm1 = SVC(kernel='linear')
    clf = grid_search.GridSearchCV(svm1, parameters, refit=True)
    clf.fit(data,labels)
    #print 'best gamma',clf.best_params_['gamma']

    # svm2 uses the optimal hyperparameters from svm1
    svm2 = svm.SVC(C=clf.best_params_['C'], kernel='linear')
    #svm2 is then passed to RFECVv as the estimator for recursive feature elimination
    rfecv = RFECV(estimator=svm2, step=1, cv=StratifiedKFold(labels, 5))      
    rfecv.fit(data,labels)                                                     

    print "support:",rfecv.support_
    return data[:,rfecv.support_]

RFECV的文档提供参数" estimator_params:外部估算器的参数。当RFE对象作为参数传递给例如sklearn.grid_search.GridSearchCV对象时,用于进行网格搜索。"

因此,我想尝试传递我的对象' rfecv'到网格搜索对象,如下:

def get_best_feats2(data,labels,c_values):

    parameters = {'C':c_values   
    svm1 = SVC(kernel='linear')
    rfecv = RFECV(estimator=svm1, step=1, cv=StratifiedKFold(labels, 5), estimator_params=parameters)
    rfecv.fit(data, labels)

    print "Kept {} out of {} features".format((data[:,rfecv.support_]).shape[1], data.shape[1])


    print "support:",rfecv.support_
    return data[:,rfecv.support_]

X,y = get_heart_data()


c_values = [0.1,1.,10.]
get_best_feats2(X,y,c_values)

但是这会返回错误:

max_iter=self.max_iter, random_seed=random_seed)
File "libsvm.pyx", line 59, in sklearn.svm.libsvm.fit (sklearn/svm   /libsvm.c:1674)
TypeError: a float is required

所以我的问题是:我如何将rfe对象传递给网格搜索,以便对递归特征消除的每次迭代进行交叉验证?

由于

1 个答案:

答案 0 :(得分:5)

因此,您想在SVM中对C中的C进行网格搜索,以获取RFE中的每个功能数量吗?或者对于RFECV中的每个CV迭代?从你的最后一句,我猜它是前者。

您可以RFE(GridSearchCV(SVC(), param_grid))来实现这一目标, 虽然我不确定这实际上是否有用。

我不认为第二种可能现在(但很快)。你可以做GridSeachCV(RFECV(), param_grid={'estimator__C': Cs_to_try}),但是它会在彼此内部进行两组交叉验证。

更新: GridSearchCV没有coef_,因此第一个失败。 一个简单的解决方法:

class GridSeachWithCoef(GridSearchCV):
    @property
    def coef_(self):
        return self.best_estimator_.coef_

然后使用它。