Устали от ручной настройки, случайных снимков в темноте или исчерпывающего поиска по сетке? Байесовская оптимизация открывает двери для более разумного и автоматизированного подхода.

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

В этой статье мы кратко обсудим HPO, а затем перейдем к коду.

TL;DR

Найдите блокнот на моем GitHub здесь.

Общие методы оптимизации гиперпараметров

Существует множество способов настройки гиперпараметров:

  • Ручная настройка: ручная настройка гиперпараметров для поиска наилучшего значения.
  • GridSearch: попробуйте все возможные комбинации в пространстве гиперпараметров.
  • Случайный поиск: поиск по сетке может потребовать значительных вычислительных ресурсов. Случайный поиск выбирает гиперпараметры из пространства случайным образом.
  • И т. д.

Однако эти методы имеют свои недостатки. Хотя ручная настройка проста и быстра, она часто приводит к неоптимальным комбинациям. GridSearch, хотя и с большей вероятностью найдет лучшее решение, может потребовать больших вычислительных ресурсов. С другой стороны, случайный поиск быстрее, чем GridSearch, но все же может привести к неоптимальным комбинациям гиперпараметров.

У Элиз Ли есть статья о случайном поиске и поиске по сетке, которую вы можете найти здесь.

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

Байесовская оптимизация с Optuna

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

Optuna использует байесовскую оптимизацию с алгоритмом, называемым TPE (оценщик Парцена с древовидной структурой).

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

Теперь пришло время запачкать руки кодом :).

Предпосылки

Установите Optuna и импортируйте библиотеки.

!pip install --quiet optuna
import optuna

from sklearn.datasets import load_iris
from sklearn.ensemble import RandomForestClassifier
from sklearn.svm import SVC
from sklearn.model_selection import cross_val_score

Загрузите набор данных радужной оболочки

Набор данных iris — известный набор данных, который содержит информацию о трех разных видах растений.

dataset = load_iris() 
features = dataset.data
target = dataset.target

print(f'features shape: {features.shape}')
print(f'target shape: {target.shape}')
print(f'features: {dataset.feature_names}')
print(f'target: {dataset.target_names}')
features shape: (150, 4)
target shape: (150,)
features: ['sepal length (cm)', 'sepal width (cm)', 'petal length (cm)', 'petal width (cm)']
features: ['setosa' 'versicolor' 'virginica']

Обучение модели случайного леса

Прежде чем оптимизировать наши модели, давайте обучим простую модель случайного леса, которая будет служить базовой метрикой.

def objective():
    """
    Define the model, then train and evaluate it using
    3-fold cross-validation.
    """
    # Define the model
    clf = RandomForestClassifier(n_estimators=5, max_depth=3)
    
     # Train and evaluate
    return cross_val_score(clf, features, target, n_jobs=-1, cv=3).mean()

print('Accuracy: {}'.format(objective()))
Accuracy: 0.96

Мы достигли точности 96%. Наша цель победить это.

Оптимизация гиперпараметров

Чтобы оптимизировать наши гиперпараметры, мы выполним два шага:

  1. Определите целевую функцию.
  2. Оптимизируйте эту функцию с лучшими гиперпараметрами.

1. Определение целевой функции

Целевая функция — это функция, которую мы стремимся оптимизировать. В нашем случае целевая функция вычисляет среднюю точность модели после перекрестной проверки, и наша цель — максимизировать это значение.

Нам просто нужно изменить функцию, чтобы она принимала пробный объект в качестве параметра, чтобы включить оптимизацию гиперпараметров.

def objective(trial):
    """
    Define a search space for the hyperparameters `n_estimators` and `max_depth`
    of a random forest model, then train and evaluate it using cross validation.
    """
  
    n_estimators = trial.suggest_int('n_estimators', 2, 20)
    max_depth = int(trial.suggest_float('max_depth', 1, 32, log=True))
    
    clf = RandomForestClassifier(n_estimators=n_estimators, max_depth=max_depth)
    
    return cross_val_score(clf, features, target, n_jobs=-1, cv=3).mean()

Методы suggest_XX () в Optuna используются для динамического предложения значений в указанном диапазоне. Это позволяет Optuna рекомендовать лучшие значения, используя свои алгоритмы оптимизации.

Например, suggest_int('n_estimators', 2, 20) предложит значения в интервале от 2 до 20 для количества оценщиков в процессе оптимизации. Эти предложения основаны на наблюдаемой эффективности предыдущих испытаний.

suggest_float и suggest_categorical — аналогичные методы.

2. Оптимизация целевой функции

Чтобы оптимизировать целевую функцию, нам просто нужно создать исследование N испытаний.

Осторожно, терминология!!

Исследование – это процесс оптимизации целевой функции. Он направлен на поиск наилучшей конфигурации.

Проба – это однократное выполнение целевой функции. В нашем случае обучение и оценка модели с использованием выбранных гиперпараметров.

# create a study
study = optuna.create_study(direction='maximize')
study.optimize(objective, n_trials=100)

# get the best trial
trial = study.best_trial
print('Accuracy: {}'.format(trial.value))
print("Best hyperparameters: {}".format(trial.params))
Accuracy: 0.9733333333333333
Best hyperparameters: {'n_estimators': 15, 'max_depth': 8.329333794531737}

Лучший результат, полученный после выполнения целевой функции в течение 100 испытаний, сохраняется в study.best_trial.

Мы заметили улучшение на 2% по сравнению с базовой моделью.

Выбор модели и оптимизация гиперпараметров

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

Например, следующий код демонстрирует, как найти наилучшую конфигурацию (модель + гиперпараметр) для двух разных моделей:

def objective(trial):
    """
    Define two models `RandomForest`, `LogisticRegression` and a search space for their hyperparameters.
    The function will evaluate one model or another depending on the evolution towards the objective.
    The optimized model with the highest accuracy will be the best.
    """
        
    classifier = trial.suggest_categorical('classifier', ['RandomForest', 'LogisticRegression'])
    
    if classifier == 'RandomForest':
        n_estimators = trial.suggest_int('n_estimators', 2, 20)
        max_depth = int(trial.suggest_float('max_depth', 1, 32, log=True))

        clf = RandomForestClassifier(n_estimators=n_estimators, max_depth=max_depth)
    else:
        c = trial.suggest_float('svc_c', 1e-10, 1e10, log=True)
        
        clf = SVC(C=c, gamma='auto')

    return cross_val_score(clf, features, target, n_jobs=-1, cv=3).mean()

Давайте разберем это:

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

Наконец, мы создаем исследование, чтобы найти лучшее испытание:

study = optuna.create_study(direction='maximize')
study.optimize(objective, n_trials=100)

trial = study.best_trial
print('Accuracy: {}'.format(trial.value))
print("Best hyperparameters: {}".format(trial.params))
Accuracy: 0.9866666666666667
Best hyperparameters: {'classifier': 'LogisticRegression', 'svc_c': 3.9657712904031657}

Визуализация исследования

Optuna предоставляет несколько методов визуализации исследования.

from optuna.visualization import plot_optimization_history, plot_slice

plot_optimization_history(study)

plot_slice(study)

Что дальше?

Вау! Вот и все. Теперь вы мастер автоматизированного HPO.

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

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

Спасибо, что отправились в это путешествие со мной.

Рекомендации