【问题标题】:Missing data and stratified k-fold cross validation of a gbm in RR中gbm的缺失数据和分层k折交叉验证
【发布时间】:2017-02-07 02:11:58
【问题描述】:

我有一个相对较大的美国多个市场房屋销售数据集。对于每个市场,我想建立一个梯度提升回归模型来预测销售价格。我的大多数自变量(特征)都有缺失值,这对于 R 中的 gbm 来说应该没问题。

caret 中的gbm 算法要求您指定超参数的值(n.treesshrinkageinteraction.depthn.minobsinnode 等)。我想结合交叉验证进行网格搜索以选择最佳超参数集:

# -------- A function to drop variables that are more than 80% missing or have no variance
Drop_Useless_Vars <- function(datan) {
  n = nrow(datan)
  p = ncol(datan)
  na = is.na(datan)
  n_na = apply(X = na, MARGIN = 2, FUN = sum)
  n_unique = apply(X = datan, MARGIN = 2, function(x) length(na.omit((unique(x)))))
  return(as.data.frame(datan[, -which(n_na > 0.8*n | n_unique < 2)]))
}

# -------- load libraries
library(gbm)
library(caret)

# -------- prepare training scheme
control = trainControl(method = "cv", number = 5)

# -------- design the parameter tuning grid 
grid = expand.grid(n.trees = 10000, 
                   interaction.depth = seq(2, 10, 1), 
                   n.minobsinnode = c(3, 4, 5), 
                   shrinkage = c(0.1, 0.01, 0.001))

# -------- tune the parameters
tuner = train(log(saleprice) ~ ., data = Drop_Useless_Vars(df), method = "gbm", distribution = "gaussian",
              trControl = control, verbose = FALSE, tuneGrid = grid, metric = "RMSE")

# -------- get the best combo
n_trees = tuner$bestTune$n.trees
interaction_depth = tuner$bestTune$interaction.depth
shrinkage = tuner$bestTune$shrinkage
n_minobsinnode = tuner$bestTune$n.minobsinnode

上面的代码工作正常,除了一些缺失值更频繁的市场。我收到如下所示的错误:

Error in checkForRemoteErrors(val) : 
  4 nodes produced errors; first error: variable 26: assessor_full_baths has only missing values.

assessor_full_baths 是我模型中的功能之一。所以发生的情况是,当算法对数据进行采样以进行交叉验证时,一个或多个折叠的变量完全缺失。

如何对caret 使用的抽样方案进行分层?也就是说,我怎样才能强制每个折叠对于缺失值具有相同的分布?另外,你们知道如何让gbm 函数忽略完全丢失的变量而不告诉它它们是哪些变量吗?

如果您能提供任何帮助,我将不胜感激。

【问题讨论】:

  • 为什么超参数是“所谓的”?该算法如何仅在 1 折交叉验证中排除具有所有缺失值的特征?
  • 我的一位老教授在谈论贝叶斯设置中的超参数时经常说“所谓的”,我想它已经卡在我的脑海里了。另外,我读了一篇论文,其中这些参数被称为正则化参数,这对我来说更有意义。

标签: r missing-data cross-validation gbm


【解决方案1】:

我认为你需要退后一步,思考如何正确处理数据并拟合模型。

您的最终建模数据集不应该有任何缺失值,更不用说太多缺失值,以至于 CV 折叠中 100% 缺失特征 (!)。

相反,做一些数据清理和特征工程:

  • 您可以将 NA 作为因子水平添加到因子变量中
  • 您可以在大多数其他情况下估算缺失值
  • 如果某个特征的缺失率很高,那么您可能需要排除它,或者
  • 如果它不是随机丢失的,并且您可以通过它丢失/存在的事实了解到许多信息,您可以创建一个或几个指示变量来指示原始特征是否丢失和/或它是否包含一定程度的兴趣。

如果您不想估算丢失的数据,那么您应该使用提到的其他策略。缺失节点与编码 NA 级别不同。缺失节点仅意味着树将给出与数据缺失拆分之前相同的预测(请参阅R gbm handling of missing values)。您永远不应该在具有高缺失值的特征上构建模型,并且在具有任何缺失值的数据上构建模型根本不是一个好习惯。准备数据集时应该清理这些。

话虽如此,您仍然可以估算 MNAR 数据。有大量的策略,可以追溯到 70 年代赫克曼和鲁宾的工作。很多人使用mice()绘制指标方法

这可能会有所帮助:http://stefvanbuuren.nl/mi/docs/mnar.pdf

【讨论】:

  • 我不想估算缺失值,因为没有证据表明缺失是随机的。此外,我的最终目标是使用这些模型来预测大型数据集(超过 30GB)的价格,我不打算估算那么大的数据集(至少目前如此)。最后,据我了解,gbm 对象中单个树中的每个拆分都会产生 3 个节点:左节点、右节点和缺失节点。也就是说,它将缺失值视为一个单独的类别。这不是实现了您的提议(即为缺失创建指标变量)吗?谢谢
  • 如果您不想估算丢失的数据,那么您应该使用提到的其他策略。缺失节点与编码 NA 级别不同。缺失节点仅意味着树将给出与数据缺失拆分之前相同的预测(请参阅stackoverflow.com/questions/14718648/…)。您永远不应该在具有高缺失值的特征上构建模型,并且在具有任何缺失值的数据上构建模型根本不是一个好习惯。准备数据集时应该清理这些。
  • 话虽如此,您仍然可以估算 MNAR 数据。有大量的策略,可以追溯到 70 年代赫克曼和鲁宾的工作。很多人使用mice 和绘制指标的方法。这可能会有所帮助:stefvanbuuren.nl/mi/docs/mnar.pdf
  • 我过去使用过mice,可能会在这里再次使用它,但我的问题不是缺少数据处理。如果您的 CV 的特定折叠最终以只有一个类别的分类变量结束,gbm 函数也会失败。例如,假设 Xj 是可以采用以下三个类别之一的属性类型:Single Family、Condo 或 Other。如果 90% 的数据是单身家庭,那么您很可能会以仅包含该类别的折叠结束,这也会导致错误。我想做的是将caret在做CV时使用的抽样分层。
【解决方案2】:

您可以使用caret::createFolds 自己创建 CV 折叠。您只需提供与结果不同的y 变量(即-saleprice)。您需要根据您的分层变量定义一个新变量...参见?interaction。然后可以将其传递给caret::trainControl

例如:

library(caret)
y2 <- interaction(df$x1, df$x2)
cv_folds <- createFolds(y2, k= 5)
control = trainControl(index= cv_folds, method= "cv", number= 5)
...

或者你可以避免使用caret,而写你自己的stratified sampling code

也就是说,我同意@Hack-R 所说的关于缺失值和插补特征的实际使用的大部分内容。

【讨论】:

    猜你喜欢
    • 2018-08-29
    • 2020-07-30
    • 2016-11-15
    • 2018-05-03
    • 2013-05-03
    • 2017-01-11
    • 2018-06-22
    • 2019-12-18
    • 2016-01-15
    相关资源
    最近更新 更多