超参数优化

超参数是用于控制学习过程的不同参数值,对机器学习模型的性能有显著影响。例如,随机森林算法中的估计器数量、最大深度和分裂标准等。超参数优化是找到超参数值的正确组合,以便在合理的时间内实现数据最大性能的过程。这个过程在机器学习算法的预测准确性中起着至关重要的作用。因此,超参数优化被认为是构建机器学习模型中最棘手的部分。

目前来说sklearn支持两种类型的超参数优化:

  • GridSearchCV 网格搜索是一种广泛使用的传统方法,详尽地考虑了所有参数组合
  • RandomizedSearchCV 随机搜索可以从具有指定分布的参数空间中抽样给定数量的候选者

贝叶斯优化方法 (Bayesian Optimization)是当前超参数优化领域的SOTA手段(State of the Art),可以被认为是当前最为先进的优化框架。

贝叶斯优化的工作原理是:首先对目标函数的全局行为建立先验知识(通常用高斯过程来表示),然后通过观察目标函数在不同输入点的输出,更新这个先验知识,形成后验分布。基于后验分布,选择下一个采样点,这个选择既要考虑到之前观察到的最优值(即利用),又要考虑到全局尚未探索的区域(即探索)。这个选择的策略通常由所谓的采集函数(Acquisition Function)来定义,比如最常用的期望提升(Expected Improvement),这样,贝叶斯优化不仅可以有效地搜索超参数空间,还能根据已有的知识来引导搜索,避免了大量的无用尝试。

具体的算法细节可以参考:https://zhuanlan.zhihu.com/p/643095927?utm_id=0

本文介绍一些实用的超参数优化技术:

  1. Hyperopt
  2. Scikit Optimize
  3. Optuna
# read the dataset
from sklearn.datasets import load_boston
from sklearn.model_selection import train_test_split

X, y = load_boston(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3)

Hyperopt

Hyperopt优化器是目前最通用的贝叶斯优化器之一,它集成了包括随机搜索、模拟退火和TPE(Tree-structured Parzen Estimator Approach)等多种优化算法。

官方文档:https://hyperopt.github.io/hyperopt/

安装库

pip install hyperopt

Hyperopt 优化过程主要分为4步:

Step 1 定义参数空间
Step 2 定义目标函数
Step 3 执行优化
Step 4 评估输出

Step 1 定义参数空间

我们使用dict()来定义超参数空间,其中key可以任意设置,value则需用hyperopt的hp函数:

hyperopt.hp 说明
hp.choice(label, options) 用于分类参数,返回options 中的元素
hp.pchoice(label, p_list) 返回 (probability, option) 元素对
hp.randint(label, low, high) 返回区间 [low, upper) 内的随机整数
hp.uniform(label, low, high) 均匀返回 low, high 之间的浮点数
hp.quniform(label, low, high, q) 均匀返回 low, high 之间的浮点数,适用于离散值
hp.uniformint(label, low, high) 均匀返回 low, high 之间均的整数,适用于离散值
hp.loguniform(label, low, high) 对数均匀返回 elow,ehigh 之间浮点数
hp.qloguniform(label, low, high, q) 对数均匀返回 elow, ehigh 之间浮点数,适用于离散值
hp.normal(label, mu, sigma) 正态分布返回实数
hp.qnormal(label, mu, sigma, q) 正态分布返回实数,适用于离散值
hp.lognormal(label, mu, sigma) 对数正态分布返回实数
hp.qlognormal(label, mu, sigma, q) 正态分布返回实数,适用于离散值

每个hp函数都有一个label作为第一个参数,这些label用于在优化过程中将参数传递给调用方。

# define a search space
from hyperopt import hp
space = {
'random_state': 42,
'max_depth': hp.uniformint('max_depth', 2, 10),
'learning_rate': hp.loguniform('learning_rate', 0.001, 1.0),
'n_estimators': hp.choice('n_estimators', [100, 200, 300, 400]),
'subsample': hp.quniform('subsample', 0.1, 1.0, 0.1),
'max_features': hp.choice('max_features', ['sqrt', 'log2'])
}

Step 2 定义目标函数

Hyperopt 目前只支持目标函数的最小化

# define an objective function
from sklearn.ensemble import GradientBoostingRegressor
from sklearn.model_selection import cross_val_score

def objective(params):
reg = GradientBoostingRegressor(**params)
mse = cross_val_score(reg, X_train, y_train, scoring='neg_mean_squared_error', cv=5).mean()
return -1*mse

Step 3 执行优化

hyperopt 使用 fmin 函数进行优化。

fmin接收两种搜索算法:

  • tpe.suggest 指代TPE (Tree Parzen Estimators) 方法
  • rand.suggest 指代随机网格搜索方法
# minimize the objective over the space
from hyperopt import fmin, tpe, space_eval, Trials
trials = Trials() # Initialize trials object

best = fmin(
fn=objective, # Objective Function to optimize
space=space, # Hyperparameter's Search Space
algo=tpe.suggest, # Optimization algorithm
max_evals=100, # Number of optimization attempts
trials = trials,
verbose=True,
early_stop_fn=no_progress_loss(5)
)

Output:

100%|██████| 1000/1000 [02:35<00:00,  6.44trial/s, best loss: 8.932729710763638]

其中 Trials 对象用于保存所有的超参数、损失和其他信息。

Step 4 评估输出

print(space_eval(space, best))

Output:

{'learning_rate': 0.2, 'max_depth': 5, 'max_features': 'sqrt', 'n_estimators': 54, 'subsample': 0.9}

分布式优化

并行化 Hyperopt 超参数优化

超参数调优通常涉及训练数百或数千个模型,Hyperopt 允许分布式调优。通过 trials 参数将 SparkTrials 传递给 fmin 函数,在Spark集群上并行运行这些任务。

# We can run Hyperopt locally (only on the driver machine)
# by calling `fmin` without an explicit `trials` argument.
best_hyperparameters = fmin(
fn=train,
space=search_space,
algo=algo,
max_evals=32)

# We can distribute tuning across our Spark cluster
# by calling `fmin` with a `SparkTrials` instance.
from hyperopt import SparkTrials
spark_trials = SparkTrials()
best_hyperparameters = fmin(
fn=train,
space=search_space,
algo=algo,
trials=spark_trials,
max_evals=32)

SparkTrials可以通过3个参数进行配置,所有这些参数都是可选的:

  • parallelism 最大并行数,默认为 SparkContext.defaultParallelism。
  • timeout 允许的最大时间(以秒为单位),默认为None。
  • spark_session 如果没有给出,SparkTrials将寻找现有的SparkSession。

除了单机训练算法(例如 scikit-learn 中的算法)以外,还可以将 Hyperopt 与分布式训练算法配合使用。将 Hyperopt 与分布式训练算法配合使用时,请不要将 trials 参数传递给 fmin(),尤其是不要使用 SparkTrials 类。 SparkTrials 旨在为本身不是分布式算法的算法分配试运行。 对于分布式训练算法,请使用在群集驱动程序上运行的默认 Trials 类。 Hyperopt 评估驱动程序节点上的每个试运行,使 ML 算法本身可以启动分布式训练。

将分布式训练算法与 Hyperopt 配合使用

Scikit-optimize

Scikit-optimize 建立在 Scipy、Numpy 和 Scikit-Learn之上。非常易于使用,它提供了用于贝叶斯优化的通用工具包,可用于超参数调优。

官方文档:https://scikit-optimize.github.io/stable/

安装库

pip install scikit-optimize

Scikit-optimize 优化过程主要分为4步:

Step 1 定义参数空间
Step 2 定义目标函数
Step 3 执行优化
Step 4 评估输出

Step 1 定义参数空间

使用 Scikit-optimize 提供的方法定义参数空间:

skopt.space comment
space.Real(low, high, prior, name) 用于浮点数参数
space.Integer(low, high, prior, name) 用于整数参数
space.Categorical(categories, prior, name) 用于分类参数

通过可选的prior参数可以对整型或浮点型取对数操作,或给类别型先验概率

# define a search space
import skopt
search_space= [
skopt.space.Integer(2, 10, name='max_depth'),
skopt.space.Real(0.001, 1.0, prior='log-uniform', name='learning_rate'),
skopt.space.Integer(10, 100, name='n_estimators'),
skopt.space.Real(0.2, 0.9, name='subsample'),
skopt.space.Categorical(['sqrt', 'log2'], name='max_features')
]

Step 2 定义目标函数

Scikit-optimize 支持目标函数最小化。

from sklearn.ensemble import GradientBoostingRegressor
from sklearn.model_selection import cross_val_score
from skopt.utils import use_named_args

# define the function used to evaluate a given configuration
@use_named_args(space)
def objective(**params):
# configure the model with specific hyperparameters
clf = GradientBoostingRegressor( random_state=42, **params)
mse = cross_val_score(reg, X_train, y_train, scoring='neg_mean_squared_error', cv=5).mean()
return -1*mse

一般使用交叉验证来避免过拟合。used_named_args装饰器允许目标函数将参数作为关键字参数接收。

Step 3 执行优化

有四种优化算法可供选择:

skopt.optimizer 说明
dummy_minimize 随机搜索
forest_minimize 使用决策树的贝叶斯优化
gbrt_minimize 使用GBRT的贝叶斯优化
gp_minimize 使用高斯过程的贝叶斯优化
from skopt import gp_minimize

# perform optimization
result = gp_minimize(
func=objective,
dimensions=search_space,
n_calls=100,
random_state=42,
verbose=True
)

Step 4 评估输出

打印最佳得分和最佳参数

# summarizing finding:
print(f'Best score: {result.fun}')
print(f'Best parameters: {result.x}')

打印优化过程中的目标函数值

print(result.func_vals)

绘制收敛轨迹

# plot convergence traces
from skopt.plots import plot_convergence
plot_convergence(result)

Scikit-Learn API

Scikit-optimize 提供了一个类似于 GridSearchCV 和 RandomizedSearchCV 的接口 BayesSearchCV,实现了 fit 和 score 方法,以及 predict, predict_proba, decision_function, transform and inverse_transform 等常用方法。

from skopt.searchcv import BayesSearchCV
from sklearn.ensemble import GradientBoostingRegressor

# define search space
params = {
"max_depth": (2, 10), # integer valued parameter
"learning_rate": (0.001, 1.0, 'log-uniform')
"n_estimators": [100, 200, 300, 400],
"subsample": (0.2, 0.9, 'uniform')
"max_features": ["sqrt", "log2"], # categorical parameter
}

# define the search
optimizer = BayesSearchCV(
estimator=GradientBoostingRegressor(),
search_spaces=params,
cv=5,
n_iter=100,
scoring="accuracy",
verbose=4,
random_state=42
)

# executes bayesian optimization
optimizer.fit(X_train, y_train)

# report the best result
print(optimizer.best_score_)
print(optimizer.best_params_)

Optuna

Optuna是目前为止最成熟、拓展性最强的超参数优化框架,它是专门为机器学习和深度学习所设计。为了满足机器学习开发者的需求,Optuna拥有强大且固定的API,因此Optuna代码简单,编写高度模块化,

Optuna可以无缝衔接到PyTorch、Tensorflow等深度学习框架上,也可以与sklearn的优化库scikit-optimize结合使用,因此Optuna可以被用于各种各样的优化场景。

官方文档:https://optuna.org/

安装库

pip install optuna

Optuna 优化过程主要分为3步:

Step 1 构建目标函数及参数空间
Step 2 执行优化
Step 3 评估输出

Step 1 构建目标函数及参数空间

Optuna 基于 Trial 和 Study 两个组件实现优化(optimization)。在优化过程中,Optuna 反复调用目标函数,在不同的参数下对其进行求值。一个 Trial 对应着目标函数的单次执行。在每次调用目标函数的时候,它都被内部实例化一次。而 suggest API (例如 suggest_uniform()) 在目标函数内部调用,被用于获取单个 trial 的参数。

Optuna 允许在目标函数中定义参数空间和目标,优化器会通过trail所携带的方法来构造参数空间。

optuna.trial.Trial 说明
trial.suggest_categorical(name, choices) 适用于分类参数
trial.suggest_int(name, low, high, step=1, log=False) 适用于整数参数
trial.suggest_float(name, low, high, *, step=None, log=False) 适用于浮点参数
trial.suggest_uniform(name, low, high) 均匀分布
trial.suggest_loguniform(name, low, high) 对数均匀分布
trial.suggest_discrete_uniform(name, low, high, q) 离散均匀分布

通过可选的 step 与 log 参数,我们可以对整形或者浮点型参数进行离散化或者取对数操作。

from sklearn.ensemble import GradientBoostingRegressor
from sklearn.model_selection import cross_val_score

# define the search space and the objecive function
def objective(trial):
# Define the search space
params= {
'max_depth': trial.suggest_int('max_depth', 2, 10, 1),
'learning_rate': trial.suggest_float('learning_rate', 0.001, 1.0, log=True),
'n_estimators': trial.suggest_int('n_estimators', 100, 400, 100),
'subsample': trial.suggest_float('subsample', 0.1, 1.0, 0.1),
'max_features': trial.suggest_categorical('max_features', ['sqrt', 'log2'])
}
reg = GradientBoostingRegressor(**params)
mse = cross_val_score(reg, X_train, y_train, scoring='neg_mean_squared_error', cv=5).mean()
return mse

通常使用交叉验证来避免过拟合。

Step 2 执行优化

下面是几个常用术语:

  • Trial: 目标函数的单次调用
  • Study: 一次优化过程,包含一系列的 trials.
  • Parameter: 待优化的参数

在 Optuna 中,我们用 study 对象来管理优化过程。 create_study() 方法会返回一个 study 对象 ,可以填写minimize或maximize确定优化方向,然后通过 .optimize 方法执行优化过程。

可以通过模块optuna.sampler来定义优化算法:

  • GridSampler:网格搜索
  • RandomSampler:随机抽样
  • TPESampler:使用TPE (Tree-structured Parzen Estimator) 算法
  • CmaEsSampler:使用 CMA-ES算法
from optuna.samplers import TPESampler

# create a study object
study = optuna.create_study(direction="maximize", sampler=TPESampler())

# # Invoke optimization of the objective function.
study.optimize(objective, n_trials=100)

获得 trial 的数目:

len(study.trials)

Out: 100

再次执行 optimize(),可以继续优化过程

study.optimize(objective, n_trials=100)

获得更新后的的 trial 数量:

len(study.trials)

Out: 200

Step 3 评估输出

打印最佳最佳分数和超参数值

print(f'Best score: {study.best_value}') 
print('Best parameters: ', *[f'- {k} = {v}' for k,v in study.best_params], sep='\n')

Optuna 中提供了不同的方法来可视化优化结果:

函数 说明
plot_contour(study) 将参数关系绘制成等值线
plot_intermidiate_values(study) 绘制所有trial的学习曲线
plot_optimization_history(study) 绘制所有trial的优化历史记录
plot_param_importances(study) 绘制超参数重要性及其值
plot_edf(study) 绘制study目标值的edf
optuna.visualization.plot_optimization_history(study)

参数空间进阶

在 Optuna 中,我们使用和 Python 语法类似的方式来定义搜索空间,其中包含条件和循环语句。

分支:

import sklearn.ensemble
import sklearn.svm

def objective(trial):
classifier_name = trial.suggest_categorical("classifier", ["SVC", "RandomForest"])
if classifier_name == "SVC":
svc_c = trial.suggest_float("svc_c", 1e-10, 1e10, log=True)
classifier_obj = sklearn.svm.SVC(C=svc_c)
else:
rf_max_depth = trial.suggest_int("rf_max_depth", 2, 32, log=True)
classifier_obj = sklearn.ensemble.RandomForestClassifier(max_depth=rf_max_depth)

循环:

import torch
import torch.nn as nn

def create_model(trial, in_size):
n_layers = trial.suggest_int("n_layers", 1, 3)

layers = []
for i in range(n_layers):
n_units = trial.suggest_int("n_units_l{}".format(i), 4, 128, log=True)
layers.append(nn.Linear(in_size, n_units))
layers.append(nn.ReLU())
in_size = n_units
layers.append(nn.Linear(in_size, 10))

return nn.Sequential(*layers)

多目标优化

from sklearn.metrics import make_scorer, root_mean_squared_error
def objective(trial):
# Define the search space
params= {
'max_depth': trial.suggest_int('max_depth', 2, 10, 1),
'learning_rate': trial.suggest_float('learning_rate', 0.001, 1.0, log=True),
'n_estimators': trial.suggest_int('n_estimators', 100, 400, 100),
'subsample': trial.suggest_float('subsample', 0.1, 1.0, 0.1),
'max_features': trial.suggest_categorical('max_features', ['sqrt', 'log2'])
}
reg = GradientBoostingRegressor(**params)
mse = cross_val_score(reg, X_train, y_train, scoring=make_scorer(root_mean_squared_error), cv=5).mean()
r2 = cross_val_score(reg, X_train, y_train, scoring='r2', cv=5).mean()
return mse, r2

study = optuna.create_study(directions=["minimize", "maximize"])
study.optimize(objective, n_trials=100, timeout=300)
print("Number of finished trials: ", len(study.trials))

注意:多目标优化使用的参数 directions 和单目标参数direction不同。

分布式优化

可使用 Joblib Apache Spark 后端将 Optuna 试验分发到 Azure Databricks 群集中的多台计算机。

使用 Optuna 进行超参数优化

import joblib
from joblibspark import register_spark

register_spark() # register Spark backend for Joblib
with joblib.parallel_backend("spark", n_jobs=-1):
study.optimize(objective, n_trials=100)

常见问题

官方链接:https://optuna.readthedocs.io/en/stable/faq.html

如何定义带有额外参数的目标函数?

有两种方法可以实现这类函数。

首先,如下例所示,可调用的 objective 类具有这个功能:

import optuna


class Objective:
def __init__(self, min_x, max_x):
# Hold this implementation specific arguments as the fields of the class.
self.min_x = min_x
self.max_x = max_x

def __call__(self, trial):
# Calculate an objective value by using the extra arguments.
x = trial.suggest_float("x", self.min_x, self.max_x)
return (x - 2) ** 2


# Execute an optimization by using an `Objective` instance.
study = optuna.create_study()
study.optimize(Objective(-100, 100), n_trials=100)

其次,你可以用 lambda 或者 functools.partial 来创建带有额外参数的函数(闭包)。 下面是一个使用了 lambda 的例子:

import optuna

# Objective function that takes three arguments.
def objective(trial, min_x, max_x):
x = trial.suggest_float("x", min_x, max_x)
return (x - 2) ** 2


# Extra arguments.
min_x = -100
max_x = 100

# Execute an optimization by using the above objective function wrapped by `lambda`.
study = optuna.create_study()
study.optimize(lambda trial: objective(trial, min_x, max_x), n_trials=100)

其他例子参见 sklearn_addtitional_args.py .

如何在目标函数中保存训练好的机器学习模型?

Optuna 会保存超参数和对应的目标函数值,但是它不会存储诸如机器学习模型或者网络权重这样的中间数据。要保存模型或者权重的话,请利用你正在使用的机器学习库提供的对应功能。

在保存模型的时候,我们推荐将 optuna.trial.Trial.number一同存储。这样易于之后确认对应的 trial.比如,你可以用以下方式在目标函数中保存训练好的 SVM 模型:

def objective(trial):
svc_c = trial.suggest_float("svc_c", 1e-10, 1e10, log=True)
clf = sklearn.svm.SVC(C=svc_c)
clf.fit(X_train, y_train)

# Save a trained model to a file.
with open("{}.pickle".format(trial.number), "wb") as fout:
pickle.dump(clf, fout)
return 1.0 - accuracy_score(y_valid, clf.predict(X_valid))


study = optuna.create_study()
study.optimize(objective, n_trials=100)

# Load the best model.
with open("{}.pickle".format(study.best_trial.number), "rb") as fin:
best_clf = pickle.load(fin)
print(accuracy_score(y_valid, best_clf.predict(X_valid)))

在优化study时,如何避免内存不足(OOM)?

如果你运行更多trials时,导致内存增加,尝试定期运行垃圾收集器。 在回调中调用optimize()或调用``gc.collect()时,设置gc_after_trial=True`。

def objective(trial):
x = trial.suggest_float("x", -1.0, 1.0)
y = trial.suggest_int("y", -5, 5)
return x + y


study = optuna.create_study()
study.optimize(objective, n_trials=10, gc_after_trial=True)

# `gc_after_trial=True` is more or less identical to the following.
study.optimize(objective, n_trials=10, callbacks=[lambda study, trial: gc.collect()])

如何保存和恢复 study?

有两种方法可以将 study 持久化。具体采用哪种取决于你是使用内存存储 (in-memory) 还是远程数据库存储 (RDB). 通过 pickle 或者 joblib, 采用了内存存储的 study 可以和普通的 Python 对象一样被存储和加载。比如用 joblib 的话:

study = optuna.create_study()
joblib.dump(study, "study.pkl")

恢复 study:

study = joblib.load("study.pkl")
print("Best trial until now:")
print(" Value: ", study.best_trial.value)
print(" Params: ")
for key, value in study.best_trial.params.items():
print(f" {key}: {value}")

Ray[tune]

Ray Tune 是一个标准的超参数调优工具,集成了多种参数搜索算法,并且支持分布式计算,使用方式简单。同时支持pytorch、tensorflow等训练框架,和tensorboard可视化。

官方文档:Welcome to Ray!

首先需要安装 Ray 的 Tune 模块,可以使用以下命令:

pip install "ray[tune]"

Ray Tune 优化过程主要分为4步:

Step 1 定义参数空间
Step 2 定义目标函数
Step 3 执行优化
Step 4 评估输出

Step 1 定义参数空间

我们使用字典来定义超参数空间

ray.tune 说明
tune.choice(categories) 分类数据采样
tune.randint(lower, upper) 在区间 lower, upper 均匀采样整数
tune.qrandint(lower, upper, q) 在区间 lower, upper 离散均匀采样整数
tune.lograndint(lower, upper, base=10) 在区间 10lower,10upper 对数均匀采样整数
tune.qlograndint(lower, upper, q,  base=10) 在区间 10lower,10upper 对数离散均匀采样整数
tune.uniform(lower, upper) 在区间 lower, upper 均匀采样浮点数
tune.quniform(lower, upper, q) 在区间 lower, upper离散均匀采样浮点数
tune.loguniform(lower, upper, base=10) 在区间 10lower,10upper 对数均匀采样浮点数
tune.qloguniform(lower, upper, q, base=10) 在区间 10lower,10upper 对数离散均匀采样浮点数
tune.randn(mean, std) 正态分布采样浮点数
tune.qrandn(mean, std, q) 正态分布离散采样浮点数
tune.grid_search(values) 指定网格搜索
tune.sample_from(func) 配置采样函数
# define a search space
from ray import tune, train
space = {
'random_state': 42,
'max_depth': tune.randint(2, 10),
'learning_rate': tune.loguniform(0.001, 1.0),
'n_estimators': tune.qrandint(20, 200, 20),
'subsample': tune.quniform(0.1, 1.0, 0.1),
'max_features': tune.choice(['sqrt', 'log2'])
}

Step 2 定义目标函数

该函数模型训练函数(trainable)接受超参数字典,在整个训练过程结束后 return {"score": score}

# define an objective function
from sklearn.ensemble import GradientBoostingRegressor
from sklearn.model_selection import cross_val_score

def trainable(params):
reg = GradientBoostingRegressor(**params)
mse = cross_val_score(reg, X_train, y_train, scoring='neg_mean_squared_error', cv=5).mean()
return return {"score": -mse}

或在训练过程中的每个epoch后进行报告 train.report({"score": score}),便于在训练过程中监控指标的变化趋势。

def objective(x, a, b):  # Define an objective function.
return a * (x**0.5) + b

def trainable(config): # Pass a "config" dictionary into your trainable.
for x in range(20): # "Train" for 20 iterations and compute intermediate scores.
score = objective(x, config["a"], config["b"])
train.report({"score": score}) # Send the score to Tune.

Step 3 执行优化

使用 Tuner 创建用于调参的优化器(turner),其输入参数包括:

  • trainable:模型训练函数

  • parame_space:超参数搜索空间

  • tune_config:以tune.TuneConfig实例作为输入,配置优化算法、度量指标等。

  • run_config:以 tune.RunConfig 实例作为输入,配置训练终止条件,check point,运行结果存储路径等

然后调用方法 .fit 启动优化。默认情况下,Tune 会自动使用全部资源并行运行。

from ray.tune.search.hyperopt import HyperOptSearch 

# Initialize
tuner = tune.Tuner(
objective, # Objective Function to optimize
param_space=search_space, # Hyperparameter's Search Space
tune_config=tune.TuneConfig(
metric="score",
mode="min", # minimize the objective over the space
search_alg=HyperOptSearch(), # Optimization algorithm
num_samples=100, # Number of optimization attempts
time_budget_s=3600
),
run_config=tune.RunConfig(
storage_path="~/ray_results",
verbose=1,
stop=None
)
)
results = tuner.fit()

tune 具有与许多流行的优化库集成的搜索算法,如果未指定搜索算法,将默认使用随机搜索。

SearchAlgorithm Summary Website Code Example
Random search/grid search Random search/grid search tune_basic_example
AxSearch Bayesian/Bandit Optimization [Ax] AX Example
HyperOptSearch Tree-Parzen Estimators [HyperOpt] Running Tune experiments with HyperOpt
BayesOptSearch Bayesian Optimization [BayesianOptimization] BayesOpt Example
TuneBOHB Bayesian Opt/HyperBand [BOHB] BOHB Example
NevergradSearch Gradient-free Optimization [Nevergrad] Nevergrad Example
OptunaSearch Optuna search algorithms [Optuna] Running Tune experiments with Optuna

Step 4 评估输出

Tuner.fit()返回一个ResultGrid对象

best_result = results.get_best_result()  # Get best result object
best_config = best_result.config # Get best trial's hyperparameters
best_logdir = best_result.path # Get best trial's result directory
best_checkpoint = best_result.checkpoint # Get best trial's best checkpoint
best_metrics = best_result.metrics # Get best trial's last results
best_result_df = best_result.metrics_dataframe # Get best result as pandas dataframe

此对象还可以转化为 DataFrame, 进行临时数据分析。

# Get a dataframe with the last results for each trial
df_results = results.get_dataframe()

# Get a dataframe of results for a specific score or mode
df = results.get_dataframe(filter_metric="score", filter_mode="max")