Как воспроизвести байесовскую оптимизацию гиперпараметров с помощью тюнера «mbo»?

Я хотел бы использовать R-пакеты mlr3* для построения алгоритмов машинного обучения воспроизводимым образом. Я пытался использовать regr.glmboost с тюнером mbo и терминатором run_time. Я поиграл с частью HPO, но мне не удалось воспроизвести ее с более высоким временем выполнения. Где я неправ?

Вот репрекс об этом явлении:

library(mlr3verse)
library(mlr3mbo)
library(mlr3misc)
library(magrittr)
library(nycflights13)

dt <- as.data.table(weather)
dt <- dt[order(time_hour), .(origin = as.factor(origin), month = as.factor(month), hour = as.factor(hour), temp, dewp, humid, wind_dir, wind_speed, precip, visib, pressure, time_hour = as.numeric(time_hour))]
dt <- na.omit(dt)

best_ones <- map_dtr(
  1L:3L,
  function(i) {
    my_learner <- lrn("regr.glmboost",
      family = to_tune(p_fct(levels = c("Gaussian", "Laplace", "Huber"))),
      nuirange = to_tune(p_dbl(lower = 0, upper = 1000, logscale = FALSE)),
      mstop = to_tune(p_int(lower = 1, upper = 3, trafo = function(x) 10**x)),
      nu = to_tune(p_dbl(lower = 0.01, upper = 0.3, logscale = TRUE)),
      risk = to_tune(p_fct(levels = c("inbag", "oobag", "none"))),
      trace = to_tune(c(TRUE, FALSE)),
      stopintern = to_tune(c(TRUE, FALSE))
    )

    my_task <- as_task_regr(
      x = dt,
      target = "pressure",
      id = "weather_data"
    )

    my_instance <- ti(
      task = my_task,
      learner = my_learner,
      resampling = rsmp("cv", folds = 3),
      measure = msr("regr.mae"),
      terminator = trm("run_time", secs = 300)
    )

    my_tuner <- tnr("mbo")

    set.seed(1234L, kind = "L'Ecuyer-CMRG")
    my_tuner$optimize(my_instance)

    my_instance$archive$best()
  }
)

best_ones[]

Это несколько разные гиперпараметры, которые у меня есть:

семья нуиранж мстоп ню риск след стопинтерн regr.mae предупреждения ошибки runtime_learners ухэш отметка времени партия_номер acq_ei .already_evaluated Хубер 841,3256 3 -2,794395 вкладыш ЛОЖЬ ЛОЖЬ 5.090834 0 0 9.656 01cf38ab-3dc6-4490-b36e-1c14325e42ad 2023-01-10 17:08:15 26 0,0010821 ЛОЖЬ Хубер 849.4117 3 -2,774291 убаг ЛОЖЬ ЛОЖЬ 5.094204 0 0 9,646 6579c965-9184-4fe3-8e01-c1b10df21782 2023-01-10 17:11:56 18 0,0021940 ЛОЖЬ Хубер 855,7414 3 -2,878846 убаг ЛОЖЬ ЛОЖЬ 5.096876 0 0 9.497 458122cc-f51c-4d81-a6d2-93dc024baa58 2023-01-10 17:16:22 15 0,0090615 ЛОЖЬ

Я предполагаю, что проблема связана с раздачей, но я не знаю, как сделать это правильно в этом случае. Любая помощь будет оценена по достоинству!

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3
0
76
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Поэтому я думаю, что в вашем коде есть два возможных источника ошибок:

  1. Я думаю, что семя должно быть в начале функции, которая вызывается в map_dtr(...), просто чтобы быть уверенным.
  2. Я бы не стал полагаться на терминатор времени выполнения, поскольку разные итерации могут получить более или менее фактические вычисления, даже если у них одинаковое время выполнения. (Вы даже видите это в выводе ниже, что все три повторения имеют немного разное время выполнения)

Обращение к обоим, кажется, дает воспроизводимые результаты (некоторые части кода немного изменены, чтобы сократить время выполнения).

Я надеюсь, что это также работает для вас.

library(mlr3verse)
#> Loading required package: mlr3
library(mlr3mbo)
#> Loading required package: mlr3tuning
#> Loading required package: paradox
library(mlr3misc)
library(magrittr)
#> 
#> Attaching package: 'magrittr'
#> The following objects are masked from 'package:mlr3misc':
#> 
#>     set_class, set_names
library(nycflights13)

dt <- as.data.table(weather)
dt <- dt[order(time_hour), .(origin = as.factor(origin), month = as.factor(month), hour = as.factor(hour), temp, dewp, humid, wind_dir, wind_speed, precip, visib, pressure, time_hour = as.numeric(time_hour))]
dt <- na.omit(dt)

best_ones <- map_dtr(
  1L:3L,
  function(i) {
    set.seed(1234L, kind = "L'Ecuyer-CMRG")
    my_learner <- lrn("regr.glmboost",
      family = to_tune(p_fct(levels = c("Gaussian", "Laplace", "Huber"))),
      nuirange = to_tune(p_dbl(lower = 0, upper = 1000, logscale = FALSE)),
      mstop = to_tune(p_int(lower = 1, upper = 3, trafo = function(x) 10**x)),
      nu = to_tune(p_dbl(lower = 0.01, upper = 0.3, logscale = TRUE)),
      risk = to_tune(p_fct(levels = c("inbag", "oobag", "none"))),
      trace = to_tune(c(TRUE, FALSE)),
      stopintern = to_tune(c(TRUE, FALSE))
    )

    my_task <- as_task_regr(
      x = dt,
      target = "pressure",
      id = "weather_data"
    )

    my_instance <- ti(
      task = my_task,
      learner = my_learner,
      resampling = rsmp("holdout"),
      measure = msr("regr.mae"),
      terminator = trm("evals", n_evals = 2)
    )

    my_tuner <- tnr("mbo")

    my_tuner$optimize(my_instance)

    my_instance$archive$best()
  }
)
#> INFO  [22:33:53.565] [bbotk] Starting to optimize 7 parameter(s) with '<OptimizerMbo>' and '<TerminatorEvals> [n_evals=2, k=0]'
#> ... (A LOT OF LOG OUTPUT THAT IS OMITTED)

best_ones[]
#>    family nuirange mstop        nu risk trace stopintern regr.mae warnings
#> 1:  Huber 85.45087     3 -2.572761 none FALSE      FALSE  4.74076        0
#> 2:  Huber 85.45087     3 -2.572761 none FALSE      FALSE  4.74076        0
#> 3:  Huber 85.45087     3 -2.572761 none FALSE      FALSE  4.74076        0
#>    errors runtime_learners                                uhash  x_domain
#> 1:      0            3.406 653adf83-6fbc-4ef5-b6dd-7e12e97b49d6 <list[7]>
#> 2:      0            3.773 f70dec6a-073a-45c8-b795-29ef5b662625 <list[7]>
#> 3:      0            3.673 dc18e13f-2e7d-4fe9-9845-187ebf0db3b3 <list[7]>
#>              timestamp batch_nr
#> 1: 2023-01-10 22:34:17        1
#> 2: 2023-01-10 22:34:41        1
#> 3: 2023-01-10 22:35:05        1

Created on 2023-01-10 by the reprex package (v2.0.1)

Хорошо, я понял, что терминатор "run_time" не связан с воспроизводимостью. Спасибо за помощь! Тем не менее, я только что попробовал итерацию с перемещенным заполнением, и терминатор «run_time» остался прежним, и это дало стабильные результаты. Так что это стало казаться воспроизводимым.

sanyi 11.01.2023 15:30

Еще один комментарий о том, почему сид должен попасть в топ здесь:

HPO — это, по сути, шумная оптимизация черного ящика с шумом в основном из-за:

  1. алгоритм учащегося недетерминирован

  2. цель, т. е. ошибка обобщения, оцениваемая с помощью метода повторной выборки

Чтобы уменьшить шум во время оптимизации, мы можем зафиксировать повторную выборку, т. Е. instantiate ее на Task (и, следовательно, использовать те же разбиения обучающего теста для оценки конфигураций гиперпараметров).

Когда вы строите TuningInstance:

my_instance <- ti(
  task = my_task,
  learner = my_learner,
  resampling = rsmp("cv", folds = 3),
  measure = msr("regr.mae"),
  terminator = trm("run_time", secs = 300)
)

вы передаете Resampling, экземпляр которого (еще) не был создан на Task. Однако во время построения ObjectiveTuning в рамках построения TuningInstance он будет автоматически создан (чтобы сделать оптимизацию менее шумной и «более легкой»).

Следовательно, если вы не зададите построение my_instance, разделение тестов поезда на основе сверток CV будет другим, и вы, естественно, получите разные прогоны оптимизатора и результаты.

По сути, то, что вы наблюдали в своем невоспроизводимом примере, - это эффект шума из-за различной передискретизации!

Последнее замечание: Если ваш Objective зашумлен, mlr3mbo по умолчанию определит результат настройки, выбрав конфигурацию с лучшим предсказанием среднего значения суррогатной модели, то есть my_instance$result будет получен с использованием result_by_surrogate_design вместо result_by_default (что аналогично использованию my_instance$archive$best()).

Поэтому будьте осторожны при использовании my_instance$result по сравнению с my_instance$archive$best(), но это также зависит от ваших пользовательских предпочтений и того, что вас интересует.

Другие вопросы по теме