我正在尝试用 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 并获得我需要的分割,还是我必须手动分割所有数据?
如果我理解正确,您的目标是创建以日期为块的块时间序列交叉验证。
一种方法是在唯一日期上使用
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)