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

集成模型predict()返回行数异常及预测存储合理性问询

caretEnsemble集成模型预测行数异常及单模型预测存储问题

操作步骤

  • 使用caretEnsemble::caretList()在鸢尾花(iris)数据集的10个随机抽取的80%子样本上训练多个模型,剩余20%作为保留集。
  • 使用caretEnsemble::caretEnsemble()对模型列表进行glm加权平均得到集成模型。
  • 用caret::predict()提取各单个模型及集成模型的预测结果,希望存入原iris数据集。

问题

单个模型predict返回结果行数为150(与iris数据集行数一致),但集成模型predict返回280行。

代码示例

# Packages
library(tidyverse)
library(caret)
library(caretEnsemble)

# Seed
set.seed(123)

# Data
datasets::iris %>% 
  select(1:3) -> iris

# Folds for training (80% of iris, 10 resamples)
folds <- createDataPartition(iris$Petal.Length, times = 10, p = 0.8, list = TRUE)

# Train controls
train.control <- trainControl(method = "cv", 
                              index = folds,
                              savePredictions = TRUE)

# List of models (generalized linear model, random forest)
models <- caretList(iris[,1:2], iris[,3], methodList=c("glm", "rf"),
                    trControl = train.control, 
                    tuneLength = 10)

# Option 1: No specific train controls
ens <- caretEnsemble(models)

ens$ens_model$resample %>% nrow() # 25

predict(ens$ens_model) # 280

# Option 2: Train controls same as in caretList
ens.2 <- caretEnsemble(models, trControl = train.control)

ens.2$ens_model$resample %>% nrow() # 10

predict(ens.2$ens_model) # 280

# Compare to individual models
predict(models$glm) # 150

predict(models$rf) # 150

iris$pred_glm <- predict(models$glm)

疑问

  1. 为何集成模型predict()始终返回280行,远超数据集的150行?
  2. 将单个模型的预测结果存入原数据集的方法是否存在严重缺陷、是否符合方法学规范?即是否仅存入了测试集的预测结果,还是意外混入了训练集的预测?

解答

1. 集成模型返回280行预测的原因

caretEnsemble训练的集成模型,是基于基模型交叉验证过程中的out-of-sample预测结果训练的加权模型。当你直接调用predict(ens$ens_model)而不指定newdata参数时,caret默认返回该集成模型在自身训练过程中保存的所有预测记录——也就是基模型在10次CV折叠中所有测试样本的预测结果总和。由于部分样本可能被多次选为测试集,最终总条数为280。

如果需要得到对原始150行iris数据集的预测,必须显式指定newdata参数,示例:

predict(ens$ens_model, newdata = iris[,1:2]) # 返回150行结果

2. 单模型预测存入原数据集的合理性分析

直接用predict(models$glm)得到的150行结果,是用最终训练好的基模型(基于全部150行数据训练的最优模型)对整个数据集的预测,并非仅包含CV测试集的结果——它同时包含了训练集和测试集样本的预测值。

这种做法本身没有“严重缺陷”,但要明确用途:

  • 如果只是需要模型对全量数据的预测结果(比如用于后续分析),是可行的;
  • 如果是要评估模型的泛化能力(比如计算预测误差),绝对不能用这个结果,因为训练集样本的预测会存在过拟合,无法反映模型真实性能。

如果需要每个样本在CV过程中作为测试集时的out-of-sample预测(即“留一”式的测试结果),应该从基模型的pred属性中提取,示例代码:

# 提取glm模型在CV中的所有测试集预测,并匹配到原数据集
cv_preds <- models$glm$pred %>%
  group_by(rowIndex) %>%
  slice_head(n=1) %>% # 若样本多次作为测试集,取第一次结果
  select(rowIndex, pred)

iris <- iris %>%
  mutate(pred_glm_cv = cv_preds$pred[match(row_number(), cv_preds$rowIndex)])

内容的提问来源于stack exchange,提问作者Dr. Fabian Habersack

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 06:47:44