超参数调优方法、工具以及基于AutoML和算法的超参数调优详解。
一、什么是机器学习超参数?
机器学习超参数是在开始学习过程之前设置值的参数,而不是通过训练得到的参数数据。
超参数是在模型训练之外设置的选项,不会在训练过程中被优化或更改。相反,需要在训练之前手动设置它们,并且对模型的性能有很大的影响。
二、为什么要进行机器学习超参数的调优?
在机器学习中,通常需要针对特定任务选择和调整超参数。例如,在支持向量机(SVM)中,有一个重要的超参数是正则化参数C,它可以控制模型复杂度并影响模型的泛化能力。在训练神经网络时,学习率和批次大小也是常见的超参数,它们可以影响模型的收敛速度和最终的预测效果。
机器学习超参数的调优是为了找到一组最佳的超参数组合,使模型在特定任务上表现最佳。超参数的调优对于提高模型性能、防止过拟合、加速收敛等方面都非常重要。
不同的超参数组合可以显著影响模型的性能,因此通过调优来找到最佳的超参数组合是非常必要的。
下文从网格搜索等直接调优方法、基于Optuna等调优工具、基于AutoML的调优、基于算法的调优等4个方面进行阐述。 whaosoft aiot http://143ai.com
三、超参数调优方法
常用的超参数调优方法有以下几种:
-
网格搜索(Grid Search):网格搜索是一种简单的超参数调优方法,它通过穷举指定的参数组合,计算每一组参数在验证集上的表现,最终选择表现最好的参数组合。
-
贝叶斯优化:贝叶斯优化是一种利用贝叶斯定理和最优化方法寻找全局最优解的优化算法,它适用于高维、高成本、有限样本的优化问题。
-
随机搜索(Random Search):随机搜索是一种基于随机采样的超参数调优方法,它通过在参数空间中随机选择参数组合,寻找最优解。
3.1 网格搜索Grid Search
1、什么是网格搜索
网格搜索(Grid Search)是一种超参数调优方法,它通过穷举指定的参数组合,计算每一组参数在验证集上的表现,最终选择表现最好的参数组合。https://pyimagesearch.com/2021/05/24/grid-search-hyperparameter-tuning-with-scikit-learn-gridsearchcv/
网格搜索是一种简单而有效的调优方法,常用于确定最佳的超参数组合。
2、网格搜索的python实战
from sklearn.model_selection import GridSearchCV
from sklearn.svm import SVC
from sklearn.datasets import load_iris
# 加载数据集
iris = load_iris()
X = iris.data
y = iris.target
# 定义模型
svm = SVC(kernel='linear', C=100, gamma='auto')
# 定义网格搜索参数范围
param_grid = {
'C': [0.1, 1, 10, 100],
'gamma': [1e-3, 1e-2, 1e-1, 1],
}
# 创建网格搜索对象
grid_search = GridSearchCV(svm, param_grid, cv=5)
# 对数据进行网格搜索
grid_search.fit(X, y)
# 输出最佳参数组合和对应的得分
print('Best parameters:', grid_search.best_params_)
print('Best score:', grid_search.best_score_)
-
使用了Scikit-learn库中的GridSearchCV类来实现网格搜索
-
定义了一个参数网格(param_grid),其中包含了C和gamma两个超参数的不同取值组合
-
创建了一个GridSearchCV对象,并将参数网格、SVM模型和交叉验证(cv)参数传入
-
使用best_params_和best_score_属性输出最佳参数组合和对应的得分
3.2 随机搜索Random Search
1、什么是随机搜索
随机搜索是一种优化方法,它通过在允许的范围内随机生成点来搜索可能的解决方案,并计算每个点的目标函数值。然后,它根据目标函数值选择下一个点进行搜索,以逐步接近最优解。
这种方法适用于处理高维、非线性、非凸或非连续的优化问题,特别是当精确解的计算成本非常高时。
2、基于随机搜索的python实战
import numpy as np
from sklearn.datasets import load_iris
from sklearn.ensemble import RandomForestClassifier
# 加载数据集
iris = load_iris()
X = iris.data
y = iris.target
# 定义随机搜索函数
def random_search(X, y, model, param_space, iteration_num):
best_score = -1
best_params = None
for i in range(iteration_num):
# 从参数空间中随机采样一组超参数
params = {k: v[np.random.randint(len(v))] for k, v in param_space.items()}
# 训练模型并计算验证集上的准确率
model.set_params(**params)
score = model.score(X[:100], y[:100])
# 更新最优解
if score > best_score:
best_score = score
best_params = params
return best_score, best_params
# 定义随机森林分类器模型
model = RandomForestClassifier()
# 定义超参数空间
param_space = {
'n_estimators': [100, 200, 300, 400, 500],
'max_depth': [2, 3, 4, 5, 6],
'max_features': ['auto', 'sqrt', 'log2'],
'bootstrap': [True, False]
}
# 执行随机搜索
best_score, best_params = random_search(X, y, model, param_space, 100)
print('最佳准确率:', best_score)
print('最佳超参数:', best_params)
-
使用随机森林分类器模型,并定义了四个需要优化的超参数:n_estimators、max_depth、max_features和bootstrap
-
从参数空间中随机采样100组超参数,然后使用验证集上的准确率来评估这些超参数的优劣,最终输出最佳准确率和对应的最佳超参数
网格搜索优化和随机搜索优化的对比:3.3 贝叶斯优化
1、什么是贝叶斯优化
贝叶斯优化是一种黑盒优化算法,用于求解表达式未知的函数的极值问题。它基于贝叶斯定理,通过构建概率模型来描述目标函数的后验分布,并利用这个模型来选择下一个采样点,以最大化采样价值。
其核心思想是利用高斯过程回归(Gaussian Process Regression, GPR)来建模目标函数的分布。GPR认为目标函数是由一系列训练数据点(输入和输出)所构成的随机过程,通过高斯概率模型来描述这个随机过程的概率分布。贝叶斯优化通过不断地添加样本点来更新目标函数的后验分布,直到后验分布基本贴合真实分布。
贝叶斯优化有两个核心过程:
-
先验函数(Prior Function, PF):PF主要利用高斯过程回归来建模目标函数的先验分布
-
采集函数(Acquisition Function, AC):AC主要包括 Expected Improvement(EI)、Probability of Improvement(PI)和 Upper Confidence Bound(UCB)等方法,用于衡量每一个点对目标函数优化的贡献,并选择下一个采样点。
贝叶斯优化在机器学习种被用于AutoML算法,自动确定机器学习算法的超参数。它也是一种全局极值搜索方法,特别适用于高维非线性非凸函数,具有较好的效果和效率。
贝叶斯优化以函数被视为一个满足某种分布的随机过程,通过在定义域内求函数值,使用贝叶斯公式更新对分布的估计,然后根据新的分布找到最可能的极值点位置,从而提高对函数及其极值的估计的精确性。
2、贝叶斯优化的python实战
import numpy as np
from scipy.optimize import minimize
from sklearn.gaussian_process import GaussianProcessRegressor
from sklearn.gaussian_process.kernels import RBF, ConstantKernel as C
# 定义目标函数
def f(x):
return np.sin(5 * x) + np.cos(x)
# 定义高斯过程回归模型
kernel = C(1.0, (1e-3, 1e3)) * RBF(10, (1e-2, 1e2))
gpr = GaussianProcessRegressor(kernel=kernel, n_restarts_optimizer=10)
# 定义贝叶斯优化函数
def bayesian_optimization(X_train, y_train, X_test):
# 训练高斯过程回归模型
gpr.fit(X_train, y_train)
# 计算测试集的预测值和方差
y_pred, sigma = gpr.predict(X_test, return_std=True)
# 计算期望改进(Expected Improvement)
gap = y_pred - f(X_test)
improvement = (gap + np.sqrt(sigma ** 2 + 1e-6) * np.abs(gap).mean()) * 0.5
# 计算高斯过程回归模型的超参数
result = minimize(gpr.kernel_, np.zeros(gpr.kernel_.shape[0]), method='L-BFGS-B')
hyperparameters = result.x
# 输出最优超参数和对应的期望改进值
return hyperparameters, improvement.max()
# 定义贝叶斯优化的迭代次数和采样点数量
n_iter = 20
n_samples = 5
# 进行贝叶斯优化
results = []
for i in range(n_iter):
# 在定义域内随机采样n_samples个点
X_train = np.random.uniform(-2 * np.pi, 2 * np.pi, (n_samples, 1))
y_train = f(X_train)
# 进行贝叶斯优化并记录最优超参数和对应的期望改进值
result = bayesian_optimization(X_train, y_train, X_test=np.random.uniform(-2 * np.pi, 2 * np.pi, (100, 1)))
results.append(result)
print('Iter: {}, Hyperparameters: {:.2f}, Expected Improvement: {:.4f}'.format(i, result[0][0], result[1]))
-
定义目标函数f
-
使用高斯过程回归模型(GPR)来建模目标函数的分布
-
定义贝叶斯优化函数bayesian_optimization;其中训练集、测试集和采样点数作为输入,输出最优的超参数和对应的期望改进值
-
Expected Improvement作为采集函数,通过不断地添加样本点来更新目标函数的后验分布,并使用L-BFGS-B方法来最小化高斯过程回归模型的超参数
四、基于超参数调优工具
4.1 什么是超参数优化库?
超参数优化库(Hyperparameter Optimization Library)是一种用于自动化超参数优化的软件库或工具。这些库使用不同的算法和技术,以实现自动化超参数搜索和优化过程。
超参数优化库通常提供易于使用的接口,允许用户定义要优化的超参数和目标函数。它们使用不同的算法和技术,如网格搜索、随机搜索、遗传算法、贝叶斯优化等,以搜索和优化超参数空间。这些库的目标是减少人工调整超参数的工作量,提高模型性能,并加速机器学习模型的训练过程。
4.2 常见的超参数优化工具
以下是几个常用的超参数优化库:
-
scikit-Opitimize
-
Hyperopt
-
Optuna
-
Spearmint
-
Gaussian Process-based Hyperparameter Optimization (GPGO)
-
Ray Tune
-
GPyOpt
-
SigOpt
-
Keras Tuner
这些库都提供了不同的算法和工具,以实现超参数优化,并具有不同的特点和优点。您可以根据您的需求选择最适合您的库。
4.3 Scikit-Optimize库
1、Scikit-Optimize库简介
Scikit-optimize 是一个 Python 库,用于执行基于scipy的优化算法。它旨在提供一种简单而有效的工具,用于机器学习和科学计算的优化问题。Scikit-optimize 提供了许多不同的优化算法,包括梯度下降、随机搜索、贝叶斯优化等。
Scikit-optimize 提供了许多预定义的搜索空间和目标函数,以便轻松地设置超参数优化任务。用户可以定义自己的搜索空间和目标函数,以适应特定的机器学习模型和任务。Scikit-optimize 还提供了可视化工具,可以帮助用户更好地理解优化过程和结果。
2、基于python的Scikit-Optimize库优化实战
import numpy as np
from sklearn.datasets import load_iris
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
from skopt import gp_minimize
# 加载数据集
iris = load_iris()
X = iris.data
y = iris.target
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 定义机器学习模型
clf = RandomForestClassifier()
# 定义搜索空间和目标函数
search_space = {
'n_estimators': [100, 200, 500],
'max_depth': [3, 5, None],
'max_features': ['auto', 'sqrt', 'log2']
}
def objective(x):
clf.set_params(**{search_space[name]: x[name] for name in x})
clf.fit(X_train, y_train)
y_pred = clf.predict(X_test)
return -accuracy_score(y_te