网格搜索或随机搜索

为什么要微调模型?

机器学习并不总是像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':[2510], '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':[2510],'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

✄-----------------------------------------------

看到这里,说明你喜欢这篇文章,请点击「在看」或顺手「转发」「点赞」。

欢迎微信搜索「panchuangxx」,添加小编磐小小仙微信,每日朋友圈更新一篇高质量推文(无广告),为您提供更多精彩内容。


▼     扫描二维码添加小编  ▼  ▼  

相关推荐

  • 恭喜了!年薪100万的新方向,全体程序员彻底狂欢吧!
  • Expedia 开源针对 Kubernetes 工作负载的容器启动自动扩缩器(CSA)
  • 拥抱数据驱动:Java 企业测试实践新趋势
  • 75亿元!今年自动驾驶领域最大融资来了:90后剑桥博士带队,微软、英伟达为其站台,这家英国 AI 独角兽被首相视为“全村的希望”
  • 美国拟限制“开源 AI 大模型出口”;百度副总裁“狼性职场言论”惹争议,李彦宏情绪激动点评;谷歌一半员工没干活?| Q资讯
  • 为什么 Spring 和 IDEA 都不推荐使用 @Autowired 注解??
  • Zed,有望打败 VS Code 吗?
  • 你真的懂HTTP缓存吗?
  • 前端权限开发从设计到实践
  • 马斯克的鸡汤,我是真爱喝~
  • 一元调用宣告国内AI应用遥遥领先指日可待
  • 时隔五年, Quill 2.0 终于发布!重回富文本巅峰!
  • 无锁并发框架Disruptor,太强了
  • Spring Boot集成activiti快速入门Demo
  • Spring Boot+Vue3 动态菜单实现思路梳理
  • 面试官:重量级锁的8连问,你能接住几个?
  • 面试官:SpringBoot 如何自定义自己的条件注解与自动配置?
  • 五一回老婆家,大家聊工资的时候,我说自己月薪3w算个中产吧!结果岳父说你算啥中产?你看看你哥,两口子是公务员,那才是真正的中产!
  • 这是我见过最好的轻量级笔记系统!
  • 15年前被钉在“FFmpeg耻辱柱”,今天他却得谢谢咱——腾讯QQ影音一雪前耻?