【机器学习】五种超参数优化技巧转载:我不爱机器学习
超参数是⽤于控制学习过程的不同参数值,对机器学习模型的性能有显著影响。
超参数优化是到超参数值的正确组合,以在合理的时间内实现数据的最⼤性能的过程
1 数据处理
import pandas as pd
import numpy as np
semble import RandomForestRegressor
from sklearn import metrics
del_selection import GridSearchCV, RandomizedSearchCV
from sklearn.preprocessing import StandardScaler
import warnings
warnings.filterwarnings('ignore')
filepath = './AEP_hourly.csv'
data = pd.read_csv(filepath, index_col=0)bootstrap 5
data.shape  # (121273, 1)
data.head()
#                      AEP_MW
# Datetime
# 2004-12-31 01:00:00  13478.0
# 2004-12-31 02:00:00  12865.0
# 2004-12-31 03:00:00  12577.0
# 2004-12-31 04:00:00  12517.0
# 2004-12-31 05:00:00  12670.0
# show data properties
data.describe()
# show data information
data.info()
# check if it has missing values
data.isnull().sum()
# 构建特征
def create_features(data):
data.index = pd.to_datetime(data.index)
data['hour'] = data.index.hour
for i in range(1, 25):
data[f'AEP_MW_lag{i}'] = data['AEP_MW'].shift(i)
data.dropna(inplace=True)
create_features(data)
# split data into features and target
X = data.drop('AEP_MW', axis=1).values[-500:]
y = data['AEP_MW'].values[-500:]
# standardize the feature variables
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
# set different parameter values to tune
param_grid = {
'n_estimators': [100, 200],
'max_depth': [1, 3],
'criterion': ['mse', 'mae'],
}
# Create regressor
rf_regressor = RandomForestRegressor(n_jobs=-1)
2 格⽹优化(Grid Search)
所有可能的参数组合来⼯作。这意味着它将花费⼤量的时间来执⾏⽹格搜索通过在模型中尝试所有可能的参数组合
整个搜索,这在计算上⾮常昂贵。
# set gridsearch
model = GridSearchCV(
estimator=rf_regressor, param_grid=param_grid, cv=5, verbose=2, n_jobs=1
)
# train the model with gridserchCV
model.fit(X_scaled, y)
# print the best score and estimator
print(model.best_score_)
# 0.7891695734212759
print(model.best_estimator_.get_params())
# {'bootstrap': True, 'ccp_alpha': 0.0, 'criterion': 'mae', 'max_depth': 3,
# 'max_features': 'auto', 'max_leaf_nodes': None, 'max_samples': None, 'min_impurity_decrease': 0.0,
# 'min_impurity_split': None, 'min_samples_leaf': 1, 'min_samples_split': 2, 'min_weight_fraction_leaf': 0.0,
# 'n_estimators': 200, 'n_jobs': -1, 'oob_score': False, 'random_state': None, 'verbose': 0, 'warm_start': False}
3 随机查(random search)
这种⽅法的⼯作⽅式有点不同:超参数值的随机组合被⽤来寻所建模型的最佳解决⽅案。
随机搜索的缺点是它有时会遗漏搜索空间中的重要点(值)。
model = RandomizedSearchCV(
estimator=rf_regressor, param_distributions=param_grid, n_iter=5, cv=5, verbose=2, n_jobs=1, random_state=42 )
# train the model with gridserchCV
model.fit(X_scaled, y)
# print the best score and estimator
print(model.best_score_)
# 0.7878893378170959
print(model.best_estimator_.get_params())
# {'bootstrap': True, 'ccp_alpha': 0.0, 'criterion': 'mae', 'max_depth': 3, 'max_features': 'auto',
# 'max_leaf_nodes': None, 'max_samples': None, 'min_impurity_decrease': 0.0, 'min_impurity_split': None,
# 'min_samples_leaf': 1, 'min_samples_split': 2, 'min_weight_fraction_leaf': 0.0, 'n_estimators': 200, 'n_jobs': -1,
# 'oob_score': False, 'random_state': None, 'verbose': 0, 'warm_start': False}
4 Hyperopt
它使⽤⼀种贝叶斯优化形式
贝叶斯优化形式进⾏参数调优,使您能够获得给定模型的最佳参数。它可以对具有数百个参数的模型进⾏⼤规模优化。
Hyperopt有四个重要的特性:
1 Search Space
Hyperopt有不同的函数来指定输⼊参数的范围。这些被称为随机搜索空间。搜索空间最常见的选项是:
hp.choice(label, options):这可以⽤于分类参数。它返回⼀个选项,是⼀个列表或元组。如:
hp.choice('criterion', ['gini','entropy',])
hp.randint(label, upper):可以⽤于整数参数。它返回范围(0,upper)内的⼀个随机整数。如:
hp.randint('max_features',50)
hp.uniform(label, low, high):这将在low和high之间统⼀返回⼀个值
hp.uniform('max_leaf_nodes',1,10)
hp.lognormal(label, mu, sigma):这返回exp(normal(mu, sigma))
hp.qlognormal(label, mu, sigma, q):返回round(exp(normal(mu, sigma)) / q) * q
每个可优化的随机表达式都有⼀个标签(例如,n_estimators)作为第⼀个参数。这些标签⽤于在优化过程中向调⽤者返回参数选择。
2 Objective Function
这是⼀个最⼩化函数,它从搜索空间接收超参数值作为输⼊,并返回损失。
在优化过程中,我们⽤选择的haypeparameter值训练模型,预测⽬标特征。然后我们评估预测误差并将其返回给优化器。
优化器将决定检查哪些值并再次迭代。
3 fmin函数是迭代不同算法集及其超参数,然后最⼩化⽬标函数的优化函数。
其输⼊:⽤于最⼩化的⽬标函数,定义的搜索空间、搜索算法如随机搜索、TPE (Tree Parzen Estimators)和Adaptive TPE。
Hyperopt.rand.suggest和hyperopt.tpe.suggest为超参数空间的顺序搜索提供了逻辑最⼤评估次数、试验对象(可选)。
4 Trials Object
Trials对象⽤于保存所有超参数、损失和其他信息。可以在运⾏优化后访问它。
Trials还可以保存重要信息,稍后加载,然后恢复优化过程
步骤
初始化需要查的空间
定义⽬标函数
选择搜索算法
运⾏hyperopt函数
在trials object 中分析评估输出
del_selection import cross_val_score
from hyperopt import tpe, hp, fmin, STATUS_OK, Trials
from hyperopt.pyll.base import scope
# step 1 : 初始化需要查的空间
space = {'n_estimators': hp.choice('n_estimators', [100, 200]),
'max_depth': hp.quniform('max_depth', 1, 4, 1),
'criterion': hp.choice('criterion', ['mse', 'mae'])}
# step 2 : 定义⽬标函数
# /stable/modules/model_evaluation.html#scoring-parameter
def hyperparameter_tuning(params):
reg = RandomForestRegressor(**params, n_jobs=-1)
mae = cross_val_score(reg, X_scaled, y, scoring='neg_mean_absolute_error').mean()
return {'loss': -mae, 'status': STATUS_OK}
# step 3 : 初始化试验对象
trials = Trials()
best = fmin(
fn=hyperparameter_tuning,
space=space,
algo=tpe.suggest,
max_evals=100,
trials=trials
)
print(f'best:{best}')
# 100%|██████████| 100/100 [03:52<00:00,  2.33s/trial, best loss: 477.21263500000003]
# best:{'criterion': 1, 'max_depth': 4.0, 'n_estimators': 1}
# step 4 : 基于试验对象分析结果
#  show a list of dictionaries returned by 'objective' during the search
# [{'loss': 511.437781538007, 'status': 'ok'},
#  {'loss': 538.1389298379975, 'status': 'ok'},
# ...]
# shows a list of losses (float for each 'ok' trial).
trials.losses()
# shows a list of status strings
trials.statuses()
这个trials对象可以保存、传递给内置绘图例程
5 Scikit-Optimize
Scikit-optimize是另⼀个⽤于超参数优化的开源Python库。
它实现了⼏种基于序列模型的优化⽅法。
该库⾮常易于使⽤,并为贝叶斯优化提供了⼀个通⽤⼯具包,可⽤于超参数调优。
它还⽀持调整scikit-learn库提供的机器学习算法的超参数。
scikit- optimization是建⽴在Scipy、NumPy和Scikit-Learn之上的。
为了进⾏第⼀次优化,scikit - optimization⾄少需要了解四个重要特性:
1 space
Scikit-optimize有不同的函数来定义⼀个或多个维度的优化空间。最常见的搜索空间选择是: Real:这是⼀个搜索空间维度,可以具有任何实际值。需要定义下界和上界,两者都是包含的。Real(low=0.2, high=0.9, name='min_samples_leaf')
Integer:可以取整数值的搜索空间维度。Integer(low=3, high=25, name='max_features') Categorical:这是⼀个搜索空间维度,可以使⽤分类值
Categorical(['gini','entropy'],name='criterion')
在每个搜索空间中,必须定义超参数名称,以便使⽤name参数进⾏优化。
2 BayesSearchCV
BayesSearchCV类提供了⼀个类似于GridSearchCV或RandomizedSearchCV的接⼝,但是它对超参数执⾏贝叶斯优化。
BayesSearchCV实现了⼀个fit和⼀个score⽅法,以及其他常见的⽅法,如predict()、
predict_proba()、 decision_function()、transform()和inverse_transform(),如果使⽤的估计器中有的话。
采样固定数量的与GridSearchCV不同的是,并⾮所有参数值都被尝试
并⾮所有参数值都被尝试。⽽是从指定的分布中采样固定数量
参数设置。尝试的参数设置的数量由n_iter给出。
3 ⽬标函数
这是搜索过程将调⽤的函数。它从搜索空间接收超参数值作为输⼊,并返回损失(越低越好)。在优化过程中,我们⽤选择的超参数值训练模型,预测⽬标特征。然后我们评估预测误差并将其返回给优化器
优化器将决定检查哪些值并再次迭代。
4 优化器
这是执⾏贝叶斯超参数优化过程的函数。优化函数在每个模型和搜索空间迭代以优化并最⼩化
⽬标函数。
scikit- optimization库提供了不同的优化函数,例如:dummy_minimize在给定范围内通过均匀抽样进⾏随机搜索。
使⽤决策树进⾏顺序优化。使⽤梯度增强树进⾏顺序优化。使⽤⾼斯过程的gp_minimize贝叶斯优化。
第⼀种⽅法:
from skopt.searchcv import BayesSearchCV
from skopt.space import Integer, Real, Categorical
from skopt.utils import use_named_args
from skopt import gp_minimize
# define search space
params = {
'n_estimators': [100, 300],
'max_depth': (1, 9),
'criterion': ['mse', 'mae']
}
# define the search
search = BayesSearchCV(
estimator=rf_regressor,
search_spaces=params,
n_jobs=1,
cv=5,
n_iter=30,
scoring='neg_mean_absolute_error',
verbose=4,
random_state=42
)
# perform the search
search.fit(X_scaled, y)
# report the best result
print(search.best_score_)  # -469.6407772534216
print(search.best_params_)
# OrderedDict([('criterion', 'mse'), ('max_depth', 6), ('n_estimators', 100)])
第⼆种⽅法:
# define the space of hyperparameters to search
search_space = []
search_space.append(Categorical([100, 200], name='n_estimators'))
search_space.append(Categorical(['mse', 'mae'], name='criterion'))
search_space.append(Integer(1, 9, name='max_depth'))
# define the function used to evaluate a given configuration
@use_named_args(search_space)
def evaluate_model(**params):
# configure the model with specific hyperparameters
reg = RandomForestRegressor(**params, n_jobs=-1)
mae = cross_val_score(reg, X_scaled, y, scoring='neg_mean_absolute_error').mean()
return -mae
# perform optimization
result = gp_minimize(
func=evaluate_model,
dimensions=search_space,
n_calls=30,
random_state=42,
verbose=True,
n_jobs=1,
)
# summarizing finding:
print('Best Accuracy: %.3f' % (result.fun))
# Best Accuracy: 480.179