R语言 为什么我的xgboost模型调整极其缓慢?

rryofs0p  于 2022-12-30  发布在  其他
关注(0)|答案(1)|浏览(362)

我尝试在R中调整xgboost参数,在一台32 GB内存、8核/16处理器的机器上需要一天多的时间才能完成。有人能看看reprex并提出改进建议或指出荒谬或错误的地方吗?tune_grid部分运行得非常慢。
注意:reprex的运行时间不超过一天,它比我的小--我有230 k个观测值,115 k个“组”(假设组=患者ID,每个患者有多个观测值),有更多的预测变量,名义预测变量有更多的类。在开始时,我做了一些任意的修改,使stackoverflow数据看起来更像真实的数据。

library(tidymodels)
library(modeldata)
library(janitor)
library(parallel)

data(stackoverflow)

set.seed(123)
ids <- 1:nrow(stackoverflow)
groups <- sample(c(state.name, state.abb),
                 size = nrow(stackoverflow),
                 replace = TRUE)
a_fctr <- sample(c('fctr1', 'fctr2', 'fctr3'),
                 size = nrow(stackoverflow),
                 replace = TRUE)

stackoverflow_mod <- stackoverflow %>%
  clean_names() %>%
  bind_cols(tibble(ids, groups, a_fctr)) %>%
  rename(id_num = ids,
         group_nm = groups,
         fctr_nm = a_fctr) %>%
  # if any member of the group contains a graphic designer mark the entire group
  group_by(group_nm) %>%
  mutate(strata_graphic = ifelse(any(graphic_designer == 1), 'Graphic designer', 'None')) %>%
  ungroup()
  

set.seed(123)
ini_split <- group_initial_split(stackoverflow_mod,
                                 prop = 0.8,
                                 group = group_nm,
                                 strata = strata_graphic)
train_split <- training(ini_split)
test_split <- testing(ini_split)

exclude <- c('id_num',
             'group_name',
             'strata_graphic')

recipe_1 <- recipe(remote ~ ., data = train_split) %>%
  update_role(any_of(exclude), new_role = 'extra') %>%
  step_dummy(all_nominal_predictors(), one_hot = TRUE)

xgb_tm <- boost_tree(
  trees = tune(),
  tree_depth = tune(),
  min_n = tune(),
  loss_reduction = tune(),
  sample_size = tune(),
  mtry = tune(),
  learn_rate = tune()
  ) %>%
  set_engine('xgboost') %>%
  set_mode('classification')

xgb_workflow <- workflow() %>%
  add_recipe(recipe_1) %>%
  add_model(xgb_tm)

set.seed(123)
xgb_grid <- grid_latin_hypercube(
  trees(range = c(500, 1500)),
  tree_depth(),
  min_n(),
  loss_reduction(),
  sample_size = sample_prop(c(0.4, 0.8)),
  finalize(mtry(), prep(recipe_1) %>% bake(train_split)),
  learn_rate(),
  size = 50
)

set.seed(123)
folds_group <- group_vfold_cv(data = train_split,
                              balance = 'groups',
                              v = 10,
                              repeats = 3, 
                              group = group_nm,
                              strata = strata_graphic)

gc()
clust <- makePSOCKcluster((detectCores() - 2))
doParallel::registerDoParallel(clust)

xgb_res <- xgb_workflow %>%
  tune_grid(
    resamples = folds_group,
    grid = xgb_grid,
    control = control_grid(save_pred = TRUE, parallel_over = 'everything'),
    metrics = metric_set(roc_auc, pr_auc)
  )

stopCluster(clust)
foreach::registerDoSEQ()

调优长度对于数据集的大小是否正常?我实现的并行化是否错误?我的调优网格设置是否愚蠢?还有其他问题吗?

ar7v8xwq

ar7v8xwq1#

使用此设置,您将拟合50个不同的模型(50个不同的超参数网格值)30次(10倍完成3次)。这将产生1500个拟合模型。即使每个模型拟合花费1秒,您也将看到25分钟的运行时间。这是假设所有内容并行运行的原因。
我喜欢使用的一个技巧是,首先使用control = control_grid(verbose = TRUE)不并行地运行代码,然后手动计算每个模型运行所需的时间,运行几个模型后,停止该过程,进行一些数学运算以确定总的运行时间。
在执行此操作时,您还应该查看在单线程运行代码时R会话占用的内存量。根据数据的大小,您可能没有足够的内存来同时适应多个模型,因此,单线程可以更快地适应所有内容。

相关问题