在机器学习模型构建过程中,调整超参数(Hyper-Parameter Optimization)是实现最佳模型性能的关键步骤之一。超参数是训练模型前需设定的参数,用于控制学习算法的行为,而模型在训练过程中学习到的参数则被称为内在参数。由于超参数的选择直接影响到模型的效果和训练效率,如何优化这些超参数成为了一个挑战。
什么是超参数(Hyper-Parameter
)
?
在机器学习中,超参数(Hyper-Parameter)是事先给定的,用来控制学习过程的参数。而其他参数(例如节点权重)的值是通过训练得出的。
超参数可分为模型超参数(Model Hyper-Parameter)和算法超参数(Algorithm Hyper-Parameter)。模型超参数主要用于模型选择,其无助于学习训练集特征;而算法超参数理论上对模型的性能没有影响,而会影响学习的速度和质量。一个典型的模型超参数是神经网络的拓扑结构及大小;而学习率和批量大小(Batch size)、小批量大小(Mini-Batch size)则是典型的算法超参数。
不同的模型训练算法需要用到不同的超参数,一些简单的算法(如普通最小二乘回归)不需要超参数。给定超参数,训练算法会从数据中学习参数。例如,LASSO算法在普通最小二乘回归中加入正则化超参数,在通过训练算法估计参数之前,必须先设置这个超参数。
什么是超参数优化(Hyper-Parameter Optimization)?
在机器学习中,不同的模型会被不断的迭代测试和优化,并且通过调整超参数来获得更好的预测效果。选择最佳模型和超参数是需要解决的挑战,以提高预测的准确性。超参数是可以通过调节来控制机器学习算法行为的指定参数。它们与参数不同,超参数是在训练前设置并提供给模型的,而参数是机器在训练过程中学习到的值。通过选择最佳的超参数值来调整超参数,以获得更高的准确性。这个过程可能非常困难且耗时,但有一些工具可以使这个过程变得更容易,例如随机搜索(Random Search)和网格搜索(Grid Search)。
随机搜索(Random Search):
随机搜索使用的是超参数的随机组合。这意味着并不会尝试所有可能的参数值,而是通过
n_iter
给定的固定迭代次数进行参数采样。关于 Scikit-learn 中超参数随机搜索的指南:
https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.RandomizedSearchCV.html
。
网格搜索(Grid Search):
网格搜索也被称为穷举搜索,它会逐一检查每种超参数组合。这意味着将尝试每一个指定的超参数值组合。关于 Scikit-learn 中超参数网格搜索的指南:
https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.GridSearchCV.html
当搜索空间较大时(即维度超过3个),建议使用随机搜索而不是网格搜索,因为随机搜索能够探索更广泛的超参数空间。当参数较多时,随机搜索可能是更好的选择,因为太多的参数会增加网格搜索的时间复杂度。然而,尽管网格搜索的计算成本可能非常高,但作为一种穷举搜索方法,它在查找所有指定超参数组合时非常有用。
超参优化(Hyper-Parameter Optimization)示例
为了示例这些方法,将使用一个从 Kaggle 获取的数据集"House Prices: Advanced Regression Techniques":
https://www.kaggle.com/c/house-prices-advanced-regression-techniques/overview
。该数据集旨在预测房价销售价格。
测试模型
将在该数据集上测试的模型包括岭回归、随机森林回归和梯度提升回归。为了选择最佳模型,通常应该考虑其他模型,但在本例中,将使用这三种模型作为示例。
-
岭回归(
Ridge regression
)
:通过增加L2惩罚(等于系数大小的平方值)来执行L2正则化,从而创建一个最优简洁性的模型。由于使用相同的因子缩小系数,因此没有系数被消除。
-
随机森林回归(
Random Forest Regression
)
:通过使用一系列基模型的组合来形成一个加性模型。使用多个模型被称为模型集成,而随机森林的最终模型是多个较小独立模型的总和。
-
梯度提升回归(
Gradient Boost Regression
)
:是一个集成学习的模型,由弱预测模型的集成组成,通常是决策树。这些弱树的集成能够变得强大,因为每个后续的树都会学习并改进前一个树的表现。
数据加载和预处理
-
加载数据集
: 使用
pandas
读取 CSV 文件,并将数据加载到
data
变量中。
-
将数据分为特征 (
features
) 和目标变量 (
target
)。
-
将数值型和类别型特征分开,并分别定义预处理步骤:对数值型数据进行填补缺失值和标准化,对类别型数据进行填补缺失值和独热编码。
-
使用
ColumnTransformer
合并预处理步骤,以便对整个数据集进行处理。
-
划分数据集
: 使用
train_test_split
将数据划分为训练集和测试集。
-
应用预处理器
: 使用
fit_transform
和
transform
方法对训练集和测试集进行相应的预处理。
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.impute import SimpleImputer
from sklearn.pipeline import Pipeline
from sklearn.compose import ColumnTransformer
from sklearn.preprocessing import OneHotEncoder
data = pd.read_csv("/home/house_price_train.csv")
features = data.drop(['Id', 'SalePrice'], axis=1)
target = data['SalePrice']
numeric_features = features.select_dtypes(include=['int64', 'float64']).columns
categorical_features = features.select_dtypes(include=['object']).columns
numeric_transformer = Pipeline(steps=[
('imputer', SimpleImputer(strategy='median')),
('scaler', StandardScaler())
])
categorical_transformer = Pipeline(steps=[
('imputer', SimpleImputer(strategy='most_frequent')),
('onehot', OneHotEncoder(handle_unknown='ignore'))
])
preprocessor = ColumnTransformer(
transformers=[
('num', numeric_transformer, numeric_features),
('cat', categorical_transformer, categorical_features)
])
x_train, x_test, y_train, y_test = train_test_split(features, target, test_size=0.2, random_state=42)
x_train = preprocessor.fit_transform(x_train)
x_test = preprocessor.transform(x_test)
使用随机搜索(RandomizedSearchCV)
首先,由于随机搜索比网格搜索占用的处理时间更少,因此将使用随机搜索得分从三种不同的模型(随机森林、岭回归和梯度提升)中选择要进一步分析的模型。另一种选择最佳模型的方法是使用平均交叉验证得分。在这里,使用训练数据集来选择最佳模型。
from sklearn.model_selection import RandomizedSearchCV
from sklearn.ensemble import GradientBoostingRegressor, RandomForestRegressor
from sklearn.linear_model import Ridge
from sklearn.metrics import mean_squared_error
rf_param_grid = {
'n_estimators': [100, 200, 500],
'max_depth': [None, 10, 20],
'min_samples_leaf': [1, 2, 4],
'min_samples_split': [2, 5, 10]
}
ridge_param_grid = {
'alpha': [0.1, 1.0, 10.0],
'solver': ['auto' , 'lsqr', 'sparse_cg', 'sag',]
}
gbr_param_grid = {
'n_estimators': [500, 1000