Гиперпараметры — это характеристики модели, которые фиксируются до начала обучения (например - глубина решающего дерева, значение силы регуляризации в линейной модели, learning rate для градиентного спуска). Гиперпараметры, в отличие от параметров задаются разработчиком модели перед ее обучением, в свою очередь параметры модели настраиваются в процессе обучения модели на данных.

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

Ключевые особенности фреймворка:

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

  2. Алгоритмы SoTA для выбора гиперпараметров из пространства заданного разработчиком (samplers) и для ранней остановки бесперспективных экспериментов (pruners). В Optuna представлены различные алгоритмы семплирования и прунинга, разработчик может выбрать какой-то конкретный, оставить дефолтный, или написать свой собственный.

  3. Легкость расспаралеливания процесса поиска гиперпараметров. Также к Optuna можно прикрутить dashboard с визуализацией обучения в реальном времени.

Установка

Рекомендуется установка через pip.

pip install optuna

Базовый пример

Этот фреймворк обычно используют как оптимизатор гиперпараметров, но никто не запрещает использовать ее для оптимизации любой функции.  В качестве базового примера использования, авторы фреймворка показывают как можно минимизировать квадратичную функцию  (x-2)^2.

import optuna

def objective(trial):
    x = trial.suggest_float('x', -10, 10)
    return (x - 2) ** 2

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

study.best_params  # E.g. {'x': 2.002108042}
  1. Определяем целевую функцию objective , в через аргументы она будет получать специальный объект trial. С его помощью можно назначать различные гипермараметры, Например, как в примере выше, мы задаем x в интервале [-10,10].

  2. Далее создаем объект обучения с помощью метода optuna.create_study.

  3. Запускаем оптимизацию целевой функции objective на 100 итераций n_trials=100. Происходит 100 вызовов нашей функции с различными параметрам от -10 до 10. Какие именно параметры выбирает optuna будет описано ниже.

Как задать пространство поиска гиперпараметров?

Как было показано выше в целевую функцию будет передан специальный объект Trial. Так как наша целевая функция будет вызываться некоторое число раз, на каждом вызове из объекта Trial будут возвращаться новые значения параметров. Разработчику остается только задать характеристики этих параметров. Для этого есть несколько методов:

  1. suggest_categorical(name, choice) задает категориальные параметры. Пример

  2. suggest_float(name, low, high, *, step=None, log=False) задает параметр типа float - число с плавающей точкой. Пример

  3. suggest_int(name, low, high, step=1, log=False) задает параметр типа int - целое число. Пример

Что еще можно настроить до начала оптимизации?

Чтобы запустить обучение нам необходимо создать объект Study. Его рекомендуется создавать либо с помощью метода create_study (пример) или load_study (пример).

В момент создания можно указать:

  1. направление оптимизации функции directions- минимизация или максимизация

  2. storage адрес базы данных, для сохранения результатов испытаний

  3. study_name имя, если не указать, то будет сгенерировано автоматически. Указание собственного имени, удобно при сохранении экспериментов и их загрузке

  4. pruner и sampler - об этом ниже

После создания объекта Study, можно приступать к оптимизации целевой функции. Сделать это можно с помощью метода optimize (пример).

Как посмотреть результаты оптимизации?

В объекте Study есть специальные поля, которые позволяют посмотреть результаты после обучения:

  1. study.best_params лучшие параметры

  2. study.best_value  лучшее оптимальное значение целевой функции

  3. study.best_trial развернутые параметры лучшего испытания

Как сохранить/загрузить результаты испытаний?

Сохранить только историю в виде датафрейма

df = study.trials_dataframe()
df.to_csv('study.csv')
loaded = pd.read_csv('study.csv')

Сохранить дамп самого оптимизатора

joblib.dump(study, 'experiments.pkl')
study_loaded = joblib.load('experiments.pkl')
study_loaded.trials_dataframe()

Можно также сохранять результаты испытаний в БД, для этого в Optuna есть специальный модуль Storages, который предоставляет некоторые объекты для взаимодействия БД. Например есть объект позволяющий взаимодействовать с redis. Пример.

Что такое Sampler и Pruner?

Samplers в Optuna это набор алгоритмов для поиска гиперпараметров.

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

  1. Grid Search - поиск по решетке. Для каждого гиперпараметра задается список возможных значений, после перебираются все возможные комбинации элементов списков, выбирается тот набор на котором значение целевой функции было минимальным/максимальным.

  2. Random Search - случайный поиск. Для каждого гиперпараметра задается распределение, из которого выбирается его значение. Благодаря такому подходу, найти оптимальный набор гиперпараметров можно быстрее.

  3. Байесовская оптимизация. Итерационный метод, который на каждой итерации указывает наиболее вероятную точку, в которой наша целевая функция будет оптимальна. При этом выдаваемые вероятные точки включают две компоненты: 

    1. хорошая точка там, где согласно истории функция выдавала хорошие результаты на предыдущих вызовах (exploitation) 

    2. хорошая точка там, где высокая неопределенность, то есть неисследованные части пространства (exploration)

Более подробно про эти алгоритмы, а также про Tree-structured Parzen Estimator (TPE), Population Based Training (PBT) можно прочитать в учебнике по машинному обучению от Яндекс, там же можно найти ссылки на полезные ресурсы по этой теме и сравнение подходов между собой.

В Optuna реализованы:

По умолчанию устанавливается TPESampler.

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

Для примера рассмотрим самый простой прунер - MedianPruner. Он обрезает на каждом шаге половину бесперспективных испытаний.

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

В Optuna реализованы: 

  • MedianPruner - pruner использующий правило половина останавливается, половина продолжает

  • NopPruner - pruner который никогда не останавливает испытания.

  • PatientPruner - pruner обертка над любым другим pruner, позволяет не останавливать бесперспективные испытания, пока не закончится терпение у PatientPruner еще несколько эпох.

  • PercentilePruner - pruner, который сохраняет определенный процентиль испытаний.

  • SuccessiveHalvingPruner - алгоритм Asynchronous Successive Halving

  • HyperbandPruner - алгоритм Hyperband

  • ThresholdPruner - pruner, который останавливает испытание, если значение целевой функции вышло за границы - превысило верхний порог или стало ниже чем нижний порог.

Какой Sampler и Pruner стоит использовать ?

В документации согласно этому исследованию “Benchmarks with Kurobako” для не глубогкого обучения стоит использовать:

  • Для RandomSampler лучший pruner - это MedianPruner.

  • Для TPESampler лучший pruner - это Hyperband.

В документации также приведены рекомендации для глубокого обучения.

Как подружить фреймворк с популярными библиотеками?

В Optuna есть модуль integration, который содержит классы, используемые для интеграции с внешними популярными библиотеками машинного обучения. Среди них есть такие библиотеки как CatBoost, fast.ai, Keras, LightGBM, PyTorch, scikit-learn, XGBoost. С полным списком можно ознакомится тут.

А что еще есть?

  • Есть модуль для визуализации, в нем представлены функции для построения графика процесса оптимизации с использованием plotly и matplotlib. Функции построения графиков обычно принимают объект Study и настроечные параметры.

    Здесь пример построения графика истории оптимизации.

  • Есть модуль importance, с помощью него есть возможность провести оценку важности гиперпараметров на основе завершенных испытаний.

Комментарии (1)


  1. romanzes
    09.12.2022 12:09

    Спасибо!
    Они там еще otpuna-dashboard сейчас пилят