无法运行ANOVA比较Random Forest模型的问题求助
问题:如何用类ANOVA方法比较tidymodels拟合的ranger随机森林模型?
我用tidymodels拟合了两个随机森林模型(带交互项和不带交互项),尝试用anova()对比模型结果时出现错误:
UseMethod("anova") :
no applicable method for 'anova' applied to an object of class "ranger"
示例代码如下:
set.seed(123) iris <- iris %>% mutate( is_versicolor = ifelse(Species == "versicolor", "versicolor", "not_versicolor")) %>% mutate(is_versicolor = factor(is_versicolor, levels = c("versicolor", "not_versicolor"))) iris_split <- initial_split(iris, strata = is_versicolor, prop = 0.8) iris_train <- training(iris_split) iris_test <- testing(iris_split) rec_normal <- recipe(is_versicolor ~ Petal.Width + Species, data = iris_train) rec_interaction <- rec_normal %>% step_interact(~ Petal.Width:starts_with("Species")) iris_model <- rand_forest() %>% set_engine("ranger") %>% set_mode("classification") # normal workflow iris_wf <- workflow() %>% add_model(iris_model) %>% add_recipe(rec_normal) # interaction workflow iris_wf_interaction <- iris_wf %>% update_recipe(rec_interaction) # fit models iris_normal_lf <- last_fit(iris_wf, split = iris_split) iris_inter_lf <- last_fit(iris_wf_interaction, split = iris_split) normalmodel <- iris_normal_lf %>% extract_fit_engine() intermodel <- iris_inter_lf %>% extract_fit_engine() anova(normalmodel, intermodel) %>% tidy()
请问如何运行类ANOVA方法比较这些模型,判断哪个性能显著更优?
解决方案
为什么会报错?
anova()函数是为线性回归、广义线性模型这类参数化模型设计的,ranger随机森林属于非参数集成模型,没有对应的anova()方法实现,因此无法直接使用该函数。需要用针对机器学习模型的性能比较方法。
方法1:查看基础性能指标
先从last_fit结果中提取测试集的性能指标,快速对比模型表现:
# 查看无交互项模型的测试集性能 iris_normal_lf %>% collect_metrics() # 查看带交互项模型的测试集性能 iris_inter_lf %>% collect_metrics()
方法2:McNemar检验(二分类场景适用)
针对二分类问题,McNemar检验可以用来比较两个模型在同一测试集上的预测结果差异是否具有统计显著性:
- 提取两个模型的测试集预测结果:
# 获取预测结果 normal_preds <- iris_normal_lf %>% collect_predictions() inter_preds <- iris_inter_lf %>% collect_predictions() # 合并预测结果,对齐样本 compare_preds <- normal_preds %>% select(.row, truth, normal_pred = .pred_class) %>% left_join(inter_preds %>% select(.row, inter_pred = .pred_class), by = ".row")
- 构建列联表并执行McNemar检验:
# 构建"模型是否预测正确"的列联表 conf_table <- table( normal_correct = compare_preds$normal_pred == compare_preds$truth, inter_correct = compare_preds$inter_pred == compare_preds$truth ) # 执行检验并整理结果 mcnemar.test(conf_table) %>% tidy()
如果检验的p值小于显著性水平(如0.05),说明两个模型的预测正确性存在显著差异。
方法3:Bootstrap重采样估计性能差异
通过bootstrap重采样,可以估计两个模型性能差异的置信区间,判断差异是否显著:
- 生成bootstrap样本并定义拟合函数:
library(rsample) library(purrr) library(yardstick) # 生成1000个bootstrap训练样本 iris_boot <- bootstraps(iris_train, times = 1000) # 定义函数:在单个bootstrap样本上拟合两个模型,返回AUC差异 compare_models <- function(split) { train_data <- analysis(split) val_data <- assessment(split) # 拟合无交互项模型 normal_fit <- workflow(iris_wf) %>% fit(data = train_data) # 拟合带交互项模型 inter_fit <- workflow(iris_wf_interaction) %>% fit(data = train_data) # 计算验证集AUC normal_auc <- roc_auc(val_data, truth = is_versicolor, predict(normal_fit, val_data, type = "prob")$.pred_versicolor)$.estimate inter_auc <- roc_auc(val_data, truth = is_versicolor, predict(inter_fit, val_data, type = "prob")$.pred_versicolor)$.estimate tibble(diff = inter_auc - normal_auc) }
- 运行重采样并计算置信区间:
# 对所有bootstrap样本执行模型比较 boot_results <- iris_boot %>% mutate(perf_diff = map(splits, compare_models)) %>% unnest(perf_diff) # 计算性能差异的均值和95%置信区间 boot_results %>% summarise( mean_diff = mean(diff), lower_ci = quantile(diff, 0.025), upper_ci = quantile(diff, 0.975) )
如果95%置信区间不包含0,说明两个模型的AUC差异具有统计显著性。
内容的提问来源于stack exchange,提问作者Adam_G
相关产品推荐
相关产品推荐

