第一个优化例子¶
二次函数的例子¶
Optuna 通常用于优化超参数,但是为了举例说明,我们将直接在 IPython shell 中优化一个二次函数。
import optuna
目标 (objective) 函数便是待优化的函数。
def objective(trial):
x = trial.suggest_uniform('x', -10, 10)
return (x - 2) ** 2
该函数的返回值是 \((x - 2)^2\). 我们的目标是找到一个 x
,使 objective
函数的输出最小。这被称为 "optimization" (优化)。 在优化过程中,Optuna 反复调用目标函数,在不同的 x
下对其进行求值。
一个 Trial
对应着目标函数的单次执行。在每次调用该函数的时候,它都被内部实例化一次。
而 suggest API (例如 suggest_uniform()
) 在目标函数内部被调用。它被用于获取单个 trial 的参数。在上面的例子中,suggest_uniform()
在给定的范围(-10
到 10
)内均匀地选择参数。
为了开始优化过程,我们将创建一个 study 对象,并将目标函数传递给它的一个方法 optimize()
:
study = optuna.create_study()
study.optimize(objective, n_trials=100)
输出:
[I 2020-04-08 10:42:09,028] Trial 0 finished with value: 25.77382032395108 with parameters: {'x': 7.076792326257898}. Best is trial 0 with value: 25.77382032395108.
[I 2020-04-08 10:42:09,064] Trial 1 finished with value: 1.5189812248635903 with parameters: {'x': 0.7675304365366298}. Best is trial 1 with value: 1.5189812248635903.
[I 2020-04-08 10:42:09,106] Trial 2 finished with value: 34.4074691838153 with parameters: {'x': -3.865788027521562}. Best is trial 1 with value: 1.5189812248635903.
[I 2020-04-08 10:42:09,145] Trial 3 finished with value: 3.3601305753722657 with parameters: {'x': 3.8330658949891205}. Best is trial 1 with value: 1.5189812248635903.
[I 2020-04-08 10:42:09,185] Trial 4 finished with value: 61.16797535698886 with parameters: {'x': -5.820995803412048}. Best is trial 1 with value: 1.5189812248635903.
[I 2020-04-08 10:42:09,228] Trial 5 finished with value: 90.08665552769618 with parameters: {'x': -7.491399028999686}. Best is trial 1 with value: 1.5189812248635903.
[I 2020-04-08 10:42:09,274] Trial 6 finished with value: 25.254236332163032 with parameters: {'x': 7.025359323686519}. Best is trial 1 with value: 1.5189812248635903.
...
[I 2020-04-08 10:42:14,237] Trial 99 finished with value: 0.5227007740782738 with parameters: {'x': 2.7229804797352926}. Best is trial 67 with value: 2.916284393762304e-06.
最佳参数可以通过如下方式获得:
study.best_params
输出:
{'x': 2.001707713205946}
可以看到,Optuna 找到的最佳 x
的值是 2.001707713205946
. 这非常靠近实际的最优值 2
.
注解
当Optuna被用于机器学习中的超参数搜索时,目标函数通常是对应模型的损失 (loss) 或者准确度 (accuracy).
Study 对象¶
下面是几个常用术语:
Trial: 目标函数的单次调用
Study: 一次优化过程,包含一系列的 trials.
Parameter: 待优化的参数,比如上面例子中的
x
.
在 Optuna 中,我们用 study 对象来管理优化过程。 create_study()
方法会返回一个 study 对象。该对象包含若干有用的属性,可以用于分析优化结果。
获得最佳参数:
study.best_params
输出:
{'x': 2.001707713205946}
获得最佳目标函数值:
study.best_value
输出:
2.916284393762304e-06
获得最佳 trial:
study.best_trial
输出:
FrozenTrial(number=67, value=2.916284393762304e-06, datetime_start=datetime.datetime(2020, 4, 8, 10, 42, 12, 595884), datetime_complete=datetime.datetime(2020, 4, 8, 10, 42, 12, 639969), params={'x': 2.001707713205946}, distributions={'x': UniformDistribution(high=10, low=-10)}, user_attrs={}, system_attrs={}, intermediate_values={}, trial_id=67, state=TrialState.COMPLETE)
获得所有 trials:
study.trials
输出:
[FrozenTrial(number=0, value=25.77382032395108, datetime_start=datetime.datetime(2020, 4, 8, 10, 42, 8, 987277), datetime_complete=datetime.datetime(2020, 4, 8, 10, 42, 9, 27959), params={'x': 7.076792326257898}, distributions={'x': UniformDistribution(high=10, low=-10)}, user_attrs={}, system_attrs={}, intermediate_values={}, trial_id=0, state=TrialState.COMPLETE),
...
user_attrs={}, system_attrs={}, intermediate_values={}, trial_id=99, state=TrialState.COMPLETE)]
获得 trial 的数目:
len(study.trials)
输出:
100
(在优化结束后)通过再次执行 optimize()
,我们可以继续优化过程。
study.optimize(objective, n_trials=100)
获得更新(再次优化后)的 trial 数量:
len(study.trials)
输出:
200