You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

R语言时间序列模型滚动窗口交叉验证实现正确性与工具问询

问题说明

我生成了如下时间序列数据:

library(forecast)
library(lubridate)

set.seed(123)

weeks <- rep(seq(as.Date("2010-01-01"), as.Date("2023-01-01"), by = "week"), each = 1)
counts <- rpois(length(weeks), lambda = 50)
df <- data.frame(Week = as.character(weeks), Count = counts)

# Convert Week column to Date format
df$Week <- as.Date(df$Week)

# Create a time series object
ts_data <- ts(df$Count, frequency = 52, start = c(year(min(df$Week)), 1))

希望为该数据拟合时间序列模型,并实现滚动窗口交叉验证,验证逻辑为:

  • 基于前60个数据点拟合模型,预测后续5个点并记录误差(RMSE、MAE、MAPE等)
  • 基于前65个数据点拟合模型,预测后续5个点并记录误差
  • 以此类推

我已尝试自行编写代码划分训练/测试块、实现模型训练测试及误差计算,还尝试了矩阵存储多步误差、子循环优化和结果绘图,现询问:

  1. 自己的实现是否正确?
  2. 是否有现成工具包可替代手动实现?

一、自定义实现的正确性检查

要确认你的代码对不对,盯着这几个核心点看就行:

  • 不能有未来数据泄露:滚动窗口必须严格按时间顺序来,训练集的所有数据都得是测试集之前的,绝对不能让模型“看到”未来的数据。
  • 窗口滑动逻辑匹配需求:你设定的是每次训练集加5个点、预测5个点,要确保每次滑动后,训练集的终点和测试集的起点是连续的,不能有间隔或者重叠。
  • 误差计算没毛病:
    • RMSE是预测值和真实值差的平方取均值再开方,别搞反顺序或者漏了开方
    • MAE是绝对差的均值,这个相对简单
    • MAPE要注意分母不能为0,你的计数数据都是非负的,但如果有真实值为0的情况得单独处理,不然会出问题
  • 模型拟合逻辑统一:每次滚动拟合模型时,用的方法(比如auto.arima())和参数要完全一样,不能这次用ARIMA,下次又换ETS,这样误差对比就没意义了。

如果你的代码都满足这些要求,那基本就是正确的。

二、现成工具包替代方案

不用自己写循环,R里有几个专门的工具包可以直接搞定:

1. forecast包的tsCV()函数

你已经在用forecast包了,它自带的tsCV()就是专门做时间序列交叉验证的,直接指定初始训练集大小和预测步长就行:

# 先定义一个预测函数,比如用auto.arima拟合模型再预测
forecast_func <- function(y, h) {
  forecast(auto.arima(y), h = h)
}

# 执行滚动验证:initial=60是初始训练集大小,h=5是每次预测的步数
cv_results <- tsCV(ts_data, forecast_func, h = 5, initial = 60)

# 计算每一步预测的RMSE和MAE
rmse_per_step <- colMeans(sqrt(cv_results^2), na.rm = TRUE)
mae_per_step <- colMeans(abs(cv_results), na.rm = TRUE)

tsCV()会自动按时间顺序滚动窗口,返回的是预测误差矩阵,每行对应一个训练窗口,每列对应一步预测的误差,后续直接统计就行。

2. fable包(tidyverse风格时序工具)

fable是forecast的继任者,配合tsibble用起来更清爽,代码逻辑更直观:

library(fable)
library(tsibble)

# 把数据转换成tsibble格式(专门的时序数据框)
tsibble_data <- df %>% 
  as_tsibble(index = Week)

# 定义滚动窗口规则:初始60个数据,每次滑动5个
rolling_plan <- tsibble_data %>%
  stretch_tsibble(initial = 60, step = 5)

# 一键完成模型拟合、预测和误差计算
cv_results <- rolling_plan %>%
  model(ARIMA(Count)) %>%
  forecast(h = 5) %>%
  accuracy(tsibble_data)

# 直接查看误差结果
print(cv_results)

这个方案输出的是整洁的数据框,后续做可视化或者统计都很方便。

3. caret包(适合机器学习模型的时序验证)

如果你想用机器学习模型做时序预测,caret可以自定义时间序列的重采样方案:

library(caret)

# 创建时间序列切片:初始窗口60,预测步长5
time_slices <- createTimeSlices(1:length(ts_data), initialWindow = 60, horizon = 5, fixedWindow = FALSE)

# 设置训练控制参数
train_control <- trainControl(method = "timeslice", index = time_slices$trainIndex, indexOut = time_slices$testIndex)

# 训练模型(以ARIMA为例,也可以换其他机器学习模型)
model <- train(x = data.frame(idx = 1:length(ts_data)), y = ts_data, 
               method = "arima", trControl = train_control)

# 查看模型的误差结果
print(model$results)

不过caret对纯时序模型的支持不如前面两个工具包灵活,更适合传统机器学习模型的时序验证场景。


内容的提问来源于stack exchange,提问作者stats_noob

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 18:24:59