注意
转至末尾 下载完整的示例代码。
轻量级、多功能且平台无关的架构
Optuna 完全用 Python 编写,并且依赖项很少。这意味着一旦您对 Optuna 感兴趣,我们就可以快速进入实际示例。
二次函数示例
通常,Optuna 用于优化超参数,但作为示例,让我们优化一个简单的二次函数:\((x - 2)^2\)。
首先,导入 optuna。
import optuna
在 Optuna 中,传统上要优化的函数名为 objective。
def objective(trial):
x = trial.suggest_float("x", -10, 10)
return (x - 2) ** 2
此函数返回 \((x - 2)^2\) 的值。我们的目标是找到使 objective 函数输出最小化的 x 值。这就是“优化”。在优化过程中,Optuna 会使用不同的 x 值反复调用和评估目标函数。
一个 Trial 对象对应于目标函数的一次单独执行,并在每次调用函数时在内部实例化。
“suggest”API(例如,suggest_float())在目标函数内部调用,以获取 trial 的参数。suggest_float() 在提供的范围内均匀选择参数。在我们的示例中,范围是从 \(-10\) 到 \(10\)。
为了开始优化,我们创建一个 study 对象,并将目标函数传递给方法 optimize(),如下所示。
study = optuna.create_study()
study.optimize(objective, n_trials=100)
您可以按如下方式获取最佳参数。
best_params = study.best_params
found_x = best_params["x"]
print(f"Found x: {found_x}, (x - 2)^2: {(found_x - 2) ** 2}")
Found x: 2.006698664607871, (x - 2)^2: 4.4872107528744237e-05
我们可以看到 Optuna 找到的 x 值接近最优值 2。
注意
当用于在机器学习中搜索超参数时,目标函数通常会返回模型的损失或准确率。
Study 对象
让我们根据如下内容澄清 Optuna 中的术语
Trial:目标函数的一次调用
Study:一次优化会话,即一组 trial
Parameter:一个需要优化其值的变量,例如上面示例中的
x
在 Optuna 中,我们使用 study 对象来管理优化。方法 create_study() 返回一个 study 对象。study 对象具有用于分析优化结果的有用属性。
获取参数名称和参数值字典
study.best_params
{'x': 2.006698664607871}
获取目标函数的最佳观测值
study.best_value
4.4872107528744237e-05
获取最佳 trial
study.best_trial
FrozenTrial(number=52, state=<TrialState.COMPLETE: 1>, values=[4.4872107528744237e-05], datetime_start=datetime.datetime(2025, 11, 10, 5, 17, 48, 529409), datetime_complete=datetime.datetime(2025, 11, 10, 5, 17, 48, 530558), params={'x': 2.006698664607871}, user_attrs={}, system_attrs={}, intermediate_values={}, distributions={'x': FloatDistribution(high=10.0, log=False, low=-10.0, step=None)}, trial_id=52, value=None)
获取所有 trial
study.trials
for trial in study.trials[:2]: # Show first two trials
print(trial)
FrozenTrial(number=0, state=<TrialState.COMPLETE: 1>, values=[10.88077703675539], datetime_start=datetime.datetime(2025, 11, 10, 5, 17, 48, 475905), datetime_complete=datetime.datetime(2025, 11, 10, 5, 17, 48, 476506), params={'x': -1.298602285325618}, user_attrs={}, system_attrs={}, intermediate_values={}, distributions={'x': FloatDistribution(high=10.0, log=False, low=-10.0, step=None)}, trial_id=0, value=None)
FrozenTrial(number=1, state=<TrialState.COMPLETE: 1>, values=[43.633281258046665], datetime_start=datetime.datetime(2025, 11, 10, 5, 17, 48, 476659), datetime_complete=datetime.datetime(2025, 11, 10, 5, 17, 48, 476807), params={'x': -4.605549277542835}, user_attrs={}, system_attrs={}, intermediate_values={}, distributions={'x': FloatDistribution(high=10.0, log=False, low=-10.0, step=None)}, trial_id=1, value=None)
获取 trial 的数量
len(study.trials)
100
通过再次执行 optimize(),我们可以继续优化。
study.optimize(objective, n_trials=100)
获取更新后的 trial 数量
len(study.trials)
200
由于目标函数非常简单,最后 100 个 trial 没有改进结果。但是,我们可以再次检查结果
best_params = study.best_params
found_x = best_params["x"]
print(f"Found x: {found_x}, (x - 2)^2: {(found_x - 2) ** 2}")
Found x: 2.005097031517559, (x - 2)^2: 2.597973029098893e-05
脚本总运行时间: (0 分钟 0.267 秒)