tidymodels: ошибка при прогнозировании новых данных с помощью модели xgboost

Я обучил две модели xgboost. Один был обучен без повторной выборки с вызовом fit () сразу после того, как спецификации модели были сделаны следующим образом ...

model <- boost_tree() %>%
set_mode() %>%
set_engine() %>%
fit()%>%
predict()

.. и он работает нормально, мои прогнозы были сделаны.

Другой был обучен повторной выборке, настраивая рабочий процесс с помощью tune :: tune_grid (). После того, как tune_grid обучил модель, я выбрал лучшую модель с помощью tune :: select_best (), завершил рабочий процесс с помощью tune :: finalize_workflow () и извлек свою окончательную модель с помощью вызова fit () для данных обучения и, наконец, workflow :: pull_workflow_fit (). Однако, когда я хочу сделать прогнозы с помощью этой модели на новых данных, появляется следующая ошибка:

Fehler in xgboost::xgb.DMatrix(data = newdata, missing = NA) : 
  'data' has class 'character' and length 1178.
  'data' accepts either a numeric matrix or a single filename.

В обоих случаях новые данные - это один и тот же тибет. Кто-нибудь знает ответ на эту проблему?


person lucaskr    schedule 17.07.2020    source источник
comment
запустить class(newdata): это числовая матрица? если формат неправильный, вы можете попробовать принудительно использовать as.matrix. Если у вас есть символы, то, возможно, это категориальные переменные, которые нуждаются в кодировании. В cran.r-project.org/web/packages/xgboost / vignettes / об этом говорится в разделе 1.2.2.3.   -  person Jonny Phelps    schedule 17.07.2020
comment
class(newdata) сначала был табличным. После выполнения as.matrix() выдает матрицу, но ошибка остается прежней. Данные обучения / тестирования не содержат никаких признаков символа, но содержат факторные особенности. Я скормил модели tbl, так как она принимает только tbl в качестве формата данных. Тем не менее, когда я хочу предсказать новые данные, он говорит: данные принимают либо числовую матрицу, либо одно имя файла, как указано выше.   -  person lucaskr    schedule 17.07.2020


Ответы (1)


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

library(tidymodels)
#> ── Attaching packages ────────────────────────────────────── tidymodels 0.1.1 ──
#> ✓ broom     0.7.0      ✓ recipes   0.1.13
#> ✓ dials     0.0.8      ✓ rsample   0.0.7 
#> ✓ dplyr     1.0.0      ✓ tibble    3.0.3 
#> ✓ ggplot2   3.3.2      ✓ tidyr     1.1.0 
#> ✓ infer     0.5.3      ✓ tune      0.1.1 
#> ✓ modeldata 0.0.2      ✓ workflows 0.1.2 
#> ✓ parsnip   0.1.2      ✓ yardstick 0.0.7 
#> ✓ purrr     0.3.4
#> ── Conflicts ───────────────────────────────────────── tidymodels_conflicts() ──
#> x purrr::discard() masks scales::discard()
#> x dplyr::filter()  masks stats::filter()
#> x dplyr::lag()     masks stats::lag()
#> x recipes::step()  masks stats::step()

## pretend this is your training data
data("hpc_data")

xgb_spec <- boost_tree(
  trees = 1000, 
  tree_depth = tune(), 
  min_n = tune()
) %>% 
  set_engine("xgboost") %>% 
  set_mode("classification")

hpc_folds <- vfold_cv(hpc_data, strata = class)

xgb_grid <- grid_latin_hypercube(
  tree_depth(),
  min_n(),
  size = 5
)

xgb_wf <- workflow() %>%
  add_formula(class ~ .) %>%
  add_model(xgb_spec)

xgb_wf
#> ══ Workflow ════════════════════════════════════════════════════════════════════
#> Preprocessor: Formula
#> Model: boost_tree()
#> 
#> ── Preprocessor ────────────────────────────────────────────────────────────────
#> class ~ .
#> 
#> ── Model ───────────────────────────────────────────────────────────────────────
#> Boosted Tree Model Specification (classification)
#> 
#> Main Arguments:
#>   trees = 1000
#>   min_n = tune()
#>   tree_depth = tune()
#> 
#> Computational engine: xgboost

doParallel::registerDoParallel()
set.seed(123)
xgb_res <- tune_grid(
  xgb_wf,
  resamples = hpc_folds,
  grid = xgb_grid
)

xgb_res
#> # Tuning results
#> # 10-fold cross-validation using stratification 
#> # A tibble: 10 x 4
#>    splits             id     .metrics          .notes          
#>    <list>             <chr>  <list>            <list>          
#>  1 <split [3.9K/434]> Fold01 <tibble [10 × 6]> <tibble [0 × 1]>
#>  2 <split [3.9K/434]> Fold02 <tibble [10 × 6]> <tibble [0 × 1]>
#>  3 <split [3.9K/434]> Fold03 <tibble [10 × 6]> <tibble [0 × 1]>
#>  4 <split [3.9K/434]> Fold04 <tibble [10 × 6]> <tibble [0 × 1]>
#>  5 <split [3.9K/434]> Fold05 <tibble [10 × 6]> <tibble [0 × 1]>
#>  6 <split [3.9K/434]> Fold06 <tibble [10 × 6]> <tibble [0 × 1]>
#>  7 <split [3.9K/433]> Fold07 <tibble [10 × 6]> <tibble [0 × 1]>
#>  8 <split [3.9K/432]> Fold08 <tibble [10 × 6]> <tibble [0 × 1]>
#>  9 <split [3.9K/431]> Fold09 <tibble [10 × 6]> <tibble [0 × 1]>
#> 10 <split [3.9K/431]> Fold10 <tibble [10 × 6]> <tibble [0 × 1]>

Затем давайте завершим этот рабочий процесс, а затем fit() перейдем к обучающим данным. (В процессе настройки использовались обучающие данные, но это было сделано для поиска лучших параметров модели, а не для обучения самой модели.)

trained_wf <- xgb_wf %>%
  finalize_workflow(
  select_best(xgb_res, "roc_auc")
) %>%
  fit(hpc_data)

trained_wf
#> ══ Workflow [trained] ══════════════════════════════════════════════════════════
#> Preprocessor: Formula
#> Model: boost_tree()
#> 
#> ── Preprocessor ────────────────────────────────────────────────────────────────
#> class ~ .
#> 
#> ── Model ───────────────────────────────────────────────────────────────────────
#> ##### xgb.Booster
#> raw: 2 Mb 
#> call:
#>   xgboost::xgb.train(params = list(eta = 0.3, max_depth = 3L, gamma = 0, 
#>     colsample_bytree = 1, min_child_weight = 9L, subsample = 1), 
#>     data = x, nrounds = 1000, watchlist = wlist, verbose = 0, 
#>     objective = "multi:softprob", num_class = 4L, nthread = 1)
#> params (as set within xgb.train):
#>   eta = "0.3", max_depth = "3", gamma = "0", colsample_bytree = "1", min_child_weight = "9", subsample = "1", objective = "multi:softprob", num_class = "4", nthread = "1", validate_parameters = "TRUE"
#> xgb.attributes:
#>   niter
#> callbacks:
#>   cb.evaluation.log()
#> # of features: 26 
#> niter: 1000
#> nfeatures : 26 
#> evaluation_log:
#>     iter training_merror
#>        1        0.320942
#>        2        0.301778
#> ---                     
#>      999        0.010390
#>     1000        0.010390

Теперь предположим, что у нас есть совершенно новые данные. Вы можете predict() использовать новые данные об обученном рабочем процессе.

brand_new_data <- hpc_data[5, -8]
brand_new_data
#> # A tibble: 1 x 7
#>   protocol compounds input_fields iterations num_pending  hour day  
#>   <fct>        <dbl>        <dbl>      <dbl>       <dbl> <dbl> <fct>
#> 1 E              100           82         20           0  10.4 Fri

predict(trained_wf, new_data = brand_new_data)
#> # A tibble: 1 x 1
#>   .pred_class
#>   <fct>      
#> 1 VF

Создано 17 июля 2020 г. пакетом REPEX (v0.3.0)

person Julia Silge    schedule 18.07.2020
comment
Спасибо за развернутый ответ. Следуя вашим инструкциям с моими собственными данными, прогнозирование с помощью обученного объекта рабочего процесса работает нормально. Однако мне это кажется не таким заметным, что я вызываю predict() на trained_wf вместо trained_wf %>% pull_workflow_fit(), что дает мне реальный объект модели пастернака. Поскольку предсказал следующий способ, я вызываю predict() на объекте модели пастернака boost_tree() %>% set_mode() %>% set_engine() %>% fit()%>% predict() - person lucaskr; 20.07.2020