使用 scikit-learn 进行递归特征消除和网格搜索

Posted

技术标签:

【中文标题】使用 scikit-learn 进行递归特征消除和网格搜索【英文标题】:Recursive feature elimination and grid search using scikit-learn 【发布时间】:2014-07-12 00:41:32 【问题描述】:

我想通过嵌套网格搜索执行递归特征消除,并使用 scikit-learn 对每个特征子集进行交叉验证。从 RFECV 文档看来,使用 estimator_params 参数支持这种类型的操作:

estimator_params : dict

    Parameters for the external estimator. Useful for doing grid searches.

但是,当我尝试将超参数网格传递给 RFECV 对象时

from sklearn.datasets import make_friedman1
from sklearn.feature_selection import RFECV
from sklearn.svm import SVR
X, y = make_friedman1(n_samples=50, n_features=10, random_state=0)
estimator = SVR(kernel="linear")
selector = RFECV(estimator, step=1, cv=5, estimator_params='C': [0.1, 10, 100, 1000])
selector = selector.fit(X, y)

我收到类似的错误

  File "U:/My Documents/Code/ModelFeatures/bin/model_rcc_gene_features.py", line 130, in <module>
    selector = selector.fit(X, y)
  File "C:\Python27\lib\site-packages\sklearn\feature_selection\rfe.py", line 336, in fit
    ranking_ = rfe.fit(X_train, y_train).ranking_
  File "C:\Python27\lib\site-packages\sklearn\feature_selection\rfe.py", line 146, in fit
    estimator.fit(X[:, features], y)
  File "C:\Python27\lib\site-packages\sklearn\svm\base.py", line 178, in fit
    fit(X, y, sample_weight, solver_type, kernel, random_seed=seed)
  File "C:\Python27\lib\site-packages\sklearn\svm\base.py", line 233, in _dense_fit
    max_iter=self.max_iter, random_seed=random_seed)
  File "libsvm.pyx", line 59, in sklearn.svm.libsvm.fit (sklearn\svm\libsvm.c:1628)
TypeError: a float is required

如果有人能告诉我我做错了什么,将不胜感激,谢谢!

编辑:

在 Andreas 的反应变得清晰之后,下面是一个 RFECV 结合网格搜索的工作示例。

from sklearn.datasets import make_friedman1
from sklearn.feature_selection import RFECV
from sklearn.grid_search import GridSearchCV
from sklearn.svm import SVR
X, y = make_friedman1(n_samples=50, n_features=10, random_state=0)
param_grid = ['C': 0.01, 'C': 0.1, 'C': 1.0, 'C': 10.0, 'C': 100.0, 'C': 1000.0, 'C': 10000.0]
estimator = SVR(kernel="linear")
selector = RFECV(estimator, step=1, cv=4)
clf = GridSearchCV(selector, 'estimator_params': param_grid, cv=7)
clf.fit(X, y)
clf.best_estimator_.estimator_
clf.best_estimator_.grid_scores_
clf.best_estimator_.ranking_

【问题讨论】:

Read this answer to avoid warning 【参考方案1】:

DavidS 提供的代码对我不起作用(sklearn 0.18),但需要对 param_grid 及其用法进行一些小改动。

from sklearn.datasets import make_friedman1
from sklearn.feature_selection import RFECV
from sklearn.model_selection import GridSearchCV
from sklearn.svm import SVR
X, y = make_friedman1(n_samples=50, n_features=10, random_state=0)
param_grid = ['estimator__C': [0.01, 0.1, 1.0, 10.0, 100.0, 1000.0]]
estimator = SVR(kernel="linear")
selector = RFECV(estimator, step=1, cv=4)
clf = GridSearchCV(selector, param_grid, cv=7)
clf.fit(X, y)
clf.best_estimator_.estimator_
clf.best_estimator_.grid_scores_
clf.best_estimator_.ranking_

【讨论】:

Danke schoen )) 这就像一个魅力。我什至会在最后 3 个语句中添加 print() 以显示所有语句的输出。【参考方案2】:

很遗憾,RFECV 仅限于交叉验证组件的数量。你不能用它搜索 SVM 的参数。错误是因为 SVC 期望浮点数为 C,而您给了它一个列表。

您可以执行以下两种操作之一:在 RFECV 上运行 GridSearchCV,这将导致将数据拆分为两次折叠(在 GridSearchCV 内和一次在 RFECV 内),但搜索组件数量将是有效的,或者您可以仅在 RFE 上执行 GridSearchCV,这将导致数据的单次拆分,但对 RFE 估计器的参数的扫描效率非常低。

如果您想让文档字符串不那么模棱两可,欢迎提出拉取请求 :)

【讨论】:

好的,谢谢你的帮助,现在清楚多了。我在原始帖子中添加了一个使用 RFECV 进行网格搜索的示例,以供其他可能遇到困难的人使用。另外,提交了一个包含一些修订文档的拉取请求,希望对您有所帮助。 我也感谢您的解释,因为我遇到了同样的问题。是否已经提出改进文档的拉取请求?如果还没有完成,我很乐意贡献。 @AndreasMueller 如果您知道这个问题的答案,请告诉我:***.com/questions/55609339/… 非常感谢 :)

以上是关于使用 scikit-learn 进行递归特征消除和网格搜索的主要内容,如果未能解决你的问题,请参考以下文章

使用 scikit-learn 对 SVR 进行递归特征消除和网格搜索

在 scikit-learn 中结合递归特征消除和网格搜索

GPU 上的 SKLearn RFE(递归特征消除)

Scikit-learn 中的特征选择遇到了混合变量类型的问题

如何在 R 中使用 SVM 进行递归特征消除

使用RFECV递归特征消除 (Recursive Feature Elimination)进行特征筛选详解及实战