Гиперпараметры — это характеристики модели, которые фиксируются до начала обучения (например - глубина решающего дерева, значение силы регуляризации в линейной модели, learning rate для градиентного спуска). Гиперпараметры, в отличие от параметров задаются разработчиком модели перед ее обучением, в свою очередь параметры модели настраиваются в процессе обучения модели на данных.
Optuna — это фреймворк для для автоматизированного поиска оптимальных гиперпараметров для моделей машинного обучения. Она подбирает эти параметры методом проб и ошибок.
Ключевые особенности фреймворка:
Настраиваемое пространство поиска гиперпараметров. Разработчик может самостоятельно задать пространство для поиска гиперпараметров, используя базовый синтаксис Python (циклы, условия).
Алгоритмы SoTA для выбора гиперпараметров из пространства заданного разработчиком (samplers) и для ранней остановки бесперспективных экспериментов (pruners). В Optuna представлены различные алгоритмы семплирования и прунинга, разработчик может выбрать какой-то конкретный, оставить дефолтный, или написать свой собственный.
Легкость расспаралеливания процесса поиска гиперпараметров. Также к Optuna можно прикрутить dashboard с визуализацией обучения в реальном времени.
Установка
Рекомендуется установка через pip.
pip install optuna
Базовый пример
Этот фреймворк обычно используют как оптимизатор гиперпараметров, но никто не запрещает использовать ее для оптимизации любой функции. В качестве базового примера использования, авторы фреймворка показывают как можно минимизировать квадратичную функцию .
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}
Определяем целевую функцию
objective
, в через аргументы она будет получать специальный объектtrial
. С его помощью можно назначать различные гипермараметры, Например, как в примере выше, мы задаемx
в интервале .Далее создаем объект обучения с помощью метода
optuna.create_study
.Запускаем оптимизацию целевой функции
objective
на 100 итерацийn_trials=100
. Происходит 100 вызовов нашей функции с различными параметрам от -10 до 10. Какие именно параметры выбирает optuna будет описано ниже.
Как задать пространство поиска гиперпараметров?
Как было показано выше в целевую функцию будет передан специальный объект Trial
. Так как наша целевая функция будет вызываться некоторое число раз, на каждом вызове из объекта Trial
будут возвращаться новые значения параметров. Разработчику остается только задать характеристики этих параметров. Для этого есть несколько методов:
suggest_categorical(name, choice)
задает категориальные параметры. Примерsuggest_float(name, low, high, *, step=None, log=False)
задает параметр типаfloat
- число с плавающей точкой. Примерsuggest_int(name, low, high, step=1, log=False)
задает параметр типаint
- целое число. Пример
Что еще можно настроить до начала оптимизации?
Чтобы запустить обучение нам необходимо создать объект Study.
Его рекомендуется создавать либо с помощью метода create_study
(пример) или load_study
(пример).
В момент создания можно указать:
направление оптимизации функции
directions
- минимизация или максимизацияstorage
адрес базы данных, для сохранения результатов испытанийstudy_name
имя, если не указать, то будет сгенерировано автоматически. Указание собственного имени, удобно при сохранении экспериментов и их загрузкеpruner
иsampler
- об этом ниже
После создания объекта Study, можно приступать к оптимизации целевой функции. Сделать это можно с помощью метода optimize
(пример).
Как посмотреть результаты оптимизации?
В объекте Study есть специальные поля, которые позволяют посмотреть результаты после обучения:
study.best_params
лучшие параметрыstudy.best_value
лучшее оптимальное значение целевой функции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 это набор алгоритмов для поиска гиперпараметров.
Небольшой экскурс в теорию. Существуют различные подходы к поиску оптимальных гиперпараметров, ниже примеры алгоритмов:
Grid Search - поиск по решетке. Для каждого гиперпараметра задается список возможных значений, после перебираются все возможные комбинации элементов списков, выбирается тот набор на котором значение целевой функции было минимальным/максимальным.
Random Search - случайный поиск. Для каждого гиперпараметра задается распределение, из которого выбирается его значение. Благодаря такому подходу, найти оптимальный набор гиперпараметров можно быстрее.
Байесовская оптимизация. Итерационный метод, который на каждой итерации указывает наиболее вероятную точку, в которой наша целевая функция будет оптимальна. При этом выдаваемые вероятные точки включают две компоненты:
хорошая точка там, где согласно истории функция выдавала хорошие результаты на предыдущих вызовах (exploitation)
хорошая точка там, где высокая неопределенность, то есть неисследованные части пространства (exploration)
Более подробно про эти алгоритмы, а также про Tree-structured Parzen Estimator (TPE), Population Based Training (PBT) можно прочитать в учебнике по машинному обучению от Яндекс, там же можно найти ссылки на полезные ресурсы по этой теме и сравнение подходов между собой.
В Optuna реализованы:
GridSampler - Grid Search
RandomSampler - Random Search
TPESampler - Tree-structured Parzen Estimator
CmaEsSampler - Алгоритм на основе CMA-ES
PartialFixedSampler - Алгоритм с частично фиксированными параметрами
NSGAIISampler - Nondominated Sorting Genetic Algorithm II
MOTPESampler - Multiobjective tree-structured parzen estimator
QMCSampler - Quasi Monte Carlo
По умолчанию устанавливается TPESampler.
Pruners в Optuna - это набор алгоритмов для прореживания экспериментов. Pruning - это механизм который позволяет обрывать эксперименты , которые с большой долей вероятности приведут к не оптимальным результатам.
Для примера рассмотрим самый простой прунер - MedianPruner. Он обрезает на каждом шаге половину бесперспективных испытаний.
В 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, с помощью него есть возможность провести оценку важности гиперпараметров на основе завершенных испытаний.