You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

合并随机森林模型后,有效绘制袋外误差(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误差,我们需要手动计算每增加一棵树时的累计误差:

  1. 收集所有树的OOB预测结果:遍历每个子模型的每棵树,获取它们对各自OOB样本的预测值。
  2. 累计投票/均值:对于每棵树(从1到68),用前k棵树的预测结果对对应OOB样本计算多数投票(分类)或均值(回归)。
  3. 计算误差:对比预测结果和真实标签,得到每一步的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 06:28:14