正在加载中...

展开本页目录
算法教程BayesOptuna-Optuna、Bayes 统一接口

BayesOptuna-Optuna、Bayes 统一接口

No.139 · 在线教程

BayesOptuna-Optuna、Bayes 统一接口 的真实核心位于:

BayesOptuna-Optuna、Bayes 统一接口

1. 方法概述

BayesOptuna-Optuna、Bayes 统一接口 的真实核心位于:

  • core/automl_runner.py
  • core/optimizers.py
  • core/search_space.py

它不是单一优化算法,而是一个统一的超参数搜索接口,支持三种引擎:

  • random
  • bayes_gp
  • optuna

目标是针对给定模型和给定搜索空间,最大化交叉验证评分。

设搜索空间为

$$ \Theta=\Theta_1\times\Theta_2\times\cdots\times\Theta_p \tag{1} $$

其中每个 \(\Theta_j\) 对应一个 ParamSpec,可以是 floatintcategorical

2. 数据预处理与目标函数

2.1 任务与模型

AutoMLConfig 支持两类任务:

  • classification
  • regression

可选模型是硬编码的,而不是任意 sklearn 模型。真实可用集合为:

  1. 分类:
    • SVC
    • RandomForestClassifier
    • LogisticRegression
    • GradientBoostingClassifier
    • KNeighborsClassifier
  2. 回归:
    • SVR
    • RandomForestRegressor
    • Ridge
    • GradientBoostingRegressor
    • KNeighborsRegressor

2.2 预处理流水线

给定数据表 \(D\),目标列为 \(y\),其余列构成特征矩阵 \(X\):

$$ D=(X,y) \tag{2} $$

预处理器 _build_preprocessor() 把特征分成数值列和类别列,然后构造:

$$ \Phi(X)=\mathrm{ColumnTransformer}\big(\Phi_{\text{num}},\Phi_{\text{cat}}\big) \tag{3} $$

其中:

  • 数值列永远做 SimpleImputer(strategy="median")
  • standardize=True,数值列再接 StandardScaler()
  • one_hot=True 且存在类别列,则类别列做 most_frequent 填补加 OneHotEncoder(handle_unknown="ignore")

这里有一个非常重要的实现细节:当 one_hot=False 时,类别列不会保留原值,而是由于 ColumnTransformer(..., remainder="drop") 被直接丢弃。

2.3 交叉验证目标

每组参数 \(\theta\in\Theta\) 的目标值定义为交叉验证平均分:

$$ f(\theta)=\frac{1}{K}\sum_{k=1}^{K}\mathrm{Score}\big(\mathcal{M}_\theta,\mathcal{D}^{(k)}_{\text{train}},\mathcal{D}^{(k)}_{\text{valid}}\big) \tag{4} $$

其中:

  • 分类任务使用 StratifiedKFold
  • 回归任务使用 KFold

并通过 cross_val_score(..., scoring=scorer, n_jobs=-1) 计算。

若某次训练报错或平均分不是有限值,代码直接返回

$$ f(\theta)=-10^{18} \tag{5} $$

把该试验当成极差解处理。

3. 搜索空间编码

3.1 ParamSpec

search_space.pyParamSpec 描述每个超参数。为了让 GP 引擎工作,参数会被编码到 \([0,1]\) 区间:

$$ x_j=\mathrm{encode}(\theta_j)\in[0,1] \tag{6} $$

全部参数拼成向量

$$ x=[x_1,\dots,x_p]^\top \tag{7} $$

再可通过 decode() 映射回原始参数。

3.2 默认搜索空间是硬编码的

所谓“统一接口”并不是让用户自由输入任意搜索空间,而是根据 task_type + model_name 调用 default_search_space() 返回一套固定范围。例如:

  • SVC / SVRC, gamma, kernel, degree, coef0
  • RandomForest*n_estimators, max_depth, min_samples_split, min_samples_leaf, max_features
  • GradientBoosting*n_estimators, learning_rate, max_depth
  • KNeighbors*n_neighbors, weights
  • LogisticRegression:只搜 Cpenalty 实际固定为 l2
  • Ridge:只搜 alpha

所以这个模块更准确地说是“若干常见模型的默认搜索空间统一入口”。

4. 三种优化引擎

4.1 随机搜索

random_search() 每次独立从各参数分布采样一组候选:

$$ \theta^{(t)}\sim p(\Theta) \tag{8} $$

然后计算 \(f(\theta^{(t)})\),保留当前最优值。

4.2 GP 贝叶斯搜索

bayes_gp_search() 不是调用第三方贝叶斯优化库,而是自己实现了一套:

  • 参数编码到 \([0,1]^p\)
  • GaussianProcessRegressor(kernel=Matern(\nu=2.5))
  • 采样 1024 个随机候选点
  • 用 Expected Improvement 选下一个点

初始化阶段先做若干次随机试验:

$$ n_{\text{init}}=\min\!\big(10,\max(3,\lfloor n_{\text{trials}}/3\rfloor)\big) \tag{9} $$

在贝叶斯阶段,对候选点 \(x\) 计算 GP 的预测均值与标准差 \((\mu(x),\sigma(x))\),再计算 EI:

$$ \mathrm{EI}(x)=\big(\mu(x)-f^\star-\xi\big)\Phi(z)+\sigma(x)\phi(z), \quad z=\frac{\mu(x)-f^\star-\xi}{\sigma(x)} \tag{10} $$

其中:

  • \(f^\star\) 是当前最优分数;
  • \(\xi=0.01\);
  • \(\Phi,\phi\) 分别是标准正态分布的 CDF 和 PDF。

候选点选择为

$$ x_{t+1}=\arg\max_{x\in\mathcal{C}}\mathrm{EI}(x) \tag{11} $$

这里的候选集 \(\mathcal{C}\) 不是连续优化求解出来的,而是一次性随机生成的 1024 个点,所以它本质上是“GP + 随机候选 EI 筛选”。

如果 GP 拟合失败,代码会记一条 warning,并回退为随机搜索。

4.3 Optuna 搜索

optuna_search() 在环境安装了 optuna 时可用。它使用:

  • optuna.samplers.TPESampler(seed=..., multivariate=True)
  • study.optimize(direction="maximize")

因此这一路并不是 GP,而是 Optuna 的 TPE。

UI 里只有在 import optuna 成功时才会显示 optuna 选项;如果用户选了但环境中没有安装,界面会自动改回 bayes_gp

5. 模型构造与真实细节

5.1 模型参数清理

SVC / SVR 的核函数参数会按 kernel 自动裁剪:

  • kernel != "poly" 时删除 degree
  • kernel not in {"poly","sigmoid"} 时删除 coef0

这避免了无关参数被传入 estimator。

5.2 指标口径

分类任务支持:

  • accuracy
  • f1_macro
  • roc_auc

回归任务支持:

  • r2
  • neg_mean_squared_error
  • neg_mean_absolute_error

这里要特别注意:后两种回归误差指标是 sklearn 的负损失 scorer,所以导出的 best_score 可能是负数;数值越大,代表误差越小。

5.3 多分类 AUC 自动替换

若任务是多分类,但用户选择了 roc_auc,代码会自动改成:

$$ \mathrm{metric}_{\text{used}}=\texttt{roc\_auc\_ovr} \tag{12} $$

并把这条信息写进 warnings,同时在 parameters 中补充 metric_used

6. 输出结果与复现

6.1 Excel 工作表

save_results() 的真实导出工作表为:

  • Parameters
  • Best
  • Trials
  • Warnings
  • Charts

其中:

  • Warnings 只有在存在 warning 时才写出;
  • Best 会把 best_scorebest_params 展平到同一行;
  • Trials 会记录每次 trial 的 score 以及各参数列,列名前缀是 param_

6.2 图表

程序会自动生成两张图:

  • trials_score_curve.png
  • best_score_trajectory.png

前者画每次 trial 的得分,后者画累计最优分数曲线。

6.3 复现脚本

结果页会自动生成 repro_bayesoptuna.py。它会:

  • 复制原始数据到 repro_inputs/
  • 重新构造 AutoMLConfig
  • 再次调用 run_automl_search()
  • 输出一份新的 Excel 结果

因此复现脚本跑的仍然是当前这套统一接口实现。

7. 实现说明与注意事项

从真实代码出发,这个模块在论文说明里应写清以下边界:

  1. 它不是任意模型的 AutoML 框架,而是少数 sklearn 模型的默认搜索空间统一接口。
  2. bayes_gp 是自写的 GaussianProcessRegressor + Expected Improvement + 随机候选采样,不是现成贝叶斯优化库的黑箱封装。
  3. one_hot=False,类别特征会被直接丢弃,而不是做别的编码。
  4. 所有引擎的优化目标都是“交叉验证平均 scorer 最大化”,所以回归里的 neg_mean_squared_error/neg_mean_absolute_error 会表现成越大越好。
  5. 失败 trial 会被赋值为 -1e18,因此 Trials 表中极小值通常表示模型训练或评分过程失败,而不是一个正常但很差的参数组合。

8. 论文写作模板

8.1 方法描述模板

可在论文“方法部分”中写为:

“本文采用统一超参数搜索框架对候选机器学习模型进行自动化调参。首先,对原始数据执行预处理、特征编码与交叉验证划分;其次,在预定义搜索空间内,分别利用 Optuna、贝叶斯高斯过程搜索或随机搜索策略对模型参数组合进行迭代评估;随后,以交叉验证平均评分作为目标函数筛选最优参数,并记录各次 trial 的得分轨迹;最后,输出最优参数、最优得分、搜索历史及图表结果,用于分析不同搜索策略下的模型调参效果。”

8.2 结果解释模板

结果部分可写为:统一搜索框架在相同数据与模型设定下比较了多种超参数优化策略的搜索效率与最优性能。若某一方法在较少 trial 下获得更优 best_score_cv,则说明其搜索效率更高;若不同策略得到的最优参数组合接近,则说明模型对超参数扰动较为稳健。

8.3 表格标题模板

表题可写为:统一超参数搜索框架下不同优化策略的最优结果对比表。

8.4 图表题注模板

图注可写为:不同超参数搜索策略的 trial 得分变化曲线。

8.5 表格示例

建议列名:搜索方法、模型名称、最优参数、最优交叉验证分数、测试集指标、trial 数量、运行时间。

9. 论文写作建议

论文中建议把该模块写成“统一超参数搜索接口”,并在方法部分明确本次实验实际使用的是哪一种搜索引擎。结果部分建议并列给出:

  1. 最优参数表;
  2. 搜索过程 trial 历史表;
  3. 不同引擎的最优分数对比图或表。

如果论文比较不同搜索策略,务必在相同搜索空间和相同评价指标下进行,否则结论不具可比性。

10. 单篇终审补充

10.1 图题与表题对齐建议

当前 BayesOptuna 统一接口模块的真实工作簿包含:

  • Parameters
  • Best
  • Trials
  • Warnings(存在 warning 时写出)
  • Charts

其中 Best 适合正文展示最优参数和最优分数;Trials 适合做搜索轨迹分析;Warnings 则是论文里最容易被忽略、但对解释结果非常关键的辅助表。不要把 Warnings 省略掉后还声称“所有评分与编码逻辑均按用户选择原样执行”,因为当前实现会自动修正部分指标口径。

图文件保存在结果目录下的 plots/ 子目录,当前真实图名为:

  • trials_score_curve.png
  • best_score_trajectory.png

因此图题建议写成“各 trial 得分变化曲线”“累计最优分数轨迹图”。这两张图分别对应单轮分数和历史最优,不应合并成同一张图的单一描述。

10.2 终审说明

这篇文档最需要强调的工程事实,是它并不是单一 Optuna 封装,而是统一接口:可走 randombayes_gpoptuna 等不同引擎。真实搜索过程记录来自 core/optimizers.py 里的 OptimizationOutput.trials,所以论文里如果比较不同引擎,必须明确本次运行用的是哪一个 engine

另外,当前 repro 脚本已经采用 repro_inputs/... 相对路径,结果目录中可见如 repro_inputs/bayesoptuna_sample.xlsx 的输入副本引用。这篇可直接按新框架写可复现性。

10.3 全量强化补充

本篇终审补充绑定的真实算法目录为 具体的算法3/可解释与AutoML/BayesOptuna-Optuna、Bayes 统一接口,本次采用的代表性结果目录为 具体的算法3/可解释与AutoML/BayesOptuna-Optuna、Bayes 统一接口/results/BayesOptuna-Optuna、Bayes 统一接口分析结果_20260323_203955

该目录里同时存在两份时间相邻的工作簿:

  • BayesOptuna_results_20260323_203955.xlsx
  • BayesOptuna_results_20260323_204000.xlsx

两者实测工作表一致,均包含:

  • Parameters
  • Best
  • Trials
  • Charts

结合目录内的 repro_bayesoptuna.py 可知,脚本使用 INPUT_FILE = 'repro_inputs/bayesoptuna_sample.xlsx' 并把结果写入当前目录,因此这两份 xlsx 不应被简单写成“同一轮主结果重复保存”。更准确的口径是:...203955.xlsx 可视为该轮主结果,...204000.xlsx 是同目录脚本再运行后产出的近邻时间戳结果。

当前目录中的真实图文件为:

  • 具体的算法3/可解释与AutoML/BayesOptuna-Optuna、Bayes 统一接口/results/BayesOptuna-Optuna、Bayes 统一接口分析结果_20260323_203955/plots/trials_score_curve.png
  • 具体的算法3/可解释与AutoML/BayesOptuna-Optuna、Bayes 统一接口/results/BayesOptuna-Optuna、Bayes 统一接口分析结果_20260323_203955/plots/best_score_trajectory.png

因此图题仍应严格对应“trial 得分曲线”和“累计最优轨迹图”,不要泛化成单一“优化历史图”。

复现实物方面,该目录实际包含:

  • 具体的算法3/可解释与AutoML/BayesOptuna-Optuna、Bayes 统一接口/results/BayesOptuna-Optuna、Bayes 统一接口分析结果_20260323_203955/repro_bayesoptuna.py
  • 具体的算法3/可解释与AutoML/BayesOptuna-Optuna、Bayes 统一接口/results/BayesOptuna-Optuna、Bayes 统一接口分析结果_20260323_203955/repro_inputs/bayesoptuna_sample.xlsx

脚本中已经固定为相对路径输入副本,因此这一篇可按“结果目录自带输入副本 + repro 入口脚本 + 再生产物”这一真实结构来写。

10. 软件实现核查补充(2026-07)

  • 当前主结果目录应写作 具体的算法3/可解释与AutoML/BayesOptuna-Optuna、Bayes 统一接口/results/BayesOptuna-Optuna、Bayes 统一接口分析结果_20260323_203955
  • 正文应围绕 RawDataProcessedDataPredictionsBestParamsMetricsTrialsCharts 来写。
  • 图证应对应 trials_score_curve.pngbest_score_trajectory.png,并把主结果和 repro 再生产物分开说明。
  • 复现脚本应按 repro_bayesoptuna.py + repro_inputs/bayesoptuna_sample.xlsx 的口径说明。