更新R包后parsnip模型调用modeltime_calibrate函数报错
问题概述
开发的一组时间序列预测模型,更新包括modeltime、timetk在内的多个R包前代码可完全正常运行;更新包后代码运行异常,经排查错误出现在校准步骤执行阶段,涉及ranger与xgboost两类模型。
核心报错提示:从新数据获取预测变量时出错,tk_get_timeseries_signature.default无适用于NULL类的方法,仅ranger、xgboost校准失败,prophet模型运行正常。
正常运行时的环境信息
包更新前可正常运行代码的会话环境信息如下:
library(forecast) library(tidyverse) library(lubridate) library(quantdates) library(tidymodels) library(timetk) library(modeltime) library(modeltime.ensemble) > sessionInfo() R version 4.1.3 (2022-03-10) Platform: x86_64-w64-mingw32/x64 (64-bit) Running under: Windows 10 x64 (build 19044) Matrix products: default attached base packages: [1] stats graphics grDevices utils datasets methods base other attached packages: [1] kernlab_0.9-30 prophet_1.0 rlang_1.0.2 Rcpp_1.0.8.3 xgboost_1.6.0.1 ranger_0.13.1 [7] modeltime.ensemble_1.0.0 modeltime.resample_0.2.0 modeltime_1.2.0 timetk_2.8.0 yardstick_0.0.9 workflowsets_0.2.1 [13] workflows_0.2.6 tune_0.2.0 rsample_0.1.1 recipes_0.2.0 parsnip_0.2.1 modeldata_0.1.1 [19] infer_1.0.0 dials_0.1.1 scales_1.2.0 broom_0.8.0 tidymodels_0.2.0 quantdates_1.0 [25] lubridate_1.8.0 forcats_0.5.1 stringr_1.4.0 dplyr_1.0.9 purrr_0.3.4 readr_2.1.2 [31] tidyr_1.2.0 tibble_3.1.7 ggplot2_3.3.6 tidyverse_1.3.1 forecast_8.16 loaded via a namespace (and not attached): [1] readxl_1.4.0 backports_1.4.1 plyr_1.8.7 splines_4.1.3 listenv_0.8.0 inline_0.3.19 digest_0.6.29 [8] foreach_1.5.2 fansi_1.0.3 magrittr_2.0.3 tzdb_0.3.0 Metrics_0.1.4 globals_0.15.0 modelr_0.1.8 [15] gower_1.0.0 RcppParallel_5.1.5 matrixStats_0.62.0 xts_0.12.1 hardhat_0.2.0 tseries_0.10-51 prettyunits_1.1.1 [22] colorspace_2.0-3 rvest_1.0.2 warp_0.2.0 haven_2.5.0 callr_3.7.0 crayon_1.5.1 jsonlite_1.8.0 [29] progressr_0.10.0 survival_3.3-1 zoo_1.8-10 iterators_1.0.14 glue_1.6.2 gtable_0.3.0 ipred_0.9-12 [36] pkgbuild_1.3.1 rstan_2.21.5 future.apply_1.9.0 quantmod_0.4.20 DBI_1.1.2 GPfit_1.0-8 stats4_4.1.3 [43] lava_1.6.10 StanHeaders_2.21.0-7 prodlim_2019.11.13 httr_1.4.3 ellipsis_0.3.2 pkgconfig_2.0.3 loo_2.5.1 [50] nnet_7.3-17 dbplyr_2.1.1 utf8_1.2.2 janitor_2.1.0 tidyselect_1.1.2 DiceDesign_1.9 munsell_0.5.0 [57] cellranger_1.1.0 tools_4.1.3 cli_3.2.0 generics_0.1.2 processx_3.5.3 fs_1.5.2 future_1.25.0 [64] nlme_3.1-155 tictoc_1.0.1 xml2_1.3.3 compiler_4.1.3 rstudioapi_0.13 curl_4.3.2 slider_0.2.2 [71] reprex_2.0.1 lhs_1.1.5 stringi_1.7.6 ps_1.7.0 lattice_0.20-45 Matrix_1.4-1 urca_1.3-0 [78] vctrs_0.4.1 pillar_1.7.0 lifecycle_1.0.1 furrr_0.3.0 lmtest_0.9-40 data.table_1.14.2 R6_2.5.1 [85] gridExtra_2.3 parallelly_1.31.1 codetools_0.2-18 MASS_7.3-55 assertthat_0.2.1 withr_2.5.0 fracdiff_1.5-1 [92] parallel_4.1.3 hms_1.1.1 quadprog_1.5-8 grid_4.1.3 rpart_4.1.16 timeDate_3043.102 class_7.3-20 [99] snakecase_0.11.0 TTR_0.24.3 pROC_1.18.0
报错复现信息
更新包后运行以下代码触发报错:
wflw_mod_rf <- workflow() %>% add_model( spec = rand_forest( mode = "regression" ) %>% set_engine("ranger") ) %>% add_recipe(recipe_spec %>% update_role(dtemonth, new_role = "indicator")) %>% fit(training(splits)) wflw_mod_xgboost <- workflow() %>% add_model( spec = boost_tree( mode = "regression" ) %>% set_engine("xgboost") ) %>% add_recipe(recipe_spec %>% update_role(dtemonth, new_role = "indicator")) %>% fit(training(splits)) wflw_mod_prophet <- workflow() %>% add_model( spec = prophet_reg( seasonality_daily = FALSE, seasonality_weekly = FALSE, seasonality_yearly = TRUE ) %>% set_engine("prophet") ) %>% add_recipe(recipe_spec) %>% fit(training(splits)) submodels_all_tbl <- modeltime_table( wflw_mod_rf, wflw_mod_xgboost, wflw_mod_prophet ) > submodels_all_tbl %>% modeltime_calibrate(testing(splits), quiet = F) Error: Problem occurred getting predictors from new data. Error in tk_get_timeseries_signature.default(.): No method for class NULL. Error: Problem occurred getting predictors from new data. Error in tk_get_timeseries_signature.default(.): No method for class NULL. ── Model Calibration Failure Report ──────────────────────── # A tibble: 2 × 6 .model_id .model .model_desc .type .calibration_data fail_check <int> <list> <chr> <chr> <list> <lgl> 1 1 <workflow> RANGER NA <lgl [1]> TRUE 2 2 <workflow> XGBOOST NA <lgl [1]> TRUE The following models had errors: - Model 1: Failed Calibration. - Model 2: Failed Calibration. Potential Solution: Check the Error/Warning Messages for clues as to why your model(s) failed calibration. ── End Model Calibration Failure Report ────────────────────
问题原因
该报错是modeltime、timetk版本迭代后的逻辑变更导致:
- 旧版本(modeltime 1.2.0、timetk 2.8.0)不会强制要求ranger、xgboost这类纯机器学习模型的工作流中保留显式标记的时间索引列
- 新版本在校准机器学习类时间序列模型时,会自动提取数据中的时间索引列做时间特征合法性校验,代码中将时间列
dtemonth的角色更新为indicator,导致框架无法识别到合法的时间索引,传入tk_get_timeseries_signature的对象为NULL,最终触发报错 - prophet模型自带内置的时间索引解析逻辑,不需要从recipe中识别时间列,因此可以正常运行
修复方案
- 方案1(推荐):将ranger、xgboost工作流中
dtemonth列的角色显式指定为"index",该角色下的列不会被当作特征输入模型,不会影响原有模型逻辑。修正后的代码示例:
wflw_mod_rf <- workflow() %>% add_model( spec = rand_forest(mode = "regression") %>% set_engine("ranger") ) %>% add_recipe(recipe_spec %>% update_role(dtemonth, new_role = "index")) %>% fit(training(splits))
xgboost工作流做相同修改即可。
- 方案2:如果需要将
dtemonth衍生的时间特征作为模型输入,可在recipe中用step_timeseries_signature()提前生成需要的时间维度特征,再将原始dtemonth列的角色设为"index"即可。 - 临时兼容方案:如果不想修改现有代码,可将
modeltime回退到1.2.0版本、timetk回退到2.8.0版本,即可恢复原有运行逻辑,但不推荐长期使用旧版本。
内容的提问来源于stack exchange,提问作者Jean Paul PG
相关产品推荐
相关产品推荐

