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

Например, Facebook анонсировал Топор и Боторч. Они планируют использовать это программное обеспечение в самых разных проектах, таких как:

  • Настройка алгоритмов потоковой передачи видео
  • Настройка моделей машинного обучения
  • Аппаратный дизайн AR / VR
  • Настройка компилятора Just-In-Time (для HHVM)

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

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

Библиотека байесовской оптимизации для функций черного ящика, написанная на Go.
https://github.com/c-bata/goptuna

Введение байесовской оптимизации

Сначала я объясню, что делают байесовские алгоритмы оптимизации. Когда у нас есть система something, и ее производительность зависит от чего-то непрерывного параметра в диапазоне от 0 до 10. Я хотел бы указать оптимальный параметр, который дает наилучшую производительность нашей системы.

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

Существует 3 современных байесовских метода оптимизации:

Алгоритмы на основе GP (гауссовского процесса) (например, GP-EI)

TPE (дерево оценщиков парзена)

SMAC (конфигурация алгоритма на основе последовательной модели)

Изучение существующей библиотеки байесовской оптимизации для Go

Я поискал в Google существующие библиотеки для байесовской оптимизации в Go и нашел go-bayesopt, библиотеку байесовской оптимизации на основе гауссовских процессов. Я подготовил задачу минимизации, как показано ниже.

f(x1, x2) = (x1–1)²+ (x2–2)²

Оптимальный параметр указанной выше функции (x1, x2) = (1, 2). Я подготовил следующую программу, используя go-bayesopt для оптимизации функции.

После выбора 10 параметров с помощью случайного поиска GP-UCB выбирает 90 параметров (GP - суррогатная модель, а UCB - функция сбора данных). Результаты исполнения следующие.

$ go run _examples/main.go
...
2019/07/25 15:23:23 x: map[bayesopt.Param]float64{bayesopt.UniformParam{Name:"X1", Max:10, Min:-10}:1.0221672603083967, bayesopt.UniformParam{Name:"X2", Max:10, Min:-10}:1.8540991095989217}
2019/07/25 15:23:23 y: 0.021778

Целевая функция вызывается 100 раз, после чего я получил f (1,022, 1,854) = 0,021778 как лучшее значение оценки. Глядя на следующий график, вы можете увидеть, что go-bayesopt фокусируется на точках, которые могут иметь высокую оценку.

Работает нормально. Но, вероятно, он реализован для учебных целей, поэтому функциональных возможностей не хватает. Для 100 оценок требуется 5 минут, потому что выводы из регрессионных моделей GP требуют вычисления обратных матриц, и, как правило, время вычислений обычно велико. Требуется O (t³), t - это количество итераций. А если вы хотите использовать другую функцию сбора данных, такую ​​как EI (ожидаемое улучшение), вам необходимо реализовать ее самостоятельно.

Библиотека Python использует LAPACK через numpy и scipy, но в Go мы не хотим использовать cgo для сохранения переносимости. Чтобы применять самые разные проекты, лучше реализовывать их на чистом Go.

Байесовская оптимизация TPE с использованием Goptuna

TPE (древовидный оценщик парзенов) требует O (t), t - это количество итераций. Я искал в Google выход из реализации TPE в Go, но не нашел. Я реализовал это и вчера опубликовал Гоптуна.

Судя по названию, это голангский порт Оптуны. Goptuna использует интерфейс Define-by-Run наподобие Optuna. Таким образом, мы можем использовать его интуитивно следующим образом.

Результаты представлены ниже:

Случайный поиск со 100 оценками

$ go run _examples/simple_random_search/main.go
...
Result:
- best value 2.5904889254208054
- best param map[x1:0.4405659427118902 x2:0.7883530201915825]

TPE со 100 оценками (включая 10 оценок случайного поиска)

$ go run _examples/simple_tpe/main.go
...
Result:
- best value 0.6195459685895217
- best param map[x1:0.7770961438621743 x2:1.2451093857329996]

В этом случае результат TPE лучше, чем случайный поиск, и хуже, чем go-bayesopt. Пространства поиска целевой функции низкоразмерны (двумерны) и не содержат категориальных переменных. Eggensperger et al. подтвердил, что байесовская оптимизация на основе гауссовского процесса работает лучше, чем TPE и SMAC в низкоразмерных пространствах непрерывного поиска (см. На пути к эмпирической основе для оценки байесовской оптимизации гиперпараметров). Так что в случае с многомерными и категориальными параметрами, я думаю, Гоптуна работает лучше.

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

Вывод

Goptuna кажется практической библиотекой оптимизации в Go. Я надеюсь, что все будут использовать Гоптуна и обратятся ко мне!