我为随机森林模型实现了一个网格搜索。
train_X, test_X, train_y, test_y = train_test_split(features, target, test_size=.10, random_state=0)# 可以通过标准化获得一些性能提升train_X, test_X = standarize(train_X, test_X)tuned_parameters = [{ 'n_estimators': [5], 'criterion': ['mse', 'mae'], 'random_state': [0]}]scores = ['neg_mean_squared_error', 'neg_mean_absolute_error']for n_fold in [5]: for score in scores: print("# 调整%s的超参数,使用%d折交叉验证" % (score, n_fold)) start_time = time.time() print() # TODO: RandomForestRegressor clf = GridSearchCV(RandomForestRegressor(verbose=2), tuned_parameters, cv=n_fold, scoring=score, verbose=2, n_jobs=-1) clf.fit(train_X, train_y) ... 其余部分省略
在我使用这个网格搜索之前,我已经用完全相同的数据集完成了许多其他任务,所以数据本身应该没有问题。此外,为了测试目的,我首先使用LinearRegression来查看整个流程是否顺利运行,结果是可以的。然后我切换到RandomForestRegressor,并设置了一个非常小的估计器数量来再次测试。接下来发生了一件非常奇怪的事情,我会附上详细信息。性能显著下降,我不知道发生了什么。没有理由花30分钟以上来运行一个小型网格搜索。
为每个候选者拟合5折,共计10次拟合[CV] criterion=mse, n_estimators=5, random_state=0 ...................构建树1/5[CV] criterion=mse, n_estimators=5, random_state=0 ...................构建树1/5[CV] criterion=mse, n_estimators=5, random_state=0 ...................构建树1/5[CV] criterion=mse, n_estimators=5, random_state=0 ...................构建树1/5[Parallel(n_jobs=1)]: 完成 1 共 1 | 耗时: 1.0s 剩余: 0.0s构建树2/5[Parallel(n_jobs=1)]: 完成 1 共 1 | 耗时: 1.0s 剩余: 0.0s构建树2/5[Parallel(n_jobs=1)]: 完成 1 共 1 | 耗时: 1.1s 剩余: 0.0s构建树2/5[Parallel(n_jobs=1)]: 完成 1 共 1 | 耗时: 1.1s 剩余: 0.0s构建树2/5构建树3/5构建树3/5构建树3/5构建树3/5构建树4/5构建树4/5构建树4/5构建树4/5构建树5/5构建树5/5构建树5/5构建树5/5[Parallel(n_jobs=1)]: 完成 5 共 5 | 耗时: 5.0s 完成[Parallel(n_jobs=1)]: 完成 1 共 1 | 耗时: 0.0s 剩余: 0.0s[Parallel(n_jobs=1)]: 完成 5 共 5 | 耗时: 5.0s 完成[Parallel(n_jobs=1)]: 完成 1 共 1 | 耗时: 0.0s 剩余: 0.0s[Parallel(n_jobs=1)]: 完成 5 共 5 | 耗时: 5.0s 完成[Parallel(n_jobs=1)]: 完成 1 共 1 | 耗时: 0.0s 剩余: 0.0s[Parallel(n_jobs=1)]: 完成 5 共 5 | 耗时: 0.2s 完成[Parallel(n_jobs=1)]: 完成 5 共 5 | 耗时: 5.0s 完成[Parallel(n_jobs=1)]: 完成 5 共 5 | 耗时: 0.3s 完成[Parallel(n_jobs=1)]: 完成 1 共 1 | 耗时: 0.1s 剩余: 0.0s[Parallel(n_jobs=1)]: 完成 1 共 1 | 耗时: 0.1s 剩余: 0.0s[Parallel(n_jobs=1)]: 完成 5 共 5 | 耗时: 0.3s 完成[Parallel(n_jobs=1)]: 完成 1 共 1 | 耗时: 0.1s 剩余: 0.0s[Parallel(n_jobs=1)]: 完成 5 共 5 | 耗时: 0.2s 完成[Parallel(n_jobs=1)]: 完成 1 共 1 | 耗时: 0.1s 剩余: 0.0s[Parallel(n_jobs=1)]: 完成 1 共 1 | 耗时: 0.1s 剩余: 0.0s[Parallel(n_jobs=1)]: 完成 5 共 5 | 耗时: 0.8s 完成[CV] .... criterion=mse, n_estimators=5, random_state=0, 总耗时= 5.3s[CV] criterion=mse, n_estimators=5, random_state=0 ...................[Parallel(n_jobs=1)]: 完成 5 共 5 | 耗时: 0.8s 完成[CV] .... criterion=mse, n_estimators=5, random_state=0, 总耗时= 5.3s构建树1/5[CV] criterion=mae, n_estimators=5, random_state=0 ...................[Parallel(n_jobs=1)]: 完成 5 共 5 | 耗时: 0.9s 完成[CV] .... criterion=mse, n_estimators=5, random_state=0, 总耗时= 5.3s构建树1/5[CV] criterion=mae, n_estimators=5, random_state=0 ...................构建树1/5[Parallel(n_jobs=1)]: 完成 5 共 5 | 耗时: 0.9s 完成[CV] .... criterion=mse, n_estimators=5, random_state=0, 总耗时= 5.3s[CV] criterion=mae, n_estimators=5, random_state=0 ...................构建树1/5[Parallel(n_jobs=1)]: 完成 1 共 1 | 耗时: 1.0s 剩余: 0.0s构建树2/5构建树3/5构建树4/5构建树5/5[Parallel(n_jobs=1)]: 完成 5 共 5 | 耗时: 5.3s 完成[Parallel(n_jobs=1)]: 完成 1 共 1 | 耗时: 0.0s 剩余: 0.0s[Parallel(n_jobs=1)]: 完成 5 共 5 | 耗时: 0.2s 完成[Parallel(n_jobs=1)]: 完成 1 共 1 | 耗时: 0.1s 剩余: 0.0s[Parallel(n_jobs=1)]: 完成 5 共 5 | 耗时: 0.5s 完成[CV] .... criterion=mse, n_estimators=5, random_state=0, 总耗时= 5.6s[CV] criterion=mae, n_estimators=5, random_state=0 ...................构建树1/5
上面的日志在几秒钟内打印出来,然后事情似乎从这里开始卡住…
[Parallel(n_jobs=1)]: 完成 1 共 1 | 耗时: 7.4min 剩余: 0.0s构建树2/5[Parallel(n_jobs=1)]: 完成 1 共 1 | 耗时: 7.5min 剩余: 0.0s构建树2/5[Parallel(n_jobs=1)]: 完成 1 共 1 | 耗时: 7.5min 剩余: 0.0s构建树2/5[Parallel(n_jobs=1)]: 完成 1 共 1 | 耗时: 7.8min 剩余: 0.0s构建树2/5构建树3/5构建树3/5构建树3/5构建树3/5构建树4/5构建树4/5构建树4/5构建树4/5构建树5/5构建树5/5构建树5/5
这些行花费了超过20分钟的时间。
顺便说一句,每次运行GridSearchCV时,线性回归的耗时不到1秒。
你知道为什么性能下降这么多吗?
任何建议和评论都将不胜感激。谢谢你。
回答:
尝试为RandomForestRegressor设置max_depth
。这应该可以减少拟合时间。默认情况下max_depth=None
。
例如:
tuned_parameters = [{ 'n_estimators': [5], 'criterion': ['mse', 'mae'], 'random_state': [0], 'max_depth': [4],}]
编辑:此外,默认情况下RandomForestRegressor
的n_jobs=1
。在这种设置下,它会一次构建一棵树。尝试设置n_jobs=-1
。
此外,你可以指定多个度量标准,而不是对GridSearchCV
的scoring
参数进行循环。当这样做时,你还必须指定你希望GridSearchCV
选择的度量标准作为refit
的值。然后,你可以在拟合后通过cv_results_
字典访问所有分数。
clf = GridSearchCV(RandomForestRegressor(verbose=2),tuned_parameters, cv=n_fold, scoring=scores, refit='neg_mean_squared_error', verbose=2, n_jobs=-1) clf.fit(train_X, train_y) results = clf.cv_results_ print(np.mean(results['mean_test_neg_mean_squared_error'])) print(np.mean(results['mean_test_neg_mean_absolute_error']))