没有简历的 GridSearch

数据挖掘 Python scikit-学习 回归 助推 网格搜索
2021-10-10 00:15:53

我使用 GridSearch CV创建了一个随机森林和梯度提升回归器。对于 Gradient Boosting Regressor,对我来说它需要的时间太长了。但我需要知道哪些是模型的最佳参数。所以我在想是否有没有 CV 的 GridSearch,因为 OOB 分数足以评估模型。我希望我能解释我的意思。

4个回答

GridSearchCV 是围绕交叉验证构建的,但如果速度是您的主要关注点,您可以使用较少的折叠数获得更好的性能。

从文档:

sklearn.model_selection.GridSearchCV 类(估计器,param_grid,评分=None,n_jobs=None,iid='deprecated',refit=True,cv=None,verbose=0,pre_dispatch='2*n_jobs',error_score=nan,return_train_score =假)

cv:int,交叉验证生成器或可迭代的,可选

确定交叉验证拆分策略。cv 的可能输入是:

    None, to use the default 5-fold cross validation,

    integer, to specify the number of folds in a (Stratified)KFold,

    CV splitter,

    An iterable yielding (train, test) splits as arrays of indices.

对于整数/无输入,如果估计器是分类器并且 y 是二元或多类,则使用 StratifiedKFold。在所有其他情况下,使用 KFold。

cv默认为 5,因此将其更改为 2 应该会为您提供显着的加速。这将显着削弱交叉验证。

或者,您可以为您的cv. 这将有效地禁用交叉验证并消除它提供的好处。

通过传递一个可调用的参数scoring,它直接使用模型的 oob 分数并完全忽略传递的数据,您应该能够使 GridSearchCV 按您希望的方式运行。cv正如@jnranton 建议的那样,只需为参数传递一个拆分;您甚至可以更进一步,使单个拆分使用训练部分的所有数据,而测试部分甚至不会在上述设置中使用。(sklearn 是否执行检查以防止通过cv=1?)

我还没有机会尝试这个:

def oob_scorer(estimator, X, y):
    return estimator.oob_score_

model = GridSearchCV(estimator=RandomForest(...),
                     param_grid={...},
                     scoring=oob_scorer,
                     cv=PredefinedSplit([-1]*TRAIN_SET.shape[0]),
                     ...
                     )

scikit docs:
固定拆分
自定义记分器

相关问题:
使用 oob 作为度量的 Scikitlearn 网格搜索随机森林?
RandomForestClassifier OOB 评分方法

我不确定这种方法是否值得。即使使用并行化,自己制作网格循环也不会非常困难。


编辑:是的,没有测试组的 cv-splitter 失败。按分钟计算,但您可以只拆分一个测试点,或者添加一个虚拟测试集,或者......
这是一个工作示例。似乎确实在使用 oob_score,并且测试集只有一个牺牲点: https ://github.com/bmreiniger/datascience.stackexchange/blob/master/GridSearchNoCV_oob.ipynb

有几种方法可以加快速度:

  1. 减少 CV 值,如@jncraton 所述
  2. 减少超参数的搜索空间(只测试几个参数或减少参数的范围)

此外,您可能会考虑通过使用 hyperopt 或 nevergrad 来使用更有效的超参数搜索方式。

或者,只需自己实现一个简单的网格搜索算法。Mueller 和 Guido 的“Python 机器学习简介”一书中包含一个使用以下代码的示例SVC

# naive grid search implementation
from sklearn.svm import SVC

X_train, X_test, y_train, y_test = train_test_split(iris.data, iris.target, random_state=0)
print("Size of training set: {} size of test set: {}".format( X_train.shape[0], X_test.shape[0]))

best_score = 0

for gamma in [0.001, 0.01, 0.1, 1, 10, 100]:
    for C in [0.001, 0.01, 0.1, 1, 10, 100]:
        # for each combination of parameters, train an SVC
        svm = SVC(gamma=gamma, C=C)
        svm.fit(X_train, y_train)
        # evaluate the SVC on the test set
        score = svm.score(X_test, y_test)
        # if we got a better score, store the score and parameters
        if score > best_score:
            best_score = score
            best_parameters = {'C': C, 'gamma': gamma}

print("Best score: {:.2f}".format(best_score))
print("Best parameters: {}".format(best_parameters))