为什么要微调模型?
机器学习并不总是像Iris、Titanic或Boston House Pricing数据集那样简单。
但是,嘿,别误会我。我从那些著名的玩具数据集中学到了很多东西(并不断学习)。它们的最大优点是不需要太多的探索或预处理。很多时候,我们可以直接到我们想要练习和学习的地方,比如管道、建模、模型调整、可视化等。
我想说的是,在建模数据时,它不会像我们用来研究的玩具数据集那样容易。需要调整、拟合真实数据,并对模型进行微调,这样我们才能从算法中获得最佳效果。为此,两个不错的选项是Scikit Learn的GridSearchCV和RandomizedSearchCV。
好吧,也许这篇文章带给你的是需要通过为模型选择正确的超参数来更好地进行预测。因此,本快速教程中提供的两个选项将允许我们为建模算法提供超参数列表。它将逐一组合这些选项,测试许多不同的模型,然后为我们提供最佳选项,即性能最佳的选项。
太棒了,不是吗?因此,让我们继续了解它们之间的区别。
为了用一个简单的类比来说明这个概念,让我们想象一下,我们要去参加一个聚会,我们想选择最佳的服装组合。我们带了几件衬衫、几条裤子和几件时装。
如果我们是GridSearchCV,我们会尝试各种衬衫、裤子和鞋子的组合,看看镜子,然后拍照。最后,我们将考虑所有问题,并采取最佳选择。
如果我们是RandomizedSearchCV,我们将尝试随机选择的一些组合,拍摄一张照片,并在最后选择最佳表现。
现在,通过这个类比,我相信你可以感觉到,随着我们尝试的服装数量的增加,网格搜索将需要更多的时间。
如果只是两件衬衫、一条裤子和一双鞋,这不会花很长时间。但如果是10件衬衫、5条裤子和4双不同的鞋子,那么……你就明白了。但是,另一方面,它将有一个完整的遍历,所以它是一套非常完整的选项可供选择。
随机搜索不会花费很长时间,因为它只会尝试一些随机选择的组合。因此,如果你的选项网格很小,那么使用它是没有意义的。训练所有选项或仅训练其中几个选项的时间几乎相同。但当你有很多组合可以尝试时,它可能更有意义。
让我们看看他们现在的实现。
让我们进入编码部分。我们将开始导入本练习所需的模块。
# Imports
import pandas as pd
import numpy as np
import seaborn as sns
# Dataset
from sklearn.datasets import make_regression
# sklearn preprocess
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.tree import DecisionTreeRegressor
from sklearn.model_selection import train_test_split
# Search
from sklearn.model_selection import RandomizedSearchCV, GridSearchCV
接下来,我们可以创建回归数据集。
# Dataframe
df = make_regression(n_samples=2000, n_features=5,
n_informative=4, noise=1, random_state=12)
# Split X and y
X= df[0]
y= df[1]
我们可以分开训练和测试。
# Train test split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random)
让我们创建一个管道来缩放数据并拟合决策树模型。
# Creating the steps for the pipeline
steps = [ ('scale', StandardScaler()),
('model', DecisionTreeRegressor()) ]
# Creating pipeline for Decision Tree Regressor
pipe = Pipeline(steps)
# Fit the model
pipe.fit(X_train, y_train)
下一步是创建要测试的超参数参数网格,以微调模型。这里有(2 x 3 x 2=12)个选项需要测试。
%%timeit
# Creating dictionary of parameters to be tested
params= {'model__max_features': [2,5], 'model__min_samples_split':[2, 5, 10], 'model__criterion': ['friedman_mse', 'absolute_error']}
# Applying the Grid Search
grid = GridSearchCV(pipe, param_grid=params, cv=5, scoring='neg_mean_squared_error')
grid.fit(X_train, y_train)
# Best model
grid.best_estimator_
时间结果如下。循环2.37秒。总时间约为18秒。这很好。
2.37 s ± 526 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
但如果我们增加测试选项的数量会发生什么?让我们试试(4 x 6 x 2=48)选项。
%%timeit
# Creating dictionary of parameters to be tested
params= {'model__max_features': [2,3,4,5], 'model__min_samples_split':[2,5,6,7,8,10],'model__criterion': ['friedman_mse', 'absolute_error']}
# Applying the Grid Search
grid = GridSearchCV(pipe, param_grid=params, cv=5, scoring='neg_mean_squared_error')
grid.fit(X_train, y_train)
# Best model
grid.best_estimator_
时间增加了很多。每个循环6.93秒。这里的总时间超过了1分钟。
6.93 s ± 505 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
现在让我们看看随机化搜索。首先,我们将尝试相同的第一次运行,有12个选项。
%%timeit
# Creating dictionary of parameters to be tested
params= {'model__max_features': [2,5],'model__min_samples_split':[2, 5, 10],'model__criterion': ['friedman_mse', 'absolute_error']}
# Applying the Grid Search
randcv = RandomizedSearchCV(pipe, param_distributions=params, cv=5, scoring='neg_mean_squared_error')
randcv.fit(X_train, y_train)
# Best model
randcv.best_estimator_
时间比预期的网格搜索时间短。每个循环1.47秒,总共运行约10秒。
1.47 s ± 140 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
如果我们增加网格中的选项数量,让我们看看会发生什么。
%%timeit
# Creating dictionary of parameters to be tested
params= {'model__max_features': [2,3,4,5],
'model__min_samples_split':[2,5,6,7,8,9,10],
'model__criterion': ['friedman_mse', 'absolute_error']}
# Applying the Grid Search
randcv = RandomizedSearchCV(pipe, param_distributions=params, cv=5, scoring='neg_mean_squared_error')
randcv.fit(X_train, y_train)
# Best model
randcv.best_estimator_
这是结果。哇,几乎同时!每个循环1.46秒。
1.46 s ± 233 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
嗯,那太好了。但是,他们给了我们类似的结果吗?让我们看看下一个。
评估GridSearchCV和RandomiedSearchCV的结果。
计算网格搜索的RMSE。
# Taking the best estimator
best_grid = grid.best_estimator_
# Predict
preds_grid = best_grid.predict(X_test)
# RMSE
np.sqrt( mean_squared_error(y_test, preds_grid) )
[OUT]:
53.70886778489411
计算随机搜索的RMSE。
# Taking the best estimator
best_rand = randcv.best_estimator_
# Predict
preds_rand = best_rand.predict(X_test)
# RMSE
np.sqrt( mean_squared_error(y_test, preds_rand) )
[OUT]:
55.35583215782757
结果相差3%。网格搜索得到了最好的结果,因为它训练了每个模型,因此,它将找到最佳拟合。当你尝试了太多的组合时,你需要训练。在这种情况下,随机搜索是一个很好的选择。
在这篇文章中,我们想展示两个用于微调模型的好选项。
当你需要考虑所有可能的优化时,可以使用GridSearchCV。但要考虑到训练模型的时间。如果你知道要选择哪些超参数,这一个可能是你最好的选择。
当有太多的超参数组合可供选择时,随机化搜索可能是最佳选择。例如,当使用网格搜索时,你可以运行它并获得最佳估计器,以便为你指明正确的组合方向。
http://gustavorsantos.medium.com/
参考
https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.GridSearchCV.html#sklearn.model_selection.GridSearchCV
https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.RandomizedSearchCV.html#sklearn.model_selection.RandomizedSearchCV
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有