Press "Enter" to skip to content

超参数调优:GridSearchCV和RandomizedSearchCV的解释

超参数调优:GridSearchCV和RandomizedSearchCV的解释 四海 第1张 

每个训练的机器学习模型都有一组参数或模型系数。机器学习算法的目标是学习这些参数的最优值,这被构建成一个优化问题。

此外,机器学习模型还有一组超参数。例如,在K近邻算法中的K值,即邻居的数量。或者在训练深度神经网络时的批处理大小等。

这些超参数并不由模型学习,而是由开发人员指定。它们影响模型性能,并且是可调节的。那么,如何找到这些超参数的最佳值呢?这个过程被称为超参数优化超参数调整

最常见的超参数调整技术包括:

  • 网格搜索
  • 随机搜索

在本指南中,我们将学习这些技术的原理以及它们在scikit-learn中的实现。

 

训练一个基准SVM分类器

 

让我们从在wine数据集上训练一个简单的支持向量机(SVM)分类器开始。

首先,导入所需的模块和类:

from sklearn import datasetsfrom sklearn.model_selection import train_test_splitfrom sklearn.svm import SVCfrom sklearn.metrics import accuracy_score

 

wine数据集是scikit-learn中内置的数据集之一。让我们按照以下方式读取特征和目标标签:

# 载入Wine数据集wine = datasets.load_wine()X = wine.datay = wine.target

 

wine数据集是一个简单的数据集,具有13个数值特征和三个输出类别标签。它是一个很好的用于熟悉多类别分类问题的候选数据集。你可以运行wine.DESCR来获取关于数据集的描述。

 超参数调优:GridSearchCV和RandomizedSearchCV的解释 四海 第2张 

接下来,将数据集拆分为训练集和测试集。这里我们使用了test_size为0.2。所以80%的数据用于训练集,20%用于测试集。

# 将数据集拆分为训练集和测试集X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=24)

 

现在实例化一个支持向量分类器,并将模型拟合到训练集上。然后评估其在测试集上的性能。

# 创建一个基准SVM分类器baseline_svm = SVC()baseline_svm.fit(X_train, y_train)y_pred = baseline_svm.predict(X_test)

 

因为这是一个简单的多分类问题,我们可以查看模型的准确率。

# 评估基准模型accuracy = accuracy_score(y_test, y_pred)print(f"Baseline SVM准确率:{accuracy:.2f}")

 

我们可以看到使用默认超参数值的模型的准确性得分约为0.78。

输出 >>>Baseline SVM准确率:0.78

 

这里我们使用了random_state为24。对于不同的随机状态,您将得到不同的训练集和测试集拆分,以及不同的准确率得分。

因此,我们需要一种比单一的训练测试拆分更好的方法来评估模型的性能。也许,可以在许多这样的拆分上训练模型,并考虑平均准确率。同时尝试不同的超参数组合?是的,这就是为什么在模型评估和超参数搜索中使用交叉验证的原因。我们将在下面的部分中学到更多知识。

接下来,让我们找出可以调整的此支持向量机分类器的超参数。

 

调整的SVM超参数

 

在超参数调优中,我们旨在为我们的SVM分类器找到最佳的超参数值组合。支持向量分类器常调优的超参数包括:

  • C:正则化参数,控制最大化边界和最小化分类误差之间的权衡。
  • kernel:指定要使用的内核函数类型(例如‘linear’,‘rbf’,‘poly’)。
  • gamma:‘rbf’和‘poly’内核的内核系数。

 

理解交叉验证的作用

 

交叉验证有助于评估模型对未见数据的泛化能力,并减少过度拟合的风险。常用的k折交叉验证将数据集分成k个大小相等的折叠。模型进行k次训练,每次一个折叠作为验证集,其余折叠作为训练集。因此,对于每个折叠,我们都会得到一个交叉验证准确性。

当我们运行网格搜索和随机搜索以找到最佳超参数时,我们将根据最佳平均交叉验证分数选择超参数。

 

什么是网格搜索?

 

网格搜索是一种超参数调优技术,它在指定的超参数空间中执行详尽的搜索,以找到产生最佳模型性能的超参数组合。

 

网格搜索的工作原理

 

我们将超参数搜索空间定义为参数网格。参数网格是一个字典,您在其中使用要调优的每个超参数以及要探索的值列表。

网格搜索然后系统地探索参数网格中的每个可能的超参数组合。它使用交叉验证拟合和评估每个组合的模型,并选择产生最佳性能的组合。

接下来,让我们在scikit-learn中实现网格搜索。

 

Scikit-Learn中的GridSearchCV

 

首先,从scikit-learn的model_selection模块导入GridSearchCV类:

from sklearn.model_selection import GridSearchCV

 

让我们为SVM分类器定义参数网格:

# 定义超参数网格param_grid = {    'C': [0.1, 1, 10],    'kernel': ['linear', 'rbf', 'poly'],    'gamma': [0.1, 1, 'scale', 'auto']}

 

网格搜索然后系统地探索参数网格中的每个可能的超参数组合。对于此示例,它使用以下参数评估模型性能:

  • C设置为0.1、1和10,
  • kernel设置为’linear’、’rbf’和’poly’,以及
  • gamma设置为0.1、1、’scale’和’auto’。

这总共产生了3 * 3 * 4 = 36种不同的组合需要评估。网格搜索为每个组合拟合和评估模型,使用交叉验证,并选择产生最佳性能的组合。

然后,我们实例化GridSearchCV来调整baseline_svm的超参数:

# 创建GridSearchCV对象grid_search = GridSearchCV(estimator=baseline_svm, param_grid=param_grid, cv=5)# 使用超参数网格拟合模型grid_search.fit(X_train, y_train)

 

请注意,我们使用了5折交叉验证。

最后,我们评估通过网格搜索找到的最佳模型的性能 – 使用最佳超参数对测试数据进行评估:

# 获取最佳超参数和模型
best_params = grid_search.best_params
best_model = grid_search.best_estimator_

# 评估最佳模型
y_pred_best = best_model.predict(X_test)
accuracy_best = accuracy_score(y_test, y_pred_best)
print(f"最佳 SVM 准确度: {accuracy_best:.2f}")
print(f"最佳超参数: {best_params}")

# 模型在以下超参数下获得了准确度得分为0.94
print("如上所示,该模型在以下超参数下获得了准确度得分为0.94:")
print("最佳 SVM 准确度: 0.94")
print("最佳超参数: {'C': 0.1, 'gamma': 0.1, 'kernel': 'poly'}")

# 网格搜索的优点和缺点
print("网格搜索的优点和缺点:")
print("使用网格搜索进行超参数调优具有以下优点:")
print("- 网格搜索能够探索所有指定的组合,确保您不会错过定义的搜索空间中的最佳超参数。")
print("- 对于探索较小的超参数空间来说是个不错的选择。")
print("然而,反过来:")
print("- 网格搜索可能需要计算量较大,特别是当涉及大量超参数及其值时。对于非常复杂的模型或广泛的超参数搜索可能不可行。")
print("现在让我们学习随机搜索:")

# 什么是随机搜索
print("什么是随机搜索:")
print("随机搜索是另一种超参数调优技术,它在指定的分布或范围内随机探索超参数的组合。当需要搜索大量超参数时特别有用。")

# 随机搜索的工作原理
print("随机搜索的工作原理:")
print("在随机搜索中,您可以为每个超参数定义概率分布或范围,而不是指定一个值网格。这样就形成了一个更大的超参数搜索空间。")
print("随机搜索然后从这些分布中随机抽样固定数量的超参数组合。这样就可以有效地探索多样的超参数组合。")

# Scikit-Learn 中的 RandomizedSearchCV
print("Scikit-Learn 中的 RandomizedSearchCV:")
print("现在让我们使用随机搜索来调整基线 SVM 分类器的参数。")

# 导入 RandomizedSearchCV 类并定义 param_dist,一个更大的超参数搜索空间
print("我们导入 RandomizedSearchCV 类,并定义 param_dist,一个更大的超参数搜索空间:")
print("从 sklearn.model_selection 模块导入 RandomizedSearchCV 类和 uniform 函数")
print("param_dist = {")
print("    'C': uniform(0.1, 10),  # 在0.1和10之间的均匀分布")
print("    'kernel': ['linear', 'rbf', 'poly'],")
print("    'gamma': ['scale', 'auto'] + list(np.logspace(-3, 3, 50))")
print("}")

# 类似于网格搜索,我们实例化随机搜索模型以搜索最佳超参数
print("类似于网格搜索,我们实例化了随机搜索模型以搜索最佳超参数。这里我们将 n_iter 设置为 20: 所以将随机选择 20 组超参数。")
print("randomized_search = RandomizedSearchCV(estimator=baseline_svm, param_distributions=param_dist, n_iter=20, cv=5)")
print("randomized_search.fit(X_train, y_train)")

# 评估使用随机搜索找到的最佳超参数的模型性能
print("接着,我们评估模型在最佳超参数下的性能:")
print("# 获取最佳超参数和模型")
print("best_params_rand = randomized_search.best_params")
print("best_model_rand = randomized_search.best_estimator_")

# 评估最佳模型
print("y_pred_best_rand = best_model_rand.predict(X_test)")
print("accuracy_best_rand = accuracy_score(y_test, y_pred_best_rand)")
print(f"最佳 SVM 准确度: {accuracy_best_rand:.2f}")
print(f"最佳超参数: {best_params_rand}")

# 最佳准确度和最佳超参数
print("最佳准确度和最佳超参数:")
print("最佳 SVM 准确度: 0.94")
print("最佳超参数: {'C': 9.66495227534876, 'gamma': 6.25055192527397, 'kernel': 'poly'}")

 

通过随机搜索找到的参数与通过网格搜索找到的参数不同。具有这些超参数的模型也实现了0.94的准确率得分。

 

随机搜索的优缺点

 

让我们总结一下随机搜索的优点:

  • 当处理大量超参数或广泛的值范围时,随机搜索效率高,因为它不需要穷举搜索。
  • 它可以处理各种参数类型,包括连续和离散值。

以下是随机搜索的一些限制:

  • 由于其随机性质,它不总能找到最佳超参数。但它通常能快速找到好的超参数。
  • 与网格搜索不同,它不能保证探索所有可能的组合。

 

结论

 

我们学习了如何使用 scikit-learn 中的 RandomizedSearchCVGridSearchCV 进行超参数调优。然后,我们使用最佳超参数评估了模型的性能。

总结起来,网格搜索通过参数网格中的所有可能组合进行穷举搜索。而随机搜索则随机抽样超参数组合。

这两种技术都能帮助您确定机器学习模型的最佳超参数,同时降低过拟合到特定训练-测试拆分的风险。

[Bala Priya C](https://twitter.com/balawc27) 是来自印度的开发人员和技术作家。她喜欢在数学、编程、数据科学和内容创作的交叉点上工作。她感兴趣的领域和专业知识包括DevOps、数据科学和自然语言处理。她喜欢阅读、写作、编码和咖啡!目前,她正在通过撰写教程、指南、观点文章等来学习并与开发者社区分享自己的知识。

Leave a Reply

Your email address will not be published. Required fields are marked *