我在美国几个市场的房屋销售数据集相对较大。对于每个市场,我想建立一个Gradient Boosting回归模型来预测销售价格。我的大多数自变量(特征)都缺少值,这对于R中的gbm
来说应该没问题。
gbm
中的caret
算法要求您指定超参数的值(n.trees
,shrinkage
,interaction.depth
,n.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
函数忽略完全缺失的变量而不告诉我们它们是哪些吗?
我将非常感谢您提供的任何帮助。
答案 0 :(得分:0)
我认为您需要退一步思考如何正确处理数据并使其适合模型。
您的最终建模数据集不应该有任何缺失值,更不用说如此多的缺失值,这些特征在CV折叠中100%缺失(!)。
相反,做一些数据清理和功能工程:
如果您不想归档丢失的数据,那么您应该使用提到的其他策略。丢失的节点与编码NA级别不同。丢失的节点仅意味着树将提供与缺少数据的拆分之前相同的预测(请参阅R gbm handling of missing values)。您永远不应该在具有高缺失的特征上构建模型,并且在具有任何缺失值的数据上构建模型根本不是一个好习惯。准备数据集时应清除这些内容。
话虽如此,您仍然可以归咎于MNAR数据。有很多策略可以追溯到70年代Heckman和Rubin的工作。很多人使用mice()
和绘制的指标方法。
答案 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所说的关于缺失值和插补的特征的实际使用的大部分内容。