Вопрос или проблема
В настоящее время я пытаюсь построить модель с использованием CatBoost. Для настройки параметров я использую optuna и кросс-валидацию, а также подрезаю испытания, проверяя промежуточные оценки кросс-валидации. Вот минимальный пример:
def objective(trial):
param = {
"iterations": trial.suggest_int("iterations", 50, 5000),
"boosting_type": trial.suggest_categorical(
"boosting_type", ["Ordered", "Plain"]
),
"model_shrink_mode": trial.suggest_categorical(
"model_shrink_mode", ["Constant", "Decreasing"]
),
}
scores = []
skf = StratifiedKFold(n_splits=nfolds)
for k_step, (train_index, test_index) in enumerate(skf.split(X, y)):
X_Ktrain, y_Ktrain = X.iloc[train_index], y.iloc[train_index]
X_Kval, y_Kval = X.iloc[test_index], y.iloc[test_index]
clf = CatBoostClassifier(**param, cat_features=X_Ktrain.select_dtype(exclude="number").columns)
clf.fit(x_Ktrain, y_Ktrain)
score = clf.score(X_Kval, y_Kval)
scores.append(score)
trial.report(score, step)
# Обработка подрезки на основе промежуточного значения.
if trial.should_prune():
raise optuna.TrialPruned()
return sum(scores) / len(scores)
Мой вопрос возникает из-за того, что подрезка optuna предназначена для работы с алгоритмами, которые могут обучаться непрерывно, поэтому я не уверен, что такой способ использования имеет смысл.
Попытка реализовать механизм кросс-валидации с Optuna на самом деле немного болезненна, так как Optuna не поддерживает интеграцию кросс-валидации с подрезкой. Если попытаться использовать ваш минимальный пример, это приведет к предупреждению, подобному этому:
UserWarning: The reported value is ignored because this `step` 21 is already reported
Причина этого заключается в том, что при выполнении разбиения кросс-валидации с N эпохами шаг может быть встречен максимум $k$ раз. Например, номер шага $1$ может быть:
trial.report(score, step)
сообщен до $3$ раз. Это вызывает конфликты во внутреннем оптимизаторе Optuna, который видит один и тот же шаг дважды. Чтобы избежать этого, можно рассмотреть возможность подрезки только во время первого разбиения кросс-валидации, что-то подобное:
if split_idx == 0:
trial.report(avg_val_loss, (split_idx * N_EPOCHS) + epoch + 1)
if trial.should_prune():
raise optuna.TrialPruned()
Позволять подрезчику работать на нескольких разбиениях также проблематично, так как после завершения первого разбиения и перед началом второго разбиения может происходить значительный скачок в проверочных потерях из-за нового разбиения, однако optuna может принять этот скачок за переобучение и неправильно остановить процесс обучения.
Более того, это решение проверять подрезку исключительно во время первого разбиения является довольно разумным, поскольку если определенная конфигурация гиперпараметров полностью портит обучение и проверку в первом разбиении, скорее всего, последующие разбиения также столкнутся с подобным поведением, так как разбиения, как правило, довольно тесно связаны друг с другом и представляют собой друг друга.
Некоторую дополнительную информацию об этом можно найти здесь и здесь.
Ответ или решение
Оптимизация гиперпараметров модели с использованием Optuna в контексте кросс-валидации и обрезки (pruning) представляет собой сложную задачу, требующую тщательного подхода. В данной статье мы разберем, имеет ли смысл применение обрезки при кросс-валидации, а также предложим некоторые рекомендации по эффективному использованию Optuna в данной ситуации.
Что такое оpтимизация гиперпараметров?
Оптимизация гиперпараметров – это процесс поиска наилучших параметров модели, которые обеспечивают максимальную производительность. В случае применения Optuna, мы можем использовать его функционал для быстрого нахождения оптимальных значений, что значительно ускоряет процесс настройки модели.
Зачем использовать обрезку в Optuna?
Обрезка – это механизм, благодаря которому Optuna может прерывать обучение неэффективных экспериментальных проб (trials), что позволяет сэкономить время и ресурсы. Однако важным аспектом является то, что обрезка лучше всего работает с алгоритмами, которые способны учиться непрерывно на протяжении обучения, например, в случае сетей.
Проблема применения обрезки в кросс-валидации
Основная проблема, с которой столкнулись авторы, заключается в том, что обрезка Optuna не совсем подходит для сценариев с кросс-валидацией. Optuna не обеспечивает специальной поддержки для кросс-валидации с обрезкой, что может приводить к предупреждениям, таким как:
UserWarning: The reported value is ignored because this `step` xx is already reported
Это происходит потому, что каждый этап (step) может быть вызван несколько раз для одного и того же пробного эксперимента. Например, когда вы разбиение на K фолдов, один и тот же шаг может быть зарегистрирован K раз, что создает конфликт в внутреннем оптимизаторе Optuna.
Решение через запись промежуточных результатов
Вместо многократного вызова trial.report(score, step)
для каждого фолда, разумнее рассмотреть возможность записи результатов только для первого фолда. Это позволяет избежать конфликта и сохранить точность процесса. Например:
if split_idx == 0:
trial.report(avg_val_loss, (split_idx * N_EPOCHS) + epoch + 1)
if trial.should_prune():
raise optuna.TrialPruned()
Такой подход позволяет эффективно использовать обрезку и направляет Optuna на правильный путь в принятии решений о прекращении проб.
Возможность ошибок в интерпретации
Также стоит отметить, что использование обрезки во всех фолдах может привести к ложным срабатываниям, когда резкие колебания значения метрики валидности могут быть восприняты как переобучение, хотя на самом деле это может быть просто следствием новой разбиения.
Заключение
Таким образом, объединение Optuna и кросс-валидации требует осторожности и понимания ограничений каждого инструмента. Использование обрезки во время кросс-валидации может иметь смысл, если правильно реализовать процесс анализа промежуточных значений. Оптимальный подход заключается в учете только первого этапа для отчетности по метрикам производительности, избегая множественных регистрации одних и тех же значений, что минимизирует риск ошибок при использовании обрезки.
Полезные ссылки
Следуя вышеизложенным рекомендациям, вы сможете улучшить свой процесс оптимизации гиперпараметров и повысить эффективность обучения ваших моделей.