tabnet icon indicating copy to clipboard operation
tabnet copied to clipboard

Trouble with learning when tune_grid() with CPU parallel processing

Open csh01470 opened this issue 3 years ago • 1 comments

HI.

I want to used a tabnet model using tidymodels(parsnip) format. and I try to train a model with parallel processing(doFuture package).

When I use the tune_grid() function, it returns the following error message : Error in UseMethod("filter"): no applicable method for 'filter' applied to an object of class "NULL"

Here's the code:

################################################################################
#00-1. SYSTEM SETTING
#(1) Set System Options
options(scipen=100)
set.seed(seed=2022)

#(2) Import Packages 
library(tidyverse)
library(tidymodels)
library(torch)
library(tabnet)
#> 
#> Attaching package: 'tabnet'
#> The following object is masked from 'package:dials':
#> 
#>     momentum
library(finetune)
library(parallel)
library(doFuture)
#> Loading required package: foreach
#> 
#> Attaching package: 'foreach'
#> The following objects are masked from 'package:purrr':
#> 
#>     accumulate, when
#> Loading required package: future
library(glue)

#(3) Set Parallel Process
THREAD_NUM <- detectCores(all.test=TRUE, logical=TRUE) - 2 
plan(multisession, workers = THREAD_NUM)
registerDoFuture()

################################################################################
#01. READ TABLE
#(1) Read BOSTON Dataset
BOSTON_raw <- read_csv(file="a:/R_project/TIL_R/data/kaggle_Predict_Boston_Hosuing/boston_housing.csv")
#> Rows: 506 Columns: 14
#> ── Column specification ────────────────────────────────────────────────────────
#> Delimiter: ","
#> dbl (14): CRIM, ZN, INDUS, CHAS, NOX, RM, AGE, DIS, RAD, TAX, PTRATIO, B, LS...
#> 
#> ℹ Use `spec()` to retrieve the full column specification for this data.
#> ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.

################################################################################
#02. PREPARE DATASET FOR MACHINE-LEARNING
#(1) Split Data
BOSTON_split <- initial_split(data=BOSTON_raw, prop=0.2)
BOSTON_train <- training(x=BOSTON_split)
BOSTON_test <- testing(x=BOSTON_split)

#(3) Define 5-Fold CV Object
BOSTON_train_cv <- vfold_cv(data=BOSTON_train, v=5)

#(4) Define Recipes
BOSTON_recipe <- recipe(formula=MEDV~., data=BOSTON_train) %>% 
  step_range(all_numeric_predictors()) %>% 
  step_zv(all_predictors()) 

################################################################################
#02. TRAIN AND PREDICT BY TABNET
#(1) Define Model
tabnet_model <- tabnet(
  epochs             = tune(), 
  decision_width     = tune(), 
  num_steps          = tune(), 
  penalty            = tune()
) %>% 
  set_mode(mode="regression") %>% 
  set_engine(engine="torch")

#(2) Define Workflow
tabnet_wf <- workflow(
  preprocessor = BOSTON_recipe,
  spec         = tabnet_model
) 
 
#(3) Define Hyper-Parameters
tabnet_params <- tabnet_model %>% 
  extract_parameter_set_dials()

#(3) Set Grid
tabnet_grid <- tabnet_params %>% 
  grid_latin_hypercube(size=100)

#(4) Tune Hyper-Parameters
tabnet_tune <- tune_grid(
  object     = tabnet_wf,
  param_info = tabnet_params,
  grid       = tabnet_grid,
  resamples  = BOSTON_train_cv,
  metrics    = metric_set(rmse),
  control    = control_grid(verbose=TRUE,
                            save_pred=TRUE,
                            save_workflow=TRUE,
                            parallel_over="everything")
)
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold1: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold2: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold2: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold2: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold2: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> x Fold2: internal: Error in UseMethod("filter"): no applicable method for 'filter' applied ...
#> ...
#> Warning: All models failed. Run `show_notes(.Last.tune.result)` for more
#> information.

Created on 2022-08-23 with reprex v2.0.2

and my session info is here

sessionInfo()
#> R version 4.2.1 (2022-06-23 ucrt)
#> Platform: x86_64-w64-mingw32/x64 (64-bit)
#> Running under: Windows 10 x64 (build 22000)
#> 
#> Matrix products: default
#> 
#> locale:
#> [1] LC_COLLATE=English_United States.utf8 
#> [2] LC_CTYPE=English_United States.utf8   
#> [3] LC_MONETARY=English_United States.utf8
#> [4] LC_NUMERIC=C                          
#> [5] LC_TIME=English_United States.utf8    
#> 
#> attached base packages:
#> [1] stats     graphics  grDevices utils     datasets  methods   base     
#> 
#> loaded via a namespace (and not attached):
#>  [1] withr_2.5.0     digest_0.6.29   lifecycle_1.0.1 magrittr_2.0.3 
#>  [5] reprex_2.0.2    evaluate_0.16   highr_0.9       stringi_1.7.8  
#>  [9] rlang_1.0.4     cli_3.3.0       rstudioapi_0.14 fs_1.5.2       
#> [13] rmarkdown_2.15  tools_4.2.1     stringr_1.4.1   glue_1.6.2     
#> [17] xfun_0.32       yaml_2.3.5      fastmap_1.1.0   compiler_4.2.1 
#> [21] htmltools_0.5.3 knitr_1.39

Created on 2022-08-23 with reprex v2.0.2

Thank you.

csh01470 avatar Aug 23 '22 08:08 csh01470

I have run into this same issue, and have not yet found a solution outside of removing the parallel parts of my workflow. Would be interested in following along.

nspies13 avatar Sep 30 '22 16:09 nspies13

Hello Some initial investigation may link the issue to {tune} not being robust to .NULL env problem : A debug of tune:::fn_tune_grid_loop() returns

Browse[2]> results
[[1]]
<error/rlang_error>
Error in `rlang::env_bind()` at tune/R/logging.R:196:2:
! `.env` must be an environment, not NULL.
---
Backtrace:
  1. parallel (local) workRSOCK()
 26. base::eval(...)
 27. base::eval(...)
 29. base::lapply(...)
 30. FUN(X[[i]], ...)
 35. tune (local) fn_tune_grid_loop_iter_safely(...)
       at tune/R/grid_code_paths.R:206:10
 36. tune:::log_problems(notes, control, split, "internal", problems)
       at tune/R/grid_code_paths.R:519:2
 37. tune:::tune_catalog(...)
       at tune/R/logging.R:314:6
 38. rlang::env_bind(.env = tune_env$progress_env)
       at tune/R/logging.R:196:2

[[2]]
<error/rlang_error>
Error in `rlang::env_bind()` at tune/R/logging.R:196:2:
! `.env` must be an environment, not NULL.
---
Backtrace:
  1. parallel (local) workRSOCK()
 26. base::eval(...)
 27. base::eval(...)
 29. base::lapply(...)
 30. FUN(X[[i]], ...)
 35. tune (local) fn_tune_grid_loop_iter_safely(...)
       at tune/R/grid_code_paths.R:206:10
 36. tune:::log_problems(notes, control, split, "internal", problems)
       at tune/R/grid_code_paths.R:519:2
 37. tune:::tune_catalog(...)
       at tune/R/logging.R:314:6
 38. rlang::env_bind(.env = tune_env$progress_env)
       at tune/R/logging.R:196:2

as {h2o} has a special .env treatment in {tune}, maybe the same is needed for {torch}, as binding renvs for torch is certainly a bad idea...

cregouby avatar Feb 06 '23 23:02 cregouby

Hello,

Sorry for this late update, but digging into this makes me definitively think it can't be supported. If I understqnd it well, the way {tune} runs parallelize compute load is through forking environements, which makes no sense with a torch backend (because you would never get enough memory to instantiate multiple torch instances on a GPU, or on even on a CPU ) so this should ideally be prevented.

Workaround for your example, you should run it sequentially with the allow_par = FALSE option, as {torch} is already using all your compute resources for each tuning iteration :

tabnet_tune <- tune:::tune_grid.workflow(
  object     = tabnet_wf,
  param_info = tabnet_params,
  grid       = tabnet_grid,
  resamples  = BOSTON_train_cv,
  metrics    = metric_set(mae),
  control    = control_grid(verbose = TRUE,
                            save_pred = TRUE,
                            save_workflow = TRUE,
                            allow_par = FALSE)
)

cregouby avatar Feb 09 '23 08:02 cregouby