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

R语言时间序列LOOCV报错:时间序列/向量长度不匹配及修正咨询

时间序列交叉验证代码错误修复与方法验证

问题背景

数据集生成代码:

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)

目标是对数据拟合时间序列模型并执行交叉验证,步骤为:

  • 按时间顺序用70%的数据拟合模型
  • 预测下一个点(步长h=1)
  • 记录预测误差
  • 重复滚动预测剩余30%数据
  • 计算平均RMSE、MAE

编写的初始化代码:

# Split data into training and test sets
train_size <- floor(0.7 * nrow(df))
train <- df[1:train_size, ]
test <- df[(train_size + 1):nrow(df), ]

# Fit ARIMA model to training data
model <- auto.arima(train$Count)

# Initialize vector to store prediction errors
errors <- vector("numeric", length = nrow(test))

rmse_vec <- numeric()
mae_vec <- numeric()

循环代码:

# Loop over test set
for (i in seq(train_end+1, n)) {
    
    # Split data into training and validation sets
    train <- df[1:(i-1), ]
    val <- df[i:(i+1), ]
    
    # Fit ARIMA model to training data
    model <- auto.arima(train$Count)
    
    # Forecast one step ahead using the model and record error
    fc <- forecast(model, h = 1)
    error <- val$Count - fc$mean
    
    # Record RMSE and MAE
    rmse_vec[i - train_end - 1] <- sqrt(mean(error^2))
    mae_vec[i - train_end - 1] <- mean(abs(error))
    
    # Update training data with actual count
    train$Count <- c(train$Count, val$Count[1])
}

# Compute mean RMSE and MAE
mean_rmse <- mean(rmse_vec)
mean_mae <- mean(mae_vec)

运行时出现错误:

Error in `-.default`(val$Count, fc$mean) : 
  time-series/vector length mismatch

错误原因分析

  1. 长度不匹配:val <- df[i:(i+1), ]取了两行数据,val$Count是长度为2的向量,但forecast(model, h=1)只生成1个预测值,两者相减时长度不匹配。
  2. 未定义变量:循环中使用的train_end和n未提前定义,会导致循环起始位置错误。
  3. 冗余操作:循环内每次重新从原始数据截取train <- df[1:(i-1), ],后续train$Count <- c(train$Count, val$Count[1])属于冗余操作,不会影响下一次循环的训练集。
  4. 误差计算逻辑错误:单个预测点的误差不需要用mean()计算RMSE/MAE,直接用单个误差值即可,后续再基于所有误差计算整体的RMSE和MAE。

修复后的代码

# 初始化核心变量
train_size <- floor(0.7 * nrow(df))
train_end <- train_size
n <- nrow(df)
errors <- numeric(n - train_end)  # 存储每个预测点的误差

# 滚动预测循环
for (i in (train_end + 1):n) {
    # 截取训练集(到当前点的前一个)和验证点(当前点)
    train <- df[1:(i-1), ]
    val <- df[i, ]
    
    # 拟合ARIMA模型
    model <- auto.arima(train$Count)
    
    # 1步预测并计算误差
    fc <- forecast(model, h = 1)
    error <- val$Count - as.numeric(fc$mean)
    
    # 存储误差
    errors[i - train_end] <- error
}

# 计算整体RMSE和MAE
mean_rmse <- sqrt(mean(errors^2))
mean_mae <- mean(abs(errors))

# 输出结果
cat("平均RMSE:", mean_rmse, "\n")
cat("平均MAE:", mean_mae, "\n")

关于时间序列交叉验证方法的说明

你当前实现的是滚动原点交叉验证(Rolling Origin Cross-Validation),这是时间序列预测中常用的验证方法,符合你设定的"从70%数据开始滚动预测剩余30%"的需求。

而严格意义上的LOOCV(留一交叉验证)是指每次仅保留一个样本作为测试集,用其余所有样本训练模型,循环遍历所有样本。但这种方法在时间序列场景中很少使用,因为它忽略了时间序列的顺序依赖性(会用未来数据训练模型预测过去),不符合时间序列预测的实际逻辑。如果你的目标是严格的LOOCV,需要调整循环逻辑,但不建议在时间序列任务中使用。


内容的提问来源于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.29 14:53:28