scikit中有一个非常有用的类GridSearchCV来学习网格搜索和交叉验证,但我不想做交叉验证。我想在没有交叉验证的情况下进行网格搜索,并使用整个数据进行训练。更具体地说,我需要在网格搜索过程中用"oob分数"来评估RandomForestClassifier制作的模型。有简单的方法吗?还是我自己上课?
这些点是
- 我想用简单的方法进行网格搜索
- 我不想做交叉验证
- 我需要使用全部数据进行训练。(不想将训练数据和测试数据分开)
- 我需要在网格搜索过程中使用oob分数进行评估
我真的建议不要使用OOB来评估模型,但知道如何在GridSearchCV()
之外运行网格搜索是很有用的(我经常这样做,这样我就可以保存最佳网格中的CV预测,以便于模型堆叠)。我认为最简单的方法是通过ParameterGrid()
创建参数网格,然后循环遍历每组参数。例如,假设您有一个名为"grid"的网格dict和名为"RF"的RF模型对象,那么您可以执行以下操作:
for g in ParameterGrid(grid):
rf.set_params(**g)
rf.fit(X,y)
# save if best
if rf.oob_score_ > best_score:
best_score = rf.oob_score_
best_grid = g
print "OOB: %0.5f" % best_score
print "Grid:", best_grid
请参阅此链接:https://stackoverflow.com/a/44682305/2202107
他使用了不被sklearn的作者推荐的cv=[(slice(None), slice(None))]
。
一种方法是使用ParameterGrid
生成所需参数的迭代器并在其上循环
您可以做的另一件事是实际配置GridSearchCV以执行您想要的操作。我不太推荐这个,因为它不必要地复杂
你需要做的是:
- 使用文档中的arg
cv
,并为其提供一个生成器,该生成器生成一个具有所有索引的元组(这样训练和测试就相同了) - 更改
scoring
参数以使用随机林中给出的oob
尽管这个问题早在几年前就已经解决了,但如果你坚持使用GridSearchCV()而不是其他方法(ParameterGrid()等),我只是发现了一种更自然的方法:
- 创建一个sklearn.model_selection.PredefinedSplit()。它接受一个名为test_fold的参数,该参数是一个列表,大小与输入数据相同。在列表中,将属于训练集的所有样本设置为-1,将其他样本设置为0
- 创建一个GridSearchCV对象,cv="创建的预定义拆分对象"
然后,GridSearchCV将只生成1个列验证拆分,该拆分在test_fold中定义。
使用ParameterGrid的并行化解决方案
from sklearn.model_selection import ParameterGrid
from joblib import Parallel, delayed
param_grid = {'a': [1, 2], 'b': [True, False]}
param_candidates = ParameterGrid(param_grid)
print(f'{len(param_candidates)} candidates')
def fit_model(params):
model = estimator.set_params(**params)
model.fit(X_train, y_train)
score = model.score(X_val, y_val)
return [params, score]
results = Parallel(n_jobs=-1, verbose=10)(delayed(fit_model)(params) for params in param_candidates)
print(max(results, key=lambda x: x[1]))