![[MLM] Tips for Tuning Hyperparameters in Machine Learning Models](https://machinelearning.org.cn/wp-content/uploads/2024/08/mlm-bala-priya-c-tips-hyperparameters.png)
图片作者 | Canva 创建
如果您熟悉机器学习,您就知道训练过程可以使模型学习其参数(或模型系数)的最优值。但是,机器学习模型也有一组超参数,您在训练模型时应该指定它们的值。那么,如何找到这些超参数的最优值呢?
您可以使用超参数调整来找到超参数的最佳值。通过系统地调整超参数,您可以优化模型以获得最佳结果。
本教程提供了有效的超参数调整的实用技巧——从构建基线模型到使用贝叶斯优化等高级技术。无论您是超参数调整的新手,还是希望改进您的方法,这些技巧都将帮助您构建更好的机器学习模型。让我们开始吧。
1. 从简单开始:训练一个未经任何调整的基线模型
在开始超参数调整过程时,最好从简单开始,训练一个未经任何调整的基线模型。这个初始模型作为衡量后续调整工作效果的参考点。
为什么此步骤至关重要以及如何有效执行它:
- 基线模型提供了一个基准,可以与调整后的模型进行比较。这有助于量化通过超参数调整实现的改进。
- 选择一个默认模型:选择一个适合当前问题的模型。例如,分类问题使用决策树,回归问题使用线性回归。
- 使用默认超参数:使用库提供的默认超参数训练模型。例如,如果使用 scikit-learn,则在不指定任何参数的情况下实例化模型。
使用适当的指标评估基线模型的性能。此步骤涉及将数据分割为训练集和测试集,训练模型,进行预测,并评估结果。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
from sklearn.tree import DecisionTreeClassifier from sklearn.metrics import accuracy_score from sklearn.model_selection import train_test_split from sklearn.datasets import load_iris # 加载数据 data = load_iris() X_train, X_test, y_train, y_test = train_test_split(data.data, data.target, test_size=0.2, random_state=25) # 使用默认参数初始化模型 model = DecisionTreeClassifier() # 训练模型 model.fit(X_train, y_train) # 预测和评估 y_pred = model.predict(X_test) baseline_accuracy = accuracy_score(y_test, y_pred) print(f'基线准确率: {baseline_accuracy:.2f}') |
记录基线模型的性能指标。这将在您继续进行超参数调整时用于比较。
2. 使用带交叉验证的超参数搜索
建立基线模型后,下一步是通过超参数调整来优化模型的性能。利用带交叉验证的超参数搜索技术是找到最佳超参数集的稳健方法。
为什么使用带交叉验证的超参数搜索?
- 交叉验证通过对多个折叠的结果进行平均,提供了更可靠的模型性能估计,降低了对特定训练-测试分割过拟合的风险。
- 网格搜索和随机搜索等超参数搜索方法允许对超参数空间进行系统性探索,确保对潜在配置进行全面评估。
- 此方法有助于选择能够很好地泛化到未见数据的超参数,从而在生产环境中获得更好的模型性能。
选择搜索技术:选择一种超参数搜索方法。最常见的两种策略是
- 网格搜索,涉及对参数网格进行穷举搜索
- 随机搜索,涉及从指定分布中随机抽样参数
定义超参数网格:指定要搜索的超参数及其各自的范围或分布。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
from sklearn.model_selection import GridSearchCV, RandomizedSearchCV from sklearn.tree import DecisionTreeClassifier from sklearn.datasets import load_iris # 加载数据 data = load_iris() X_train, X_test, y_train, y_test = train_test_split(data.data, data.target, test_size=0.2, random_state=25) # 初始化模型 model = DecisionTreeClassifier() # 为网格搜索定义超参数网格 param_grid = { 'criterion': ['gini', 'entropy'], 'max_depth': [None, 10, 20, 30], 'min_samples_split': [2, 5, 10] } |
使用交叉验证:您可以使用 cross_val_score 来评估模型在指定交叉验证方案下的性能,而不是单独定义交叉验证策略。
1 2 3 4 5 6 7 8 9 10 |
from sklearn.model_selection import cross_val_score # 网格搜索 grid_search = GridSearchCV(model, param_grid, cv=5, scoring='accuracy') grid_search.fit(X_train, y_train) best_params_grid = grid_search.best_params_ best_score_grid = grid_search.best_score_ print(f'最佳参数(网格搜索):{best_params_grid}') print(f'最佳交叉验证分数(网格搜索):{best_score_grid:.2f}') |
以这种方式使用带交叉验证的超参数调整,可以确保更可靠的性能估计和更好的模型泛化能力。
3. 使用随机搜索进行初步探索
在开始超参数调整时,通常最好使用随机搜索进行初步探索。与网格搜索相比,随机搜索提供了一种更有效的方法来探索广泛的超参数,尤其是在处理高维超参数空间时。
定义超参数分布:指定超参数及其要从中抽样的各自分布。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
from sklearn.model_selection import RandomizedSearchCV from sklearn.tree import DecisionTreeClassifier from sklearn.datasets import load_iris import numpy as np # 加载数据 data = load_iris() X_train, X_test, y_train, y_test = train_test_split(data.data, data.target, test_size=0.2, random_state=42) # 初始化模型 model = DecisionTreeClassifier() # 为随机搜索定义超参数分布 param_dist = { 'criterion': ['gini', 'entropy'], 'max_depth': [None] + list(range(10, 31)), 'min_samples_split': range(2, 11), 'min_samples_leaf': range(1, 11) } |
使用带交叉验证的随机搜索进行设置:使用带交叉验证的随机搜索来探索超参数空间。
1 2 3 4 5 6 7 8 |
# 随机搜索 random_search = RandomizedSearchCV(model, param_dist, n_iter=100, cv=5, scoring='accuracy') random_search.fit(X_train, y_train) best_params_random = random_search.best_params_ best_score_random = random_search.best_score_ print(f'最佳参数(随机搜索):{best_params_random}') print(f'最佳交叉验证分数(随机搜索):{best_score_random:.2f}') |
评估模型:使用最佳超参数训练模型,并在测试集上评估其性能。
1 2 3 4 5 6 |
best_model = DecisionTreeClassifier(**best_params_random) best_model.fit(X_train, y_train) y_pred = best_model.predict(X_test) final_accuracy = accuracy_score(y_test, y_pred) print(f'最终模型准确率: {final_accuracy:.2f}') |
因此,随机搜索更适合高维超参数空间和计算成本高昂的模型。
4. 使用验证曲线监控过拟合
验证曲线有助于可视化超参数对训练和验证性能的影响,从而帮助您识别过拟合或欠拟合。
以下是一个示例。此代码片段使用验证曲线评估随机森林分类器性能随 n_estimators 超参数值变化的情况。它通过计算 5 折交叉验证下,一系列 n_estimators 值(10、100、200、400、800、1000)的训练和交叉验证分数来实现这一点。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
from sklearn.model_selection import validation_curve from sklearn.ensemble import RandomForestClassifier import matplotlib.pyplot as plt import numpy as np # 定义超参数范围 param_range = [10, 100, 200, 400, 800, 1000] # 计算验证曲线 train_scores, test_scores = validation_curve( RandomForestClassifier(), X_train, y_train, param_name="n_estimators", param_range=param_range, cv=5, scoring="accuracy") # 计算均值和标准差 train_mean = np.mean(train_scores, axis=1) train_std = np.std(train_scores, axis=1) test_mean = np.mean(test_scores, axis=1) test_std = np.std(test_scores, axis=1) |
然后,它绘制了训练集和交叉验证集的平均准确率得分及其标准差。生成的图有助于可视化在不同的 n_estimators 值下模型是过拟合还是欠拟合。
1 2 3 4 5 6 7 8 9 10 |
# 绘制验证曲线 plt.plot(param_range, train_mean, label="训练分数", color="r") plt.fill_between(param_range, train_mean - train_std, train_mean + train_std, color="r", alpha=0.3) plt.plot(param_range, test_mean, label="交叉验证分数", color="g") plt.fill_between(param_range, test_mean - test_std, test_mean + test_std, color="g", alpha=0.3) plt.title("随机森林验证曲线") plt.xlabel("估计器数量") plt.ylabel("准确率") plt.legend(loc="best") plt.show() |
5. 使用贝叶斯优化进行高效搜索
使用贝叶斯优化进行超参数调整是一种非常高效有效的方法。它使用概率模型来探索超参数空间——需要更少的评估和计算资源。
您需要像 scikit-optimize 或 hyperopt 这样的库来执行贝叶斯优化。在这里,我们将使用 scikit-optimize
1 |
!pip install scikit-optimize |
定义超参数空间:指定要搜索的超参数及其各自的范围。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
from skopt import BayesSearchCV from sklearn.tree import DecisionTreeClassifier from sklearn.datasets import load_iris from sklearn.model_selection import train_test_split from sklearn.metrics import accuracy_score # 加载数据 data = load_iris() X_train, X_test, y_train, y_test = train_test_split(data.data, data.target, test_size=0.2, random_state=25) # 初始化模型 model = DecisionTreeClassifier() # 为贝叶斯优化定义超参数空间 param_space = { 'criterion': ['gini', 'entropy'], 'max_depth': [None] + list(range(10, 31)), 'min_samples_split': (2, 10), 'min_samples_leaf': (1, 10) } |
使用带交叉验证的贝叶斯优化进行设置:使用带交叉验证的贝叶斯优化来探索超参数空间。
1 2 3 4 5 6 7 8 |
# 贝叶斯优化 opt = BayesSearchCV(model, param_space, n_iter=32, cv=5, scoring='accuracy') opt.fit(X_train, y_train) best_params_bayes = opt.best_params_ best_score_bayes = opt.best_score_ print(f'最佳参数(贝叶斯优化):{best_params_bayes}') print(f'最佳交叉验证分数(贝叶斯优化):{best_score_bayes:.2f}') |
评估模型:使用贝叶斯优化找到的最佳超参数训练最终模型,并在测试集上评估其性能。
1 2 3 4 5 6 |
best_model = DecisionTreeClassifier(**best_params_bayes) best_model.fit(X_train, y_train) y_pred = best_model.predict(X_test) final_accuracy = accuracy_score(y_test, y_pred) print(f'最终模型准确率: {final_accuracy:.2f}') |
总结
有效的超参数调整可以极大地改善机器学习模型的性能。
通过从一个简单的基线模型开始,并逐步使用搜索技术,您可以系统地探索并找到最佳超参数。从随机搜索的初步探索到贝叶斯优化的有效微调,我们概述了优化模型超参数的实用技巧。
祝您超参数调整愉快!
哇!非常感谢!!
请回答以下问题
如果我想训练两个以上的(许多)机器学习模型,应该选择哪个模型作为基线模型?
谢谢!
Gadisa
你好 Gadisa……不客气!请详细说明您模型的目标,以便我们更好地指导您。