Optuna предлагает одинаковые значения параметров во многих испытаниях (повторяющиеся испытания, которые тратят время и бюджет)

Optuna TPESampler и RandomSampler по какой-то причине пробуют одни и те же предлагаемые целочисленные значения (также возможные числа с плавающей запятой и логарифмические формы) для любого параметра более одного раза. Я не мог найти способа, чтобы он не предлагал одни и те же значения снова и снова. Из 100 исследований довольно много всего лишь дубликатов. Количество уникальных предлагаемых значений составляет около 80–90 из 100 испытаний. Если я добавлю больше параметров для настройки, скажем 3, я даже увижу, что все 3 из них получают одинаковые значения несколько раз за 100 испытаний.

Это вот так. 75 для min_data_in_leaf использовалось 3 раза:

[I 2020-11-14 14: 44: 05,320] Пробная версия 8 завершена со значением: 45910.54012028659 и параметрами: {'min_data_in_leaf': 75}. Лучшее - проба 4 со значением: 45805.19030897498.

[I 2020-11-14 14: 44: 07,876] Пробная версия 9 завершена со значением: 45910.54012028659 и параметрами: {'min_data_in_leaf': 75}. Лучшее - проба 4 со значением: 45805.19030897498.

[I 2020-11-14 14: 44: 10,447] Пробная версия 10 завершена со значением: 45831.75933279074 и параметрами: {'min_data_in_leaf': 43}. Лучшее - проба 4 со значением: 45805.19030897498.

[I 2020-11-14 14: 44: 13,502] Испытание 11 завершено со значением: 46125.39810101329 и параметрами: {'min_data_in_leaf': 4}. Лучшее - это проба 4 со значением: 45805.19030897498.

[I 2020-11-14 14: 44: 16,547] Пробная версия 12 завершена со значением: 45910.54012028659 и параметрами: {'min_data_in_leaf': 75}. Лучшее - это проба 4 со значением: 45805.19030897498.

Пример кода ниже:

def lgb_optuna(trial):

    rmse = []

    params = {
        "seed": 42,
        "objective": "regression",
        "metric": "rmse",
        "verbosity": -1,
        "boosting": "gbdt",
        "num_iterations":  1000,
        'min_data_in_leaf':  trial.suggest_int('min_data_in_leaf', 1, 100)
    }

    cv = StratifiedKFold(n_splits=5, random_state=42, shuffle=False)
    for train_index, test_index in cv.split(tfd_train, tfd_train[:,-1]):
        X_train, X_test = tfd_train[train_index], tfd_train[test_index]
        y_train = X_train[:,-2].copy()
        y_test = X_test[:,-2].copy()
        
        dtrain = lgb.Dataset(X_train[:,:-2], label=y_train)
        dtest = lgb.Dataset(X_test[:,:-2], label=y_test)
    
        booster_gbm = lgb.train(params, dtrain, valid_sets=dtest, verbose_eval=False)

        y_predictions = booster_gbm.predict(X_test[:,:-2])
        final_mse = mean_squared_error(y_test, y_predictions)
        final_rmse = np.sqrt(final_mse)
        rmse.append(final_rmse)

     return np.mean(rmse)

study = optuna.create_study(sampler=TPESampler(seed=42), direction='minimize') 
study.optimize(lgb_optuna, n_trials=100) 

person Lord Permaximum    schedule 14.11.2020    source источник


Ответы (2)


Проблема в вашем семплере, указанном в этой строке:

study = optuna.create_study(sampler=TPESampler(seed=42), direction='minimize')

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

Чтобы получить действительно однородную выборку, вы должны изменить свой сэмплер на:

sampler=RandomSampler(seed)

Это не гарантирует, что дубликатов не будет, но значения будут распределены более равномерно.

Если вы хотите, чтобы вы искали только разные комбинации, вы должны использовать GridSampler. Как указано в документе:

испытания предлагают все комбинации параметров в заданном пространстве поиска во время исследования.

см. здесь

person Nikaido    schedule 14.11.2020
comment
Как я описал в начале OP, RandomSampler также имеет примерно такое же количество дубликатов. Я хочу использовать TPESampler, поскольку он предположительно находит оптимальные гиперпараметры быстрее по сравнению со случайным поиском или поиском по сетке при том же бюджете / времени. Какие-либо обходные пути, чтобы запретить ему использовать ранее использованные значения параметров (например, сначала поиск значения параметра в истории испытаний) или просто как работают TPESampler и RandomSampler? - person Lord Permaximum; 14.11.2020
comment
@LordPermaximum в любом случае случайный сэмплер сильно отличается от TPESampler. Как я вижу по результатам эксперимента, значения распределены более-менее равномерно. - person Nikaido; 14.11.2020
comment
Я знаю, что GridSampler работает, но это отнимает много времени. Вот почему я в первую очередь хотел использовать TPESampler. Должен быть способ использовать tpe или другую байесовскую оптимизацию без дублирования предыдущих испытаний. Звучит так просто, но я не хочу связываться с базовыми классами модуля optuna. Кроме того, я не думаю, что здесь проблема с выборкой TPE. Я подозреваю, что TPESampler использует случайную выборку для нескольких испытаний стартапа. Скажите 40 или что-то в этом роде. Затем он переключается на выборку tpe. - person Lord Permaximum; 14.11.2020
comment
@LordPermaximum, как я сказал в обновленном ответе, если вы хотите исследовать только неиспользуемые комбинации без дубликатов, GridSampler - это то, что вам нужно. - person Nikaido; 14.11.2020

У меня есть моя целевая функция check study.trials_dataframe (), если эти параметры были запущены раньше, а затем просто вернуть study.trials_dataframe (). Value, если они есть.

person Mike Breytenbach    schedule 12.04.2021