Как сделать выборку параметров без дубликатов в 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())