这个问题与caret中交叉验证内的预处理非常相似;然而,在我正在进行的一个项目中,我只想对19个预测变量中的三个进行PCA。以下是来自caret中交叉验证内的预处理的示例,我将使用这些数据(PimaIndiansDiabetes
)来简化操作(这不是我的项目数据,但概念应该是相同的)。然后我想仅对一组变量进行预处理,即PimaIndiansDiabetes[, c(4,5,6)]。有没有办法做到这一点?
library(caret)library(mlbench)data(PimaIndiansDiabetes)control <- trainControl(method="cv", number=5)p <- preProcess(PimaIndiansDiabetes[, c(4,5,6)], #只对这些列进行操作! method = c("center", "scale", "pca"))pgrid=expand.grid(mtry=c(1,2,3))model <- train(diabetes~., data=PimaIndiansDiabetes, method="rf", preProcess= p, trControl=control, tuneGrid=grid)
但我得到了这个错误:
Error: pre-processing methods are limited to: BoxCox, YeoJohnson, expoTrans, invHyperbolicSine, center, scale, range, knnImpute, bagImpute, medianImpute, pca, ica, spatialSign, ignore, keep, remove, zv, nzv, conditionalX, corr
我尝试这样做的原因是为了将三个变量减少到一个PCA1,并用于预测。在我的项目中,所有三个变量的相关性都超过90%,但我想将它们纳入进来,因为其他研究也使用了这些变量。谢谢。试图避免数据泄漏!
回答:
据我所知,caret无法做到这一点。这可能可以通过recipes来实现。然而,我不使用recipes,但我使用mlr3,所以我将展示如何使用这个包来完成:
library(mlr3)library(mlr3pipelines)library(mlr3learners)library(paradox)library(mlr3tuning)library(mlbench)
从数据中创建任务:
data("PimaIndiansDiabetes")pima_tsk <- TaskClassif$new(id = "Pima", backend = PimaIndiansDiabetes, target = "diabetes")
定义一个名为”slct1″的预处理选择器:
pos1 <- po("select", id = "slct1")
并在其中定义选择器函数:
pos1$param_set$values$selector <- selector_name(colnames(PimaIndiansDiabetes[, 4:6]))
现在定义对所选特征应采取的操作:缩放 -> 选择第一主成分的PCA(param_vals = list(rank. = 1)
)
pos1 %>>% po("scale", id = "scale1") %>>% po("pca", id = "pca1", param_vals = list(rank. = 1)) -> pr1
现在定义一个反向选择器:
pos2 <- po("select", id = "slct2")pos2$param_set$values$selector <- selector_invert(pos1$param_set$values$selector)
定义学习器:
rf_lrn <- po("learner", lrn("classif.ranger")) #ranger是rf的一个更快的版本
将它们组合起来:
gunion(list(pr1, pos2)) %>>% po("featureunion") %>>% rf_lrn -> graph
检查是否看起来正常:
graph$plot(html = TRUE)
将图形转换为学习器:
glrn <- GraphLearner$new(graph)
定义要调整的参数:
ps <- ParamSet$new(list( ParamInt$new("classif.ranger.mtry", lower = 1, upper = 6), ParamInt$new("classif.ranger.num.trees", lower = 100, upper = 1000)))
定义重采样方法:
cv10 <- rsmp("cv", folds = 10)
定义调整方法:
instance <- TuningInstance$new( task = pima_tsk, learner = glrn, resampling = cv10, measures = msr("classif.ce"), param_set = ps, terminator = term("evals", n_evals = 20))set.seed(1)tuner <- TunerRandomSearch$new()tuner$tune(instance)instance$result
有关如何调整保留的主成分数量的更多详细信息,请查看这个答案:R caret: How do I apply separate pca to different dataframes before training?
如果你觉得这很有趣,请查看mlr3book
另外
cor(PimaIndiansDiabetes[, 4:6]) triceps insulin masstriceps 1.0000000 0.4367826 0.3925732insulin 0.4367826 1.0000000 0.1978591mass 0.3925732 0.1978591 1.0000000
并不产生你在问题中提到的结果。