【问题标题】:Stratified k-fold Cross Validation in RR中的分层k-fold交叉验证
【发布时间】:2020-07-30 10:25:24
【问题描述】:

假设我有一个多类数据集(例如鸢尾花)。我想执行分层的 10 倍 CV 来测试模型性能。我在包splitstackchange 中找到了一个名为stratified 的函数,它根据我想要的数据的比例给了我一个分层的折叠。因此,如果我想要一个测试折叠,它将是 0.1 个数据行。

#One Fold
library(splitstackchange)
stratified(iris,c("Species"),0.1)

我想知道如何在 10 倍循环中实现此功能或任何其他形式的分层 cv。我无法破解它背后的逻辑。这里我包括一个可重现的例子。

    library(splitstackshape)
    data=iris
    names(data)[ncol(data)]=c("Y")
    nFolds=10

    for (i in 1:nFolds){
      testing=stratified(data,c("Y"),0.1,keep.rownames=TRUE)
      rn=testing$rn
      testing=testing[,-"rn"]
      row.names(testing)=rn
      trainingRows=setdiff(1:nrow(data),as.numeric(row.names(testing)))
      training=data[trainingRows,]
      names(training)[ncol(training)]="Y"
    }

【问题讨论】:

  • 你看过caret吗?它可以很容易地做到这一点。
  • 如果我的回答对你有帮助,请考虑采纳。谢谢

标签: r data-mining cross-validation sampling multiclass-classification


【解决方案1】:

对 n 倍简历使用 caret 包。我会建议 this 插入符号上非常有用的链接。

许多人发现以下解决方案很有用。

library(tidyverse)
library(splitstackshape)
library(caret)
library(randomForest)

data=iris

## split data into train and test using stratified sampling
d <- rownames_to_column(data, var = "id") %>% mutate_at(vars(id), as.integer)
training <- d %>% stratified(., group = "Species", size = 0.90)
dim(training)

## proportion check
prop.table(table(training$Species)) 

testing <- d[-training$id, ]
dim(testing)
prop.table(table(testing$Species)) 


## Modelling

set.seed(123)

tControl <- trainControl(
  method = "cv", #cross validation
  number = 10, #10 folds
  search = "random" #auto hyperparameter selection
)


trRf <- train(
  Species ~ ., #formulae
  data = training[,-1], #data without id field
  method = "rf", # random forest model
  trControl = tControl # train control from previous step.
)

【讨论】:

    【解决方案2】:

    已经很晚了,但我希望我能帮助别人。 示例代码对我有帮助:

    library(splitstackshape)
    
    
    dat1 <- data.frame(ID = 1:100,
                  A = sample(c("AA", "BB", "CC", "DD", "EE"), 100, replace = TRUE),
                  B = rnorm(100), C = abs(round(rnorm(100), digits=1)),
                  D = sample(c("CA", "NY", "TX"), 100, replace = TRUE),
                  E = sample(c("M", "F"), 100, replace = TRUE))
    
    
    
    flds=list()
    dat=dat1
    
    for(i in 1:10){
      j=10-(i-1)
      if(j>1){
      a=stratified(dat, c("E", "D"), size = 1/j)
      flds[[i]]=a$ID
      dat=dat%>%filter(ID %in% setdiff(dat$ID,a$ID))
      } else{
      flds[[i]]=dat$ID  
      }
    }
    

    【讨论】:

    • 感谢分享!我最终使用了列表,就像你过去在我的最终代码中所做的那样,它起作用了。
    猜你喜欢
    • 2016-10-21
    • 2018-09-11
    • 2019-02-19
    • 1970-01-01
    • 2011-10-01
    • 2020-10-25
    • 1970-01-01
    • 1970-01-01
    • 2015-09-26
    相关资源
    最近更新 更多