在 R 中按唯一日期而不是观察进行训练和测试拆分
Train and test splits by unique dates, not observations, in R
我正在尝试用 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)。
第一个 training/test 拆分应该是训练 = 数据集的第一个唯一天数,测试 = 接下来的 5 个唯一天数,然后第二个 training/test 拆分应该是测试集编号 2是第一次测试集后的 5 天。
与我上面显示的数据集不同,我的数据集每天包含不同数量的观察结果。我的数据集包含 417497 个观测值,但只有 2482 个唯一日期,因此能够根据 "grouped" 日期进行 training/testing 拆分会产生很大的不同。
有什么方法可以使用 trainControl 并获得我需要的拆分,还是我必须手动拆分所有数据?
如果我理解正确的话,您的目标是创建以日期为块的块时间序列交叉验证。
一种方法是对唯一日期(按顺序)使用 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)
我正在尝试用 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)。
第一个 training/test 拆分应该是训练 = 数据集的第一个唯一天数,测试 = 接下来的 5 个唯一天数,然后第二个 training/test 拆分应该是测试集编号 2是第一次测试集后的 5 天。
与我上面显示的数据集不同,我的数据集每天包含不同数量的观察结果。我的数据集包含 417497 个观测值,但只有 2482 个唯一日期,因此能够根据 "grouped" 日期进行 training/testing 拆分会产生很大的不同。
有什么方法可以使用 trainControl 并获得我需要的拆分,还是我必须手动拆分所有数据?
如果我理解正确的话,您的目标是创建以日期为块的块时间序列交叉验证。
一种方法是对唯一日期(按顺序)使用 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)