基于R语言neuralnet包构建的股价预测神经网络是否过拟合?
分析股价预测模型97-99%准确率的疑虑:是否过拟合?
首先,你的疑虑非常合理——股价预测属于典型的强噪声、非线性时间序列问题,通常很难达到这么高的准确率,大概率是过拟合或者评估方式的误导,咱们一步步拆解问题:
一、先排查准确率计算的合理性
你的准确率计算方式是 1 - abs(mean(deviation)),其中 deviation = abs((actual-predicted)/actual),这个指标很容易因为股价本身的特性产生“虚高”的准确率:
- 假设股价每天的波动幅度很小(比如单日涨跌不超过2%),哪怕预测值和实际值有小幅偏差,偏差率也会很低,最终准确率就会显得极高,但这种“高准确率”对实际交易毫无意义——你无法通过这种预测判断涨跌方向或者获取收益。
- 建议替换成更贴合时间序列预测的评估指标,比如:
方向准确率能直接反映模型对股价涨跌趋势的判断能力,这才是股价预测的核心价值。# 计算RMSE(均方根误差) rmse <- sqrt(mean((actual - predicted)^2)) # 计算MAE(平均绝对误差) mae <- mean(abs(actual - predicted)) # 计算涨跌方向准确率(更有实际意义) actual_dir <- sign(diff(actual)) pred_dir <- sign(diff(predicted)) dir_accuracy <- mean(actual_dir == pred_dir, na.rm = TRUE)
二、验证是否真的过拟合
过拟合的核心特征是训练集表现远优于测试集,你可以做以下验证:
对比训练集和测试集的误差
用同样的方式计算训练集的准确率/误差:# 对训练集做预测 nn_pred_train <- compute(nn_model, nn_df_train) results_train <- data.frame(actual = nn_df_train$GSPC.Close, prediction = nn_pred_train$net.result) # 反归一化 predicted_train = results_train$prediction * abs(diff(range(nn_org$GSPC.Close))) + min(nn_org$GSPC.Close) actual_train = results_train$actual * abs(diff(range(nn_org$GSPC.Close))) + min(nn_org$GSPC.Close) # 计算训练集偏差率和准确率 deviation_train= abs((actual_train-predicted_train)/actual_train) accuracy_train=1-abs(mean(deviation_train))如果
accuracy_train接近100%,而测试集准确率是97-99%,那可能不是严重过拟合;但如果训练集准确率比测试集高5%以上,那基本可以确定过拟合。时间序列交叉验证(更严谨)
股价是时间序列数据,不能像普通结构化数据那样随机拆分训练测试——你的拆分方式是前1965条训练,后843条测试,可能存在数据泄露(比如未来信息提前被模型学习)。建议用时间序列交叉验证:# 示例:滚动窗口交叉验证 library(forecast) train_window <- 1965 test_window <- 30 accuracies <- c() for(i in seq(from = train_window, to = nrow(nn_df)-test_window, by = test_window)){ train_data <- nn_df[1:i,] test_data <- nn_df[(i+1):(i+test_window),] # 训练模型 temp_model <- neuralnet(GSPC.Close ~ GSPC.Open + GSPC.Low + GSPC.High + SentimentGI, data = train_data, hidden=5, linear.output=TRUE, threshold=0.01) # 预测 temp_pred <- compute(temp_model, test_data) # 反归一化并计算准确率 pred_temp = temp_pred$net.result * abs(diff(range(nn_org$GSPC.Close))) + min(nn_org$GSPC.Close) act_temp = test_data$GSPC.Close * abs(diff(range(nn_org$GSPC.Close))) + min(nn_org$GSPC.Close) dev_temp = abs((act_temp - pred_temp)/act_temp) acc_temp = 1 - mean(dev_temp) accuracies <- c(accuracies, acc_temp) } # 查看交叉验证的平均准确率 mean(accuracies)如果交叉验证的平均准确率远低于你之前的97-99%,那说明之前的测试集拆分有问题,模型存在过拟合或者数据泄露。
三、解决过拟合的常见方法
如果确认是过拟合,可以尝试以下调整:
- 简化模型结构:减少隐藏层神经元数量(比如从5降到2-3),避免模型过度学习训练数据的噪声。
- 调整训练阈值:降低模型训练的阈值(比如从0.01调到0.05),让模型提前停止训练,避免过度拟合。
- 特征筛选:检查输入特征是否有冗余(比如
GSPC.Open和GSPC.Close本身高度相关),用相关性分析筛选核心特征,减少无关信息对模型的干扰。 - 扩充数据集:如果可能的话,增加数据集的时间跨度,让模型学习到更多不同市场环境下的股价规律,提升泛化能力。
最后总结
先从评估指标合理性和训练测试集表现对比入手,确认是真的高准确率还是指标误导;再通过时间序列交叉验证验证模型的泛化能力;如果确实是过拟合,再通过简化模型、调整训练参数等方式优化。
内容的提问来源于stack exchange,提问作者james_ricky
相关产品推荐
相关产品推荐

