丢失数据并对R中的gbm进行分层k折交叉验证

时间:2016-09-28 22:30:17

标签: r missing-data cross-validation gbm

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

gbm中的caret算法要求您指定超参数的值(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函数忽略完全缺失的变量而不告诉我们它们是哪些吗?

我将非常感谢您提供的任何帮助。

2 个答案:

答案 0 :(得分:0)

我认为您需要退一步思考如何正确处理数据并使其适合模型。

您的最终建模数据集不应该有任何缺失值,更不用说如此多的缺失值,这些特征在CV折叠中100%缺失(!)。

相反,做一些数据清理和功能工程:

  • 您可以将NA作为因子级别添加到因子变量
  • 您可以在大多数其他情况下估算缺失值
  • 如果某项功能缺失率较高,则可能需要将其排除,或
  • 如果它没有随机丢失,并且有许多信息你可以通过它丢失/存在的事实来学习,你可以创建一个或几个指示变量,指示原始特征是否缺失和/或是否包含一定程度的兴趣。

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

话虽如此,您仍然可以归咎于MNAR数据。有很多策略可以追溯到70年代Heckman和Rubin的工作。很多人使用mice()绘制的指标方法

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

答案 1 :(得分:0)

您可以使用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所说的关于缺失值和插补的特征的实际使用的大部分内容。