weixin_46847933 2024-07-12 15:57 采纳率: 25%
浏览 11
已结题

对于LSTM实践问题的疑问

最近想跑一个简单的LSTM的模型,但是预测结果总是很差,不知道问题处在了哪里?

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

# 获取股票数据
df = yf.download('AAPL', start='2012-01-01', end=datetime.now().strftime('%Y-%m-%d'))

# 选择特征:Open, High, Low, Close, Volume
data = df[['Open', 'High', 'Low', 'Close', 'Volume']]

# 计算移动平均线(如5日、10日、20日)
data['MA5'] = data['Close'].rolling(window=5).mean()
data['MA10'] = data['Close'].rolling(window=10).mean()
data['MA20'] = data['Close'].rolling(window=20).mean()

# 计算指数平滑移动平均线(EMA)
data['EMA'] = data['Close'].ewm(span=20, adjust=False).mean()

# 计算相对强弱指数(RSI)
delta = data['Close'].diff(1)
gain = delta.where(delta > 0, 0)
loss = -delta.where(delta < 0, 0)
avg_gain = gain.rolling(window=14).mean()
avg_loss = loss.rolling(window=14).mean()
rs = avg_gain / avg_loss
data['RSI'] = 100 - (100 / (1 + rs))

# 移除缺失值
data.dropna(inplace=True)

# 数据归一化
scaler = MinMaxScaler(feature_range=(0, 1))
scaled_data = scaler.fit_transform(data)

# 定义窗口大小
look_back = 60

# 创建特征和目标
x_data = []
y_data = []
for i in range(look_back, len(scaled_data)):
    x_data.append(scaled_data[i-look_back:i])
    y_data.append(scaled_data[i, 3])  # 目标是收盘价

# 转换为numpy数组
x_data, y_data = np.array(x_data), np.array(y_data)

# 划分训练和测试数据
train_size = int(len(x_data) * 0.8)
x_train, x_test = x_data[:train_size], x_data[train_size:]
y_train, y_test = y_data[:train_size], y_data[train_size:]

# 重塑数据为LSTM的输入形状
x_train = np.reshape(x_train, (x_train.shape[0], x_train.shape[1], x_train.shape[2]))
x_test = np.reshape(x_test, (x_test.shape[0], x_test.shape[1], x_test.shape[2]))

import torch
from torch.utils.data import DataLoader, Dataset

class StockDataset(Dataset):
    def __init__(self, features, targets):
        self.features = features
        self.targets = targets

    def __len__(self):
        return len(self.features)

    def __getitem__(self, index):
        return self.features[index], self.targets[index]

train_dataset = StockDataset(x_train, y_train)
train_loader = DataLoader(train_dataset, batch_size=16, shuffle=True)

test_dataset = StockDataset(x_test, y_test)
test_loader = DataLoader(test_dataset, batch_size=16, shuffle=False)

import torch.nn as nn

class LSTMModel(nn.Module):
    def __init__(self, input_size, hidden_size1=128, hidden_size2=64, output_size=1):
        super(LSTMModel, self).__init__()
        self.lstm1 = nn.LSTM(input_size, hidden_size1, num_layers=1, batch_first=True)
        self.lstm2 = nn.LSTM(hidden_size1, hidden_size2, num_layers=1, batch_first=True)
        self.dense = nn.Linear(hidden_size2, output_size)

    def forward(self, x):
        lstm_out1, _ = self.lstm1(x)
        lstm_out2, _ = self.lstm2(lstm_out1)
        lstm_out2 = lstm_out2[:, -1, :]  # 只取最后一个时间步的输出
        predictions = self.dense(lstm_out2)
        return predictions

input_size = x_train.shape[2]
model = LSTMModel(input_size=input_size)

import torch.optim as optim

def train_model(model, train_loader, num_epochs=100, lr=0.001):
    loss_function = nn.MSELoss()
    optimizer = optim.Adam(model.parameters(), lr=lr)
    
    for epoch in range(num_epochs):
        model.train()
        for inputs, targets in train_loader:
            inputs, targets = inputs.float(), targets.float()
            optimizer.zero_grad()
            outputs = model(inputs)
            loss = loss_function(outputs, targets)
            loss.backward()
            optimizer.step()
        print(f'Epoch {epoch+1}/{num_epochs}, Loss: {loss.item()}')

train_model(model, train_loader)

model.eval()
predictions = []

with torch.no_grad():
    for inputs, _ in test_loader:
        inputs = inputs.float()
        outputs = model(inputs)
        predictions.append(outputs.numpy())

# 连接预测结果
predictions = np.concatenate(predictions)

# 反归一化
predictions = scaler.inverse_transform(np.concatenate((np.zeros((predictions.shape[0], scaled_data.shape[1] - 1)), predictions.reshape(-1, 1)), axis=1))[:, -1]

# 可视化
train = data.iloc[:train_size + look_back]
valid = data.iloc[train_size + look_back:]
valid['Predictions'] = predictions

plt.figure(figsize=(16,8))
plt.title('Model')
plt.xlabel('Date')
plt.ylabel('Close Price USD ($)')
plt.plot(train['Close'])
plt.plot(valid[['Close', 'Predictions']])
plt.legend(['Train', 'Val', 'Predictions'], loc='lower right')
plt.show()

结果很差:

img

  • 写回答

30条回答 默认 最新

  • 专家-赤兔[在线] 全栈领域优质创作者 2024-07-12 15:57
    关注
    获得0.50元问题酬金

    引自免费微信小程序:皆我百晓生

    你的代码看起来大体上没有问题,但有几个可能的原因导致预测结果不佳:

    1. 数据问题:你可能需要更多的数据,特别是更多的近期数据,以提高模型的预测能力。股票市场受到许多复杂因素的影响,因此更多的数据可以让模型更好地捕捉这些因素的影响。另外,你需要检查你的数据是否确实包含了你预期的所有特征,例如市场趋势、季节性变化等。对于股票价格预测来说,一些宏观经济因素如政策变化、全球经济形势等也可能产生影响,这些因素在你的当前数据中可能没有体现。
    2. 模型结构问题:你的模型可能过于简单或过于复杂。尝试调整LSTM层的数量和隐藏层的大小,看看是否可以改善结果。此外,你也可以尝试添加更多的预处理步骤或特征工程步骤,例如添加更多的技术指标或统计特征。此外,考虑使用更复杂的模型结构,如使用注意力机制或者结合其他机器学习算法。
    3. 训练问题:你可能需要更长时间的训练或者更多的训练周期。深度学习模型的训练通常需要大量的时间和计算资源。你可以尝试增加训练的epoch数量或者调整学习率来看看是否能提高模型的性能。此外,确保你的训练过程没有出现过早停止或者欠拟合的情况。
    4. 归一化和反归一化问题:你的归一化和反归一化步骤看起来是正确的,但请确保你的测试数据和训练数据使用的归一化参数是一致的。如果测试数据的归一化参数和训练数据的参数不一致,可能会导致预测结果不准确。另外,确保你在反归一化预测结果时使用的是正确的列索引(在你的代码中看起来是scaled_data.shape[1] - 1)。这是因为你的模型是在预测收盘价(Close),所以你需要从归一化的数据中提取相应的部分进行反归一化。如果这一步出现问题,可能会导致预测结果与实际结果有较大偏差。

    希望这些建议对你有所帮助!如果还有其他问题,请继续提问。

    评论 编辑记录

报告相同问题?

问题事件

  • 系统已结题 7月20日
  • 创建了问题 7月12日

悬赏问题

  • ¥15 Windows Script Host 无法找到脚本文件"C:\ProgramData\Player800\Cotrl.vbs”
  • ¥15 matlab自定义损失函数
  • ¥15 35114 SVAC视频验签的问题
  • ¥15 impedancepy
  • ¥15 求往届大挑得奖作品(ppt…)
  • ¥15 如何在vue.config.js中读取到public文件夹下window.APP_CONFIG.API_BASE_URL的值
  • ¥50 浦育平台scratch图形化编程
  • ¥20 求这个的原理图 只要原理图
  • ¥15 vue2项目中,如何配置环境,可以在打完包之后修改请求的服务器地址
  • ¥20 微信的店铺小程序如何修改背景图