合并随机森林模型后,有效绘制袋外误差(err.rate)的方法问询
解决合并随机森林后绘制OOB误差曲线的问题
我完全理解你的困扰——把大随机森林拆分成子模型合并后,combine()确实会丢掉err.rate这类统计量,因为每个子模型的袋外(OOB)误差是基于各自的训练样本子集计算的,合并后的模型没有现成的统一OOB误差统计。不过我们有两种可行的方法来绘制符合需求的误差曲线:
方法一:近似拼接子模型的err.rate(快速可视化)
如果只是想展示误差随树数量增加的整体趋势,拼接每个子模型的err.rate是一种简单有效的方式。这里的核心是给每个子模型的误差数据加上对应的树数量偏移:
# 假设你的4个子模型分别是rf1, rf2, rf3, rf4(各17棵树) # 提取每个子模型的OOB误差(分类模型取第一列,回归模型取"mse"列) err_data <- list( rf1$err.rate[, 1], rf2$err.rate[, 1], rf3$err.rate[, 1], rf4$err.rate[, 1] ) # 生成对应树数量的x轴序列:1-17, 18-34, 35-51, 52-68 tree_seq <- unlist(lapply(0:3, function(i) (i*17 + 1):((i+1)*17))) # 拼接误差数据 combined_err <- unlist(err_data) # 绘制误差曲线 plot(tree_seq, combined_err, type = "l", lwd = 2, xlab = "Number of Trees", ylab = "OOB Error Rate", main = "Combined Random Forest OOB Error Trend")
这种方法的优点是快速简单,能直观看到每个子模型的误差下降趋势;缺点是它并非严格意义上合并后模型的累计OOB误差——因为第二个子模型的第1棵树的误差是基于它自己的OOB样本,而非合并后前18棵树针对所有样本的OOB误差。
方法二:计算合并模型的真实累计OOB误差(更准确)
如果需要严格准确的合并模型OOB误差,我们需要手动计算每增加一棵树时的累计误差:
- 收集所有树的OOB预测结果:遍历每个子模型的每棵树,获取它们对各自OOB样本的预测值。
- 累计投票/均值:对于每棵树(从1到68),用前k棵树的预测结果对对应OOB样本计算多数投票(分类)或均值(回归)。
- 计算误差:对比预测结果和真实标签,得到每一步的OOB误差。
示例代码框架(分类模型):
# 假设你的训练数据是train_data,标签列是"y" library(randomForest) # 初始化存储所有树的OOB预测和对应样本索引的列表 tree_oob_preds <- list() tree_oob_indices <- list() # 遍历每个子模型 for (rf in list(rf1, rf2, rf3, rf4)) { for (tree_idx in 1:rf$ntree) { # 获取当前树的OOB样本索引 oob_idx <- which(rf$inbag[, tree_idx] == 0) # 获取当前树对OOB样本的预测 pred <- predict(rf, newdata = train_data[oob_idx, ], predict.all = TRUE)$individual[, tree_idx] # 存入列表 tree_oob_preds[[length(tree_oob_preds)+1]] <- pred tree_oob_indices[[length(tree_oob_indices)+1]] <- oob_idx } } # 计算累计误差 cumulative_err <- numeric(68) # 存储每个样本的累计投票结果 sample_votes <- rep(list(integer(0)), nrow(train_data)) for (k in 1:68) { # 更新当前树的样本投票 current_idx <- tree_oob_indices[[k]] current_pred <- tree_oob_preds[[k]] for (i in seq_along(current_idx)) { sample_votes[[current_idx[i]]] <- c(sample_votes[[current_idx[i]]], current_pred[i]) } # 计算当前所有OOB样本的预测结果(多数投票) oob_samples <- which(sapply(sample_votes, length) > 0) pred_y <- sapply(oob_samples, function(x) { votes <- sample_votes[[x]] names(which.max(table(votes))) }) # 计算误差率 true_y <- train_data$y[oob_samples] cumulative_err[k] <- mean(pred_y != true_y) } # 绘制真实的累计误差曲线 plot(1:68, cumulative_err, type = "l", lwd = 2, col = "blue", xlab = "Number of Trees", ylab = "OOB Error Rate", main = "True Combined Random Forest OOB Error Curve")
这种方法能得到最准确的合并模型累计OOB误差,但缺点是对于大数据量来说计算量较大,需要更多的内存和时间。
补充说明
相关讨论中提到过,combine()函数设计时就不会保留err.rate、confusion这类统计量,因为它们依赖于单个模型的训练样本子集。上面两种方法可以根据你的需求选择:追求速度选方法一,追求准确性选方法二。
内容的提问来源于stack exchange,提问作者kneijenhuijs
相关产品推荐
相关产品推荐

