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

无法绘制LSTM模型预测结果,报IndexError错误如何解决?

解决LSTM股票价格预测代码中的IndexError问题

错误原因

触发IndexError的核心问题是:代码中将data转换为了numpy数组,而numpy数组不支持用字符串列名(如valid['Predictions'])来添加新列——numpy数组仅接受整数、切片、布尔数组等类型的索引,这和错误提示完全对应。

另外代码还存在两个隐性问题:

  1. 预测值predictions的长度与验证集valid的长度不匹配(预测值是从验证集第60天开始生成的,比验证集短60个数据点)
  2. RMSE计算时,y_test仍处于归一化尺度,与逆变换后的predictions尺度不一致,导致误差计算无效

修改步骤

  1. 保留DataFrame格式:不要过早将data转换为numpy数组,保留pandas DataFrame结构,方便后续添加列和绘图
  2. 对齐预测值与验证集长度:由于预测值需要前60天数据生成,给验证集的前60天填充NaN,再拼接预测值,保证长度匹配
  3. 修正RMSE计算逻辑:先将归一化后的y_test逆变换回原始尺度,再和predictions计算误差

修正后的完整代码

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import tensorflow as tf
from sklearn.preprocessing import MinMaxScaler
from datetime import datetime, timedelta
import yfinance as yf

# 下载AAPL股票数据
symbol = 'AAPL'
start_date = datetime.now() - timedelta(days=365 * 2)
end_date = datetime.now()
df = yf.download(symbol, start=start_date, end=end_date)

# 保留DataFrame格式,不转numpy数组
data = df.filter(['Adj Close'])

# 归一化数据(用values获取numpy数组进行处理)
scaler = MinMaxScaler(feature_range=(0, 1))
scaled_data = scaler.fit_transform(data.values)

# 划分训练集和测试集
training_data_len = int(len(data) * 0.8)
train_data = scaled_data[:training_data_len, :]
test_data = scaled_data[training_data_len:, :]

# 准备训练数据
x_train = []
y_train = []
for i in range(60, len(train_data)):
    x_train.append(train_data[i-60:i, 0])
    y_train.append(train_data[i, 0])

x_train, y_train = np.array(x_train), np.array(y_train)
# 调整LSTM输入形状
x_train = np.reshape(x_train, (x_train.shape[0], x_train.shape[1], 1))

# 构建LSTM模型
model = tf.keras.models.Sequential()
model.add(tf.keras.layers.LSTM(50, return_sequences=True, input_shape=(x_train.shape[1], 1)))
model.add(tf.keras.layers.LSTM(50, return_sequences=False))
model.add(tf.keras.layers.Dense(25))
model.add(tf.keras.layers.Dense(1))

# 编译并训练模型
model.compile(optimizer='adam', loss='mean_squared_error')
model.fit(x_train, y_train, batch_size=1, epochs=1)

# 准备测试数据
x_test = []
y_test = scaled_data[training_data_len + 60:, :]
for i in range(60, len(test_data)):
    x_test.append(test_data[i-60:i, 0])

x_test = np.array(x_test)
x_test = np.reshape(x_test, (x_test.shape[0], x_test.shape[1], 1))

# 获取预测值并逆变换回原始尺度
predictions = model.predict(x_test)
predictions = scaler.inverse_transform(predictions)

# 修正RMSE计算:先将y_test逆变换
y_test_unscaled = scaler.inverse_transform(y_test)
rmse = np.sqrt(np.mean((predictions - y_test_unscaled)**2))
print(f"RMSE: {rmse}")

# 绘图部分:用DataFrame处理,对齐长度
train = data[:training_data_len]
valid = data[training_data_len:].copy()
# 前60天无预测值,填充NaN,再拼接预测值
valid['Predictions'] = np.concatenate([np.full(60, np.nan), predictions])

plt.figure(figsize=(16,8))
plt.title('LSTM股票价格预测模型')
plt.xlabel('日期')
plt.ylabel('调整后收盘价(美元)')
plt.plot(train['Adj Close'])
plt.plot(valid[['Adj Close', 'Predictions']])
plt.legend(['训练集', '验证集', '预测值'], loc='lower right')
plt.show()

# 预测未来1天价格
last_60_days = data[-60:].values
last_60_days_scaled = scaler.transform(last_60_days)
X_test = []
X_test.append(last_60_days_scaled)
X_test = np.array(X_test)
X_test = np.reshape(X_test, (X_test.shape[0], X_test.shape[1], 1))
predicted_price = model.predict(X_test)
predicted_price = scaler.inverse_transform(predicted_price)
print(f"次日预测价格: ${predicted_price[0][0]:.2f}")

关键修改点说明

  • 将data = df.filter(['Adj Close']).values改为data = df.filter(['Adj Close']),保留DataFrame结构
  • 给valid添加Predictions列时,用np.concatenate填充前60天的NaN,保证和验证集长度一致
  • RMSE计算前先对y_test做逆变换,确保和predictions尺度统一
  • 修复了最后打印语句的引号缺失问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 22:57:57