Как сделать выборку параметров без дубликатов в optuna?

Я использую optuna для оптимизации параметров моих пользовательских моделей.

Есть ли способ отбирать параметры до тех пор, пока текущий набор параметров не был протестирован раньше? Я имею в виду, попробуйте выбрать другие параметры, если в прошлом были некоторые испытания с тем же набором параметров.

В некоторых случаях это невозможно, например, при категориальном распределении и n_trials больше числа возможных уникальных значений выборки.

Что я хочу: иметь какой-то параметр конфигурации, например num_attempts для выборки параметров до num_attempts в цикле for до тех пор, пока не будет набора, который ранее не тестировался, иначе - для запуска пробной версии на последнем выбранном наборе.

Зачем мне это нужно: просто потому, что запускать тяжелые модели несколько раз с одними и теми же параметрами слишком дорого.

Что я делаю сейчас: просто делаю этот "цикл for", но это беспорядок.

Если есть еще один умный способ сделать это - буду очень признателен за информацию.

Спасибо!

2 ответа

Решение

Насколько мне известно, на данный момент нет прямого способа рассмотреть ваше дело. В качестве обходного пути вы можете проверить дублирование параметров и пропустить оценку следующим образом:

import optuna

def objective(trial: optuna.Trial):
    # Sample parameters.
    x = trial.suggest_int('x', 0, 10)
    y = trial.suggest_categorical('y', [-10, -5, 0, 5, 10])

    # Check duplication and skip if it's detected.
    for t in trial.study.trials:
        if t.state != optuna.structs.TrialState.COMPLETE:
            continue

        if t.params == trial.params:
            return t.value  # Return the previous value without re-evaluating it.

            # # Note that if duplicate parameter sets are suggested too frequently,
            # # you can use the pruning mechanism of Optuna to mitigate the problem.
            # # By raising `TrialPruned` instead of just returning the previous value,
            # # the sampler is more likely to avoid sampling the parameters in the succeeding trials.
            #
            # raise optuna.structs.TrialPruned('Duplicate parameter set')

    # Evaluate parameters.
    return x + y

# Start study.
study = optuna.create_study()

unique_trials = 20
while unique_trials > len(set(str(t.params) for t in study.trials)):
    study.optimize(objective, n_trials=1)

Чтобы добавить комментарий к коду @lea, вы можете написать секатор, например:

class RepeatPruner(BasePruner):
    def prune(self, study, trial):
        # type: (Study, FrozenTrial) -> bool

        trials = study.get_trials(deepcopy=False)
        completed_trials = [t.params for t in trials if t.state == TrialState.COMPLETE]
        n_trials = len(completed_trials)

        if n_trials == 0:
            return False

        if trial.params in completed_trials:
            return True

        return False

затем вызовите секатор как:

study = optuna.create_study(study_name=study_name, storage=storage, load_if_exists=True, pruner=RepeatPruner())
Другие вопросы по тегам