【问题标题】:Stratifying multiple columns for cross-validation对多列进行分层以进行交叉验证
【发布时间】:2018-11-23 07:23:58
【问题描述】:

我见过很多方法可以通过单个变量对样本进行分层以用于交叉验证。 caret 包通过 createFolds() 函数很好地做到了这一点。默认情况下,caret 似乎会进行分区,使得每个折叠都具有大致相同的目标事件率。

我想做的是按目标速率和时间进行分层。我找到了一个可以部分执行此操作的函数,它是 splitstackshape 包并使用 stratified() 函数。该函数的问题在于它返回单个样本,它不会在给定条件下将数据分成 k 个组。

这里有一些要重现的虚拟数据。

set.seed(123)

time = rep(seq(1:10),100)
target = rbinom(n=100, size=1, prob=0.3)

data = as.data.frame(cbind(time,target))

table(data$time,data$target)

      0  1
  1  60 40
  2  80 20
  3  80 20
  4  60 40
  5  80 20
  6  80 20
  7  60 40
  8  60 40
  9  70 30
  10 80 20

如您所见,目标事件发生率随时间变化。在时间 1 中为 40%,在时间 2 中为 20%,等等。我想在创建用于交叉验证的折叠时保留它。如果我理解正确,插入符号将按整体事件率进行划分。

table(data$target)

  0   1 
710 290 

这个约 30% 的比率将总体上保留,但随着时间的推移目标事件率不会。

我们可以得到一个这样的样本:

library(splitstackshape)
train.index <- stratified(data,c("target","time"),size=.2)

我需要再重复 4 次以进行 5 倍交叉验证,并且需要这样做,以便一旦分配了一行,就不能再次分配它。我觉得应该已经为此设计了一个功能。有什么想法吗?

【问题讨论】:

    标签: r partitioning cross-validation r-caret


    【解决方案1】:

    我知道这篇文章很旧,但我也遇到了同样的问题,我找不到其他解决方案。如果其他人需要答案,这是我正在实施的解决方案。

    library(data.table)
    mystratified <- function(indt, group, NUM_FOLDS) {
    
      indt <- setDT(copy(indt))
    
      if (is.numeric(group)) 
          group <- names(indt)[group]
    
      temp_grp <- temp_ind <- NULL
      indt[, `:=`(temp_ind, .I)]
      indt[, `:=`(temp_grp, do.call(paste, .SD)), .SDcols = group]
    
      samp_sizes <- indt[, .N, by = group]
      samp_sizes[, `:=`(temp_grp, do.call(paste, .SD)), .SDcols = group]
    
      inds <- split(indt$temp_ind, indt$temp_grp)[samp_sizes$temp_grp]
    
      z = unlist(inds,use.names=F)
      model_folds <- suppressWarnings(split(z, 1:NUM_FOLDS))
    
    }
    

    这基本上是对splitstackshape::stratified 的重写。它的工作原理如下,为每个折叠提供一个验证索引列表作为输出。

    myfolds = mystratified(indt = data, group = colnames(data), NUM_FOLDS = 5)
    
    str(myfolds)
    
    List of 5
     $ 1: int [1:200] 1 91 181 261 351 441 501 591 681 761 ...
     $ 2: int [1:200] 41 101 191 281 361 451 541 601 691 781 ...
     $ 3: int [1:200] 51 141 201 291 381 461 551 641 701 791 ...
     $ 4: int [1:200] 61 151 241 301 391 481 561 651 741 801 ...
     $ 5: int [1:200] 81 161 251 341 401 491 581 661 751 841 ...
    

    因此,例如,每个折叠的训练和验证数据是:

    # first fold
    train = data[-myfolds[[1]],]
    valid = data[myfolds[[1]],]
    
    # second fold
    train = data[-myfolds[[2]],]
    valid = data[myfolds[[2]],]
    
    # etc...
    

    【讨论】:

      猜你喜欢
      • 2019-04-20
      • 2018-01-06
      • 2021-08-12
      • 2014-10-02
      • 1970-01-01
      • 2015-06-11
      • 2020-07-13
      • 2019-09-06
      • 2017-04-21
      相关资源
      最近更新 更多