如何用ranger包计算随机森林中MSE最低的树的数量?
问题描述
我正在遵循一个随机森林示例,想要把randomForest包的代码转换成ranger包的等价代码。原randomForest代码如下:
# default RF model m1 <- randomForest( formula = Sale_Price ~ ., data = ames_train ) # number of trees with lowest MSE btree <- which.min(m1$mse)
使用ranger包时,无法直接获取MSE最低的树的数量,该如何计算并把结果存入btree变量?
我的测试代码如下:
library(rsample) # data splitting library(randomForest) # basic implementation library(ranger) # a faster implementation of randomForest set.seed(123) ames_split <- initial_split(AmesHousing::make_ames(), prop = .7) ames_train <- training(ames_split) ames_test <- testing(ames_split) # for reproduciblity set.seed(123) # default RF model m1 <- randomForest( formula = Sale_Price ~ ., data = ames_train ) # the equivalent in ranger m1 <- ranger( formula = Sale_Price ~ ., data = ames_train ) # number of trees with lowest MSE (randomForest package) btree <- which.min(m1$mse)
根据ranger文档说明:
prediction.error: 整体袋外预测误差。分类任务为准确率(错误分类观测的比例),概率估计为Brier分数,回归任务为均方误差(MSE),生存分析为1减去Harrell's C-index。
我尝试了以下代码,但结果明显不对:
m1 <- ranger( formula = Sale_Price ~ ., data = ames_train ) # number of trees with highest r2 btree = which.max(m1$prediction.error) print(btree)
输出结果:
[1] 1
解决方案
问题核心是:ranger默认仅返回最终的整体OOB MSE,不会保存每棵树逐步累积的MSE序列。要实现和randomForest相同的功能,需要在训练时开启相关参数,手动计算每增加一棵树后的累积OOB MSE。
具体实现代码
set.seed(123) # 训练ranger模型时开启袋内样本记录,树数量与randomForest默认一致(500) m1_ranger <- ranger( formula = Sale_Price ~ ., data = ames_train, keep.inbag = TRUE, predict.all = TRUE, num.trees = 500 ) # 提取每棵树的预测值、袋内样本标记,以及真实房价 tree_preds <- m1_ranger$predictions inbag_counts <- m1_ranger$inbag.counts actual_prices <- ames_train$Sale_Price # 初始化累积预测和、OOB样本计数、MSE存储向量 cumulative_pred_sum <- numeric(nrow(ames_train)) oob_tree_count <- numeric(nrow(ames_train)) cumulative_mse <- numeric(500) for (k in 1:500) { # 获取当前树的OOB样本索引 oob_idx <- inbag_counts[[k]] == 0 # 更新OOB样本的预测和与计数 cumulative_pred_sum[oob_idx] <- cumulative_pred_sum[oob_idx] + tree_preds[oob_idx, k] oob_tree_count[oob_idx] <- oob_tree_count[oob_idx] + 1 # 计算当前累积的OOB预测均值(避免除以0) avg_pred <- ifelse(oob_tree_count > 0, cumulative_pred_sum / oob_tree_count, NA) # 计算当前累积MSE cumulative_mse[k] <- mean((actual_prices - avg_pred)^2, na.rm = TRUE) } # 找到MSE最小的树数量 btree <- which.min(cumulative_mse) print(btree)
关键说明
keep.inbag = TRUE:让ranger保存每棵树的袋内样本计数,用于识别OOB样本predict.all = TRUE:返回每个样本在每棵树上的预测值,用于逐步累积计算- 循环中逐棵树更新OOB样本的预测均值,计算对应MSE,最终通过
which.min找到最优树数量
内容的提问来源于stack exchange,提问作者Nikos
相关产品推荐
相关产品推荐

