如何在caret中用虚拟变量按组训练时间序列模型并维持时间切片逻辑
解决方案:通用多组时间序列滚动预测实现
针对你的需求,我们可以通过手动生成训练/测试索引的方式替代timeslice的默认参数设置,这样既可以合并多组数据用虚拟变量建模,又能严格保证每个组的一步超前预测逻辑,而且完全不需要手动调整参数适配组数量。
步骤1:数据预处理与排序
首先生成虚拟变量,同时保留group和period用于后续索引生成,并且必须确保数据按组和时间周期排序,保证时序的正确性:
library(data.table) library(caret) set.seed(503) # 生成原始数据 foo <- data.table(group = rep(LETTERS[1:6], 150), y = rnorm(n = 6 * 150, mean = 5, sd = 2), x1 = rnorm(n = 6 * 150, mean = 5, sd = 10), x2 = rnorm(n = 6 * 150, mean = 25, sd = 10), x3 = rnorm(n = 6 * 150, mean = 50, sd = 10), x4 = rnorm(n = 6 * 150, mean = 0.5, sd = 10), x5 = sample(c(1, 0), size = 6 * 150, replace = T)) foo[, period := 1:.N, by = group] # 生成组虚拟变量,保留group和period用于索引 dat <- cbind(foo, model.matrix(~ group - 1, data = foo)) # 按组+周期排序,确保时序连续 setorder(dat, group, period)
步骤2:自动计算通用参数
我们先提取关键参数,所有计算都基于组数量和单组窗口长度,完全不需要手动硬编码:
n_groups <- length(unique(dat$group)) # 组数量 window_length_per_group <- 115 # 单组训练窗口长度 n_periods_per_group <- max(dat$period) # 单组总周期数 initial_window <- window_length_per_group * n_groups # 初始训练集总大小 n_reps <- n_periods_per_group - window_length_per_group # 滚动预测次数
步骤3:手动生成训练/测试索引
通过循环生成每次滚动的训练集和测试集索引,确保每次测试集都是所有组的下一个周期观测,严格对应一步超前预测:
train_indices <- list() test_indices <- list() for(i in 1:n_reps){ # 训练集:包含所有组的前 (window_length_per_group + i -1) 个周期数据 train_periods <- 1:(window_length_per_group + i - 1) train_indices[[i]] <- which(dat$period %in% train_periods) # 测试集:包含所有组的第 (window_length_per_group + i) 个周期数据 test_period <- window_length_per_group + i test_indices[[i]] <- which(dat$period == test_period) }
步骤4:配置trainControl并训练模型
我们用method = "cv"模式,传入手动生成的索引,这样就能完全控制滚动逻辑:
timecontrol <- trainControl( method = "cv", index = train_indices, indexOut = test_indices, selectionFunction = "best", savePredictions = 'final' ) # 批量训练三个模型 model_list <- list() model_list[["xgbTree"]] <- train( y ~ . - group - period, # 排除原始group和period,用虚拟变量替代 data = dat, method = "xgbTree", trControl = timecontrol ) model_list[["earth"]] <- train( y ~ . - group - period, data = dat, method = "earth", trControl = timecontrol ) model_list[["cubist"]] <- train( y ~ . - group - period, data = dat, method = "cubist", trControl = timecontrol )
为什么这个方案更优?
- 通用性极强:不管组数量是6还是其他数值,只要修改
window_length_per_group,其他参数会自动适配,完全不需要手动调整initialWindow或horizon。 - 严格的时序逻辑:手动生成的索引确保每次测试集都是每个组的下一个周期观测,完美符合一步超前预测的需求。
- 效率更高:不需要循环每个组训练,直接在合并后的数据集上一次性训练,减少代码冗余和计算时间。
注意事项
- 必须保证数据按
group和period排序,否则索引会失效。 - 训练公式中要排除原始的
group和period变量,避免冗余。 - 训练
cubist模型前需要先安装Cubist包:install.packages("Cubist")
内容的提问来源于stack exchange,提问作者Felipe Alvarenga
相关产品推荐
相关产品推荐

