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
错误原因分析
- 长度不匹配:
val <- df[i:(i+1), ]取了两行数据,val$Count是长度为2的向量,但forecast(model, h=1)只生成1个预测值,两者相减时长度不匹配。 - 未定义变量:循环中使用的
train_end和n未提前定义,会导致循环起始位置错误。 - 冗余操作:循环内每次重新从原始数据截取
train <- df[1:(i-1), ],后续train$Count <- c(train$Count, val$Count[1])属于冗余操作,不会影响下一次循环的训练集。 - 误差计算逻辑错误:单个预测点的误差不需要用
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
相关产品推荐
相关产品推荐

