在机器学习领域,模型优化是一项极具挑战性的任务。市场上有许多工具可以帮助简化这一过程。本文将探讨如何高效地微调XGBoost回归模型。在机器学习中,超参数是控制学习过程的参数,例如学习率、正则化、gamma等。这些参数的值不能从数据中估计,它们控制模型在数据上的学习过程。通过调整这些学习参数,可以确保模型能够完美地适应并从数据中学习,从而提供准确的预测。随着模型复杂度的增加,机器学习模型的超参数优化变得越来越复杂。本文将介绍几种流行的优化超参数的方法。
超参数优化有几种流行的方法,包括网格搜索(Grid Search)、随机搜索(Randomized Search)和贝叶斯方法。网格搜索会训练模型在所有可能的超参数组合上,并通过交叉验证进行比较。随机搜索则在随机的超参数组合上训练模型,然后使用交叉验证进行比较。贝叶斯方法使用贝叶斯技术来模拟搜索空间,并找到优化的参数。有许多工具,如HyperOpt、Optuna、SMAC和Spearmint等,专为深度学习和机器学习模型的快速超参数优化而设计。
Optuna是用于微调机器学习和深度学习模型的SOTA算法,它依赖于贝叶斯微调技术。Optuna会剪枝那些不会进一步提高分数的试验,并尝试那些能够提高整体分数的组合。Optuna的主要特点包括:高效搜索大空间并剪枝不具前景的试验以获得更快的结果;能够在不修改代码的情况下,通过多线程或多进程并行化超参数搜索;使用Python的条件语句、循环和语法自动搜索最优超参数。
在本文中,将通过以下几个步骤来详细探讨如何使用Optuna进行超参数调优:在波士顿房价数据集上训练XGBoost;详细探索超参数调优;分析可视化以实现更好更快的调优。
首先,需要导入必要的模块并将数据加载到数据框中。使用sklearn.datasets中的load_boston函数来加载数据,并将其转换为pandas数据框。然后,将数据分为特征X和目标y。接下来,使用StandardScaler对数据进行标准化,这有助于模型更有效地收敛。然后,使用train_test_split将数据集分为训练集和测试集。
import sklearn
import pandas as pd
import numpy as np
from sklearn.datasets import load_boston
boston = load_boston()
df = pd.DataFrame(boston.data, columns=boston.feature_names)
df['target'] = boston.target
X = df.iloc[:, df.columns != 'target']
y = df.target
from sklearn.preprocessing import StandardScaler
se = StandardScaler()
X = se.fit_transform(X)
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=12)
在进行参数调优之前,构建一个基础模型(默认参数)可以为提供一个比较的基准,这样就可以比较调优后模型的改进程度。使用xgboost库中的XGBRegressor,并使用cross_val_score函数来评估模型的性能。
import xgboost as xgb
from sklearn.model_selection import cross_val_score
xg_reg = xgb.XGBRegressor()
scores = cross_val_score(xg_reg, X_train, y_train, scoring='neg_root_mean_squared_error', n_jobs=-1, cv=10)
print(np.mean(scores), np.std(scores))
print(scores)
通常在回归器模型中计算均方根误差(RMSE),在分类器模型中计算AUC分数。下面是一个定义返回分数的函数,它接受超参数作为关键字参数,并返回交叉验证的值。
def return_score(param):
model = xgb.XGBRegressor(**param)
rmse = -np.mean(model_selection.cross_val_score(model, X_train[:1000], y_train[:10000], cv=4, n_jobs=-1, scoring='neg_root_mean_squared_error'))
return rmse
在这一步中,将实际使用Optuna。首先创建一个Optuna study对象,它保存了该研究下尝试的所有超参数信息。然后,定义一个目标函数,它包含所有可能的超参数范围,并返回一个分数值。
import optuna
from optuna import Trial, visualization
from optuna.samplers import TPESampler
def objective(trial):
param = {
"n_estimators": trial.suggest_int('n_estimators', 0, 500),
'max_depth': trial.suggest_int('max_depth', 3, 5),
'reg_alpha': trial.suggest_uniform('reg_alpha', 0, 6),
'reg_lambda': trial.suggest_uniform('reg_lambda', 0, 2),
'min_child_weight': trial.suggest_int('min_child_weight', 0, 5),
'gamma': trial.suggest_uniform('gamma', 0, 4),
'learning_rate': trial.suggest_loguniform('learning_rate', 0.05, 0.5),
'colsample_bytree': trial.suggest_uniform('colsample_bytree', 0.4, 0.9),
'subsample': trial.suggest_uniform('subsample', 0.4, 0.9),
'nthread': -1
}
return return_score(param)
为了开始超参数搜索,需要创建一个Optuna study对象,它保存了该研究下尝试的所有超参数信息。然后,使用study.optimize方法来优化目标函数。
study1 = optuna.create_study(direction='minimize', sampler=TPESampler())
study1.optimize(objective, n_trials=550, show_progress_bar=True)
study1.best_params
optuna.visualization.plot_slice(study1)
params = {}
print(f"without tuning {return_score(params)}")
print(f"with tuning {return_score(study1.best_params)}")