如何调优tidymodels中recipe步骤的自定义参数?
问题原因
- 语法位置错误:你把
digits = tune("digits")写在了step_mutate()的顶级参数位置,step_mutate()会将其识别为你要新增一个名为digits的列,赋值为tune()返回的调用对象,这就是你报错「digits必须为向量而非调用对象」的直接原因。 - 调优规则不符:
tune()仅能标记recipe step本身公开的可调节参数,无法识别嵌套在step内部表达式里的普通函数(如round())参数,所以即使你把digits = tune("digits")放到round()括号内,tune_grid()也检测不到待调参数。
修复方案
你可以通过自定义recipe step的方式将round的digits参数公开为可调节参数,可运行的完整示例如下:
library(tidyverse) library(tidymodels) # 自定义step_round:指定列四舍五入,digits设为可调参数 step_round <- function( recipe, ..., role = NA, trained = FALSE, columns = NULL, digits = 0, skip = FALSE, id = rand_id("round") ) { add_step( recipe, step_round_new( terms = enquos(...), role = role, trained = trained, columns = columns, digits = digits, skip = skip, id = id ) ) } step_round_new <- function(terms, role, trained, columns, digits, skip, id) { step( subclass = "round", terms = terms, role = role, trained = trained, columns = columns, digits = digits, skip = skip, id = id ) } # 定义step预处理逻辑 prep.step_round <- function(x, training, info = NULL, ...) { col_names <- recipes_eval_select(x$terms, training, info) step_round_new( terms = x$terms, role = x$role, trained = TRUE, columns = col_names, digits = x$digits, skip = x$skip, id = x$id ) } # 定义step执行逻辑 bake.step_round <- function(object, new_data, ...) { col_names <- object$columns for (col in col_names) { new_data[[col]] <- round(new_data[[col]], digits = object$digits) } new_data } # 注册可调参数 tunable.step_round <- function(x, ...) { tibble::tibble( name = "digits", call_info = list(list(pkg = "dials", fun = "digits")), source = "recipe", component = "step_round", component_id = x$id ) } # 调整后的recipe,使用自定义step标记digits为可调参数 glmnet_recipe <- recipe(formula = Species ~ Sepal.Length + Petal.Length, data = iris) %>% step_round(Sepal.Length, digits = tune("digits")) %>% step_zv(all_predictors()) %>% step_normalize(all_predictors(), -all_nominal()) glmnet_spec <- multinom_reg(penalty = 0, mixture = 0) %>% set_mode("classification") %>% set_engine("glmnet") glmnet_workflow <- workflow() %>% add_recipe(glmnet_recipe) %>% add_model(glmnet_spec) glmnet_grid <- expand_grid(digits = c(0, 1)) # 运行调优 glmnet_tune <- tune_grid(glmnet_workflow, resamples = vfold_cv(iris), grid = glmnet_grid)
运行上述代码即可正常识别到待调的digits参数,无报错完成调优。
内容的提问来源于stack exchange,提问作者AlbertRapp
相关产品推荐
相关产品推荐

