通过独特的日期而不是观察来训练和测试分割

问题描述 投票:0回答:1

我正在尝试用 R 中的随机森林训练一个模型。我有一个时间序列,其中包含每个日期多个股票的信息,并创建了一个非常简化的版本:

Date <- rep(seq(as.Date("2009/01/01"), by = "day", length.out = 100), 10)
Name <- c(rep("Stock A", 100), rep("Stock B",100), rep("Stock C", 100), rep("Stock D", 100), rep("Stock E",100), rep("Stock F",100), rep("Stock G",100), rep("Stock H",100), rep("Stock I", 100), rep("Stock J", 100))
Class <- sample(1:10, 1000, replace=TRUE)

DF <- data.frame(Date, Name, Class)
DF <- DF %>% arrange(Date, Name)

看起来像这样:

        Date   Name    Class
1  2009-01-01  Stock A     5
2  2009-01-01  Stock B     2
3  2009-01-01  Stock C     4
4  2009-01-01  Stock D    10
5  2009-01-01  Stock E     7
6  2009-01-01  Stock F     3
...
11 2009-01-02  Stock A    10
12 2009-01-02  Stock B     8 
13 2009-01-02  Stock C     9

当使用trainControl将数据分割为训练和测试期间时,分割是根据每个观察结果完成的,但我希望根据独特的日期完成分割。到目前为止我所做的是:

timecontrol <- DF %>% group_by(Date) %>% trainControl(
  method            = 'timeslice',
  initialWindow     = 10,
  horizon           = 5,
  skip              = 4,
  fixedWindow       = TRUE,
  returnData        = TRUE, 
  classProbs        = TRUE
)

fitRF <- train(Class ~ ., 
               data = DF,
               method = "ranger",
               tuneGrid = tunegrid,
               na.action = na.omit,
               trControl = timecontrol)

这给了我一个包含 10 个观察值的训练集,然后是 5 个测试观察值。 然而,我希望有一个训练集(和测试..),其中包含 10 天的所有观察结果,这样一个训练集将是 10 天乘以每天的观察次数,并且在时间段之间进行跳跃,以便每个测试周期都基于全新的数据(因此skip=4)。

第一次训练/测试分割应该是训练=数据集的前 10 天,测试=接下来的 5 天,然后第二次训练/测试分割应该是测试集编号 2 是第一个测试集之后的 5 天测试集。

与我上面显示的数据集不同,我的数据集每天包含不同数量的观察结果。我的数据集包含 417497 个观察值,但只有 2482 个唯一日期,因此能够根据“分组”日期进行训练/测试划分会产生很大的差异。

有什么方法可以使用 trainControl 并获得我需要的分割,还是我必须手动分割所有数据?

r machine-learning time-series partitioning r-caret
1个回答
0
投票

如果我理解正确,您的目标是创建以日期为块的块时间序列交叉验证。

一种方法是在唯一日期上使用

createTimeSlices
(按顺序),然后将其映射回您的数据集:

dates <- unique(DF$Date) #already in order


slices <- createTimeSlices(dates,
                           initialWindow = 10,
                           horizon = 5,
                           skip = 4,
                           fixedWindow = TRUE)

将这些切片映射回原始数据中的索引:

slices <- lapply(slices, function(x){
  lapply(x, function(k){
    DF %>%
      mutate(n = 1:n()) %>%
      filter(Date %in% dates[k]) %>%
      pull(n)
  })
})

所以第一个列车数据帧将是:

DF[slices$train[[1]],]

测试数据为:

DF[slices$test[[1]],]

现在定义 trainControl 时使用获得的训练和测试索引:

tr <- trainControl(returnData = TRUE, 
                   classProbs = TRUE,
                   index = slices$train,
                   indexOut = slices$test)

数据:

Date <- rep(seq(as.Date("2009/01/01"), by = "day", length.out = 100), 10)
Name <- c(rep("Stock A", 100), rep("Stock B",100), rep("Stock C", 100), rep("Stock D", 100), rep("Stock E",100), rep("Stock F",100), rep("Stock G",100), rep("Stock H",100), rep("Stock I", 100), rep("Stock J", 100))
Class <- sample(1:10, 1000, replace=TRUE)

DF <- data.frame(Date, Name, Class)
DF <- DF %>% arrange(Date, Name)
© www.soinside.com 2019 - 2024. All rights reserved.