【问题标题】:Multiple trainings / multiple NN initialisations per Hyperparamter validation with Optuna and pruning使用 Optuna 和修剪的每个超参数验证的多次训练/多次 NN 初始化
【发布时间】:2022-01-24 14:55:05
【问题描述】:

我正在做我的第一个 ML-with-optuna 项目。 我的问题是如何探测一组超参数以进行多个 NN 初始化,在一次试验中的每次运行仍然需要修剪?

我假设初始化有相当大的影响,我不想因为运气不好而将好的HP击出。

据我所知,每个试验代表一组 HP。因此,如果我想对它们进行多次初始化评估,我会在每次试验中执行多次训练。但在一次试验中,我只能为每个时间戳报告一个值。

我必须在没有 optuna 的情况下实现这个吗?我是否应该采用一种方法,让 optuna 首先建议一组 HP,然后为下一次试验修复它?或者您知道一些使用 optuna 实现此目的的好方法吗?

非常感谢!

编辑 1;添加一个最小的代码示例:

from random import randrange
import optuna


def objective(trial):
    """
    return x * 20 + random_offset
    multiplication calculated iteratively to enable pruning
    """

    x = trial.suggest_float("x", 0, 10)

    random_offset = randrange(0, 1000)
    temp = 1
    res_temp = None
    for i in range(20):
        temp += x
        res_temp = temp + random_offset
        trial.report(res_temp, i)

        if trial.should_prune():
            raise optuna.TrialPruned()

    return res_temp


if __name__ == '__main__':
    study = optuna.create_study(pruner=optuna.pruners.MedianPruner())

    study.optimize(objective, n_trials=20)

    print("best params:", study.best_params)
    print("best value:", study.best_value)

此示例尝试在 0 到 10 的范围内找到“x”,从而最小化“x * 20”。显而易见的答案是 0。目标函数是基于迭代求和计算结果;它使用修剪。遗憾的是,由于随机偏移,目标函数是嘈杂的。这是作为训练 NN 的隐喻。迭代是训练循环,x是超参数,偏移量是网络的随机初始化。

由噪声引起的问题是您无法确定超参数的质量,因为结果可能由随机偏移量决定。这可能会导致选择次优的 x。 如果我是对的,那么增加试验次数以消除随机性可能不起作用,因为 optuna 可能会建议基于旧超参数的新超参数。所以不幸的观察会阻碍进一步的进展。

因此,我认为最好对同一组 hyperpramters 多次评估目标,并且只记住最好的“运行”。

所以我的问题是如何最好地消除噪音?我的假设是否正确,即仅增加试验次数不是最好的方法,您将如何实施重复评估?

【问题讨论】:

  • 你能提供一个最小的可重现代码吗?
  • @ferdy 我添加了一个示例和一些解释。这是否有助于您理解问题?

标签: deep-learning hyperparameters optuna


【解决方案1】:

由于您的目标现在也取决于随机性,因此最好按照您的假设多次评估目标。

但最好尝试确定随机性来自何处,是来自种子数吗?如果没有,那么你真的需要更多的试验和对完整时代的更多评估。

optuna example 中看起来像这样。每个 epoch 或 step,模型都会针对相同的参数评估 n_train_iter 次。

import numpy as np
from sklearn.datasets import load_iris
from sklearn.linear_model import SGDClassifier
from sklearn.model_selection import train_test_split

import optuna

X, y = load_iris(return_X_y=True)
X_train, X_valid, y_train, y_valid = train_test_split(X, y)
classes = np.unique(y)


def objective(trial):
    alpha = trial.suggest_float("alpha", 0.0, 1.0)
    clf = SGDClassifier(alpha=alpha)
    n_train_iter = 100

    for step in range(n_train_iter):
        clf.partial_fit(X_train, y_train, classes=classes)

        intermediate_value = clf.score(X_valid, y_valid)
        trial.report(intermediate_value, step)

        if trial.should_prune():
            raise optuna.TrialPruned()

    return clf.score(X_valid, y_valid)


study = optuna.create_study(
    direction="maximize",
    pruner=optuna.pruners.MedianPruner(
        n_startup_trials=5, n_warmup_steps=30, interval_steps=10
    ),
)
study.optimize(objective, n_trials=20)

你可以通过调用更进一步

X_train, X_valid, y_train, y_valid = train_test_split(X, y)

多次寻找最佳客观价值。

【讨论】:

  • 第一:非常感谢您的帮助:) 第二段:随机性来自种子数。在 PC 上不是几乎总是这样吗?固定种子数似乎不太像正确的方法,更像是作弊,更像是记住一次幸运的试验。如果你这样做,你可以随机选择所有 HP,而不是只记住最好的种子,不是吗?我同意通过识别随机性来源使训练尽可能稳健是值得的。第 3 段。似乎该语句不符合代码。每个步骤(循环体)只评估一次。我错过了什么吗?
猜你喜欢
  • 1970-01-01
  • 2018-12-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-05
  • 2017-01-13
  • 2019-04-14
  • 2019-10-04
相关资源
最近更新 更多