使用Tidymodels调优rpart泊松决策树时公式报错问题
解决Tidymodels调优泊松决策树时的公式解析错误
问题重现
我用rpart包实现了泊松决策树,随后用Tidymodels复现固定超参数的拟合,结果完全一致。但尝试用Tidymodels进行超参数调优时,所有模型训练失败,报错信息如下:
Error in str2lang(x): :1:32: unexpected symbol
1: cbind(cbind(exposure, n_claims).exposure
^
相关代码见原提问的rpart实现、Tidymodels固定参数拟合及调优代码。
问题原因
Tidymodels的workflow在调优过程中会对公式做内部解析处理,当直接使用cbind(exposure, n_claims) ~ ...这种多响应变量格式时,解析逻辑会出现重复包裹响应变量的错误,把本应是分隔符的.误识别为无效符号,导致公式语法错误。而直接调用fit()时没有这个问题,是因为此时公式会直接传递给rpart引擎,没有经过调优模块的额外解析。
解决方案
避免在add_formula()中直接使用cbind,提前构造好适合rpart泊松模型的响应变量矩阵,让Tidymodels能正确传递给底层引擎。
方案1:提前构造响应变量列
在训练数据中先创建响应变量的矩阵列,再在公式中引用该列:
# 提前构造响应变量矩阵 dat_train <- dat_train %>% mutate(response = cbind(exposure, n_claims)) # 模型规格不变 tree_spec <- decision_tree( cost_complexity = tune(), tree_depth = tune(), min_n = tune()) %>% set_engine("rpart", method = "poisson") %>% set_mode("regression") # 更新workflow的公式 tree_wf <- workflow() %>% add_model(tree_spec) %>% add_formula(response ~ is_renewed + gender + age_group + cluster_k3 + insured_amount) # 后续调优代码保持不变 tree_grid <- grid_latin_hypercube(extract_parameter_set_dials(tree_spec), size = 50) doParallel::registerDoParallel() set.seed(345) tree_rs <- tree_wf %>% tune_grid( resamples = folds, grid = tree_grid, metrics = metric_set(yardstick::rmse) )
方案2:使用Recipe处理响应变量
如果更倾向用Tidymodels的recipe体系管理数据预处理,可以这样实现:
# 创建recipe,合并响应变量 tree_rec <- recipe(dat_train) %>% # 标记变量角色 update_role(exposure, n_claims, new_role = "outcome") %>% update_role(is_renewed, gender, age_group, cluster_k3, insured_amount, new_role = "predictor") %>% # 构造rpart所需的响应矩阵 step_mutate(response = cbind(exposure, n_claims), role = "outcome") %>% # 移除原单独的结果列 step_rm(exposure, n_claims) # 模型规格不变 tree_spec <- decision_tree( cost_complexity = tune(), tree_depth = tune(), min_n = tune()) %>% set_engine("rpart", method = "poisson") %>% set_mode("regression") # 使用recipe构建workflow tree_wf <- workflow() %>% add_model(tree_spec) %>% add_recipe(tree_rec) # 后续调优代码保持不变 tree_grid <- grid_latin_hypercube(extract_parameter_set_dials(tree_spec), size = 50) doParallel::registerDoParallel() set.seed(345) tree_rs <- tree_wf %>% tune_grid( resamples = folds, grid = tree_grid, metrics = metric_set(yardstick::rmse) )
说明
两种方案都是通过提前构造好rpart泊松模型所需的响应变量矩阵,避免了Tidymodels调优模块对cbind公式的错误解析,保证调优过程能正常运行。
内容的提问来源于stack exchange,提问作者gabriel chirinos
相关产品推荐
相关产品推荐

