Python 中的网格搜索

原文:https://www.javatpoint.com/grid-search-in-python

在本教程中,我们将讨论用于优化超参数的网格搜索。我们还将了解网格搜索的工作原理,以及它在优化机器学习方法性能方面的实现。

超参数调整对于机器学习(ML) 模型的适当工作具有重要意义。像网格搜索这样的方法似乎是超参数优化的基本工具。

网格搜索方法考虑一些超参数组合,并选择返回较低错误分数的组合。当只有一些超参数需要优化时,这种方法特别有用。然而,当机器学习模型的复杂性增加时,它的性能优于其他加权随机搜索方法。

让我们从理解网格搜索开始。

理解网格搜索

网格搜索是一种优化算法,它允许我们从我们提供的参数选择列表中选择最佳参数来优化问题,从而使‘试错’方法自动化。虽然我们可以将其应用于多个优化问题;然而,最常见的是将其用于机器学习,以获得模型提供最佳精度的参数。

让我们考虑模型以输入的形式接受以下三个参数:

  1. 隐藏层数[2,4]

  2. 每层神经元数量[5,10]

  3. 时代数量[10,50]

如果我们想为每个参数输入尝试两个选项(如上面方括号中所指定的),它会估计不同的组合。例如,一个可能的组合可以是[2,5,10]。手动找到这样的组合将是一件令人头痛的事情。

现在,假设我们有 10 个不同的参数作为输入,我们想要为每个参数尝试 5 个可能的值。每当我们想要更改参数值、重新执行代码以及记录每个参数组合的输出时,都需要程序员手动输入。

网格搜索自动执行该过程,因为它接受每个参数的可能值并执行代码,以便尝试每个可能的组合,输出组合的结果并输出具有最佳精度的组合。

安装所需的库

在我们开始用 Python 编程语言实现网格搜索之前,让我们简单讨论一下系统中需要安装的一些必要的库和框架。

这些库和框架如下:

  1. Python 3

  2. num py

  3. Pandas

  4. Scikit-Learn

它们都很容易安装。我们可以使用 pip 安装程序来安装这些库,如下所示:


$ pip install numpy tensorflow pandas scikit-learn keras

注意:如果在执行任何软件包时出现任何问题,请尝试重新安装并参考每个软件包的官方文档。

现在,让我们开始用 Python 实现网格搜索

Python 中网格搜索的实现

在下一节中,我们将了解如何在实际应用中实现网格搜索。我们将简单地执行代码,并深入讨论网格搜索部分,而不是讨论机器学习和数据预处理部分。

那么,让我们开始吧。

我们将使用饮食数据集,该数据集包含基于各种属性(如性别、年龄和饮食类型)的不同人的身高和体重数据。借助 Pandas read_csv() 功能,我们可以直接从在线资源导入数据。

但在此之前,我们必须导入所需的包:

文件:mygrid.py


import sys
import pandas as pd
import numpy as np
from sklearn.model_selection import GridSearchCV, KFold
from keras.models import Sequential
from keras.layers import Dense, Dropout
from keras.wrappers.scikit_learn import KerasClassifier
from keras.optimizers import Adam

说明:

在上面的代码片段中,我们已经导入了项目所需的包和库。还可以保存程序文件并执行它,以便检查库和包是否正确安装和导入。

一旦包成功导入,我们必须使用下面的代码片段来导入数据集并打印它的前五行。

文件:mygrid.py


# importing the dataset
mydf = pd.read_csv("Diet_Dataset.csv")

# printing the first five lines of dataset
print(mydf.head())

输出:

   Person gender  Age  Height  pre.weight  Diet  weight6weeks
0 25 41 171 60 2 60.0
1 26 32 174 103 2 103.0
2 1 0 22 159 58 1 54.2
3 2 0 46 192 60 1 54.0
4 3 0 55 170 64 1 63.3

说明:

在上面的代码片段中,我们使用Pandas库的 read_csv() 导入数据集,并将其存储在 mydf 变量中。然后,我们使用 head() 函数和 mydf 变量打印了前五行。

现在,让我们将数据划分为要素集和标签集,以便对数据集应用标准缩放。

其代码片段如下所示:

文件:mygrid.py


# converting dataframe into numpy array
mydataset = mydf.values

X = mydataset[:, 0:6]
Y = mydataset[:, 6].astype(int)

# Normalizing the data using sklearn StandardScaler
from sklearn.preprocessing import StandardScaler

myscaler = StandardScaler().fit(X)

# Transforming and displaying the training data
X_stdized = myscaler.transform(X)

mydata = pd.DataFrame(X_stdized)

说明:

在上面的代码片段中,我们已经将Pandas数据帧转换成了 NumPy 数组。然后我们从 sklearn 库中导入了标准缩放器模块,并使用该函数对数据进行归一化。然后,我们使用 transform() 函数转换并显示了训练数据。

现在,让我们考虑下面的代码片段,以便创建一个简单的深度学习模型。

文件:mygrid.py


# defining the function to create model
def create_my_model(learnRate, dropoutRate):
# Creating model
mymodel = Sequential()
mymodel.add(Dense(6, input_dim = 6, kernel_initializer = 'normal', activation = 'relu'))
mymodel.add(Dropout(dropoutRate))
mymodel.add(Dense(3, input_dim = 6, kernel_initializer = 'normal', activation = 'relu'))
mymodel.add(Dropout(dropoutRate))
mymodel.add(Dense(1, activation = 'sigmoid'))

# Compiling the model
my_Adam = Adam(learning_rate = learnRate)
mymodel.compile(loss = 'binary_crossentropy', optimizer = my_Adam, metrics = ['accuracy'])
return mymodel

说明:

下面的代码片段将函数定义为 create_my_model() 接受两个参数,即 learnRatedropoultrate。然后,我们使用顺序()功能将模型创建为我的模型。我们还使用了 add() 以及 Dense() 和**drop()**功能。然后我们使用 compile() 函数编译了模型。

因此,当我们执行代码时,这将导致加载数据集,对其进行预处理,并创建机器学习模型。因为我们只对理解网格搜索的工作感兴趣,所以我们没有执行训练/测试分割,我们已经在完整的数据集上拟合了模型。

现在,我们将在下一节中了解网格搜索如何通过优化参数使程序员的生活变得更容易。

不使用网格搜索训练模型

在下面显示的代码片段中,我们将借助随机决定的或基于直觉的参数值创建一个模型,并看看我们的模型如何运行:

文件:mygrid.py


# Declaring the values of the parameter
dropoutRate = 0.1
epochs = 1
batchSize = 20
learnRate = 0.001

# Creating the model object by calling the create_my_model function we created above
mymodel = create_my_model(learnRate, dropoutRate)

# Fitting the model onto the training data
mymodel.fit(X_stdized, Y, batch_size = batchSize, epochs = epochs, verbose = 1)

输出:

4/4 [==============================] - 41s 14ms/step - loss: 0.9364 - accuracy: 0.0000e+00

说明:

在上面的代码片段中,我们已经分别声明了参数的值,即dropoultrate、epochs、batchSizelearnRate 。然后,我们通过调用 create_my_model() 函数来创建模型对象。然后,我们将模型拟合到训练数据上。

结果,我们得到的精度是 0.0000e+00。

利用网格搜索优化超参数

如果我们没有使用网格搜索方法,我们可以在上面创建的模型上直接调用 fit() 函数。但是为了利用网格搜索方法,我们必须向 create_my_model() 函数传递一些参数。此外,我们必须用各种选项声明网格,以尝试每个参数。让我们在不同的地方表演。

首先,我们将尝试修改 create_my_model() 函数,以便接受来自调用函数的参数,如下所示:

文件:mygrid.py


def create_my_model(learnRate, dropoutRate):
# Creating the model
mymodel = Sequential()
mymodel.add(Dense(6, input_dim = 6, kernel_initializer = 'normal', activation = 'relu'))
mymodel.add(Dropout(dropoutRate))
mymodel.add(Dense(3, input_dim = 6, kernel_initializer = 'normal', activation = 'relu'))
mymodel.add(Dropout(dropoutRate))
mymodel.add(Dense(1, activation = 'sigmoid'))

# Compile the model
myadam = Adam(learning_rate = learnRate)
mymodel.compile(loss = 'binary_crossentropy', optimizer = myadam, metrics = ['accuracy'])
return mymodel

# Creating the model object
mymodel = KerasClassifier(build_fn = create_my_model, verbose = 1)

说明:

在上面的代码片段中,我们对之前的 create_my_model 函数进行了一些更改,并使用了 KerasClassifier 来创建模型对象。

现在,让我们实现网格搜索算法,并在其上拟合数据集:

文件:mygrid.py


# Defining the arguments that we want to use in Grid Search along
# with the list of values that we want to try out
learnRate = [0.001, 0.02, 0.2]
dropoutRate = [0.0, 0.2, 0.4]
batchSize = [10, 20, 30]
epochs = [1, 5, 10]

# Making a dictionary of the grid search parameters
paramgrid = dict(learnRate = learnRate, dropoutRate = dropoutRate, batch_size = batchSize, epochs = epochs )

# Building and fitting the GridSearchCV
mygrid = GridSearchCV(estimator = mymodel, param_grid = paramgrid, cv = KFold(random_state = None), verbose = 10)

gridresults = mygrid.fit(X_stdized, Y)

# Summarizing the results in a readable format
print("Best: " + gridresults.best_score_ + " using " + gridresults.best_params_)

means = gridresults.cv_results_['mean_test_score']
stds = gridresults.cv_results_['std_test_score']
params = gridresults.cv_results_['params']

for mean, stdev, param in zip(means, stds, params):
print(mean + "(" + stdev + ")" + " with: " + param)

输出:

Best: 0.00347268912077, using {batch_size=10, dropoutRate=0.4, epochs=5, learnRate=0.2}

说明:

上述输出显示了产生最佳精度的参数组合。

最后,我们可以得出结论,网格搜索在 Python 编程语言中非常容易实现,并且节省了我们大量的人工时间。我们可以列出所有想要调优的参数,声明需要测试的值,执行代码,然后忘掉它。这个过程是如此简单和方便,以至于它需要程序员更少的输入。一旦找到最佳参数组合,我们就可以将它用于最终模型。