时间序列LSTM实现

这个代码参考了时间序列预测模型实战案例(三)(LSTM)(Python)(深度学习)时间序列预测(包括运行代码以及代码讲解)_lstm预测模型-CSDN博客

结合我之前所学的lstm-seq2seq里所学习到的知识对其进行预测

python 复制代码
import time
import numpy as np
import pandas as pd
import torch
import torch.nn as nn
from matplotlib import pyplot as plt
from sklearn.preprocessing import MinMaxScaler

np.random.seed(0)


def calculate_mae(y_true, y_pred):
    # 平均绝对误差
    mae = np.mean(np.abs(y_true - y_pred))
    return mae


true_data = pd.read_csv(r"C:\Users\33746\Desktop\DailyDelhiClimateTrain.csv")  # 填你自己的数据地址

target = 'meanpressure'

# 这里加一些数据的预处理, 最后需要的格式是pd.series

true_data = np.array(true_data['meanpressure'])

# 定义窗口大小
test_data_size = 32
# 训练集和测试集的尺寸划分
test_size = 0.15
train_size = 0.85
# 标准化处理
scaler_train = MinMaxScaler(feature_range=(0, 1))
scaler_test = MinMaxScaler(feature_range=(0, 1))
train_data = true_data[:int(train_size * len(true_data))]
test_data = true_data[-int(test_size * len(true_data)):]
print("训练集尺寸:", len(train_data))
print("测试集尺寸:", len(test_data))
train_data_normalized = scaler_train.fit_transform(train_data.reshape(-1, 1))
test_data_normalized = scaler_test.fit_transform(test_data.reshape(-1, 1))
# 转化为深度学习模型需要的类型Tensor
train_data_normalized = torch.FloatTensor(train_data_normalized).view(-1)
test_data_normalized = torch.FloatTensor(test_data_normalized).view(-1)


def create_inout_sequences(input_data, tw, pre_len):
    inout_seq = []
    L = len(input_data)
    for i in range(L - tw):
        train_seq = input_data[i:i + tw]
        if (i + tw + 4) > len(input_data):
            break
        train_label = input_data[i + tw:i + tw + pre_len]
        inout_seq.append((train_seq, train_label))
    return inout_seq


pre_len = 4
train_window = 16
# 定义训练器的的输入
train_inout_seq = create_inout_sequences(train_data_normalized, train_window, pre_len)


class LSTM(nn.Module):
    def __init__(self, input_dim=1, hidden_dim=350, output_dim=1):
        super(LSTM, self).__init__()

        self.hidden_dim = hidden_dim
        self.lstm = nn.LSTM(input_dim, hidden_dim, batch_first=True)
        self.fc = nn.Linear(hidden_dim, output_dim)

    def forward(self, x):
        x = x.unsqueeze(1)

        h0_lstm = torch.zeros(1, self.hidden_dim).to(x.device)
        c0_lstm = torch.zeros(1, self.hidden_dim).to(x.device)

        out, _ = self.lstm(x, (h0_lstm, c0_lstm))
        out = out[:, -1]
        out = self.fc(out)

        return out


lstm_model = LSTM(input_dim=1, output_dim=pre_len, hidden_dim=train_window)
loss_function = nn.MSELoss()
optimizer = torch.optim.Adam(lstm_model.parameters(), lr=0.001)
epochs = 10
Train = False  # 训练还是预测

if Train:
    losss = []
    lstm_model.train()  # 训练模式
    start_time = time.time()  # 计算起始时间
    for i in range(epochs):
        for seq, labels in train_inout_seq:
            lstm_model.train()
            optimizer.zero_grad()

            y_pred = lstm_model(seq)

            single_loss = loss_function(y_pred, labels)

            single_loss.backward()
            optimizer.step()
            print(f'epoch: {i:3} loss: {single_loss.item():10.8f}')
            losss.append(single_loss.detach().numpy())
    torch.save(lstm_model.state_dict(), 'save_model.pth')
    print(f"模型已保存,用时:{(time.time() - start_time) / 60:.4f} min")
    plt.plot(losss)
    # 设置图表标题和坐标轴标签
    plt.title('Training Error')
    plt.xlabel('Epoch')
    plt.ylabel('Error')
    # 保存图表到本地
    plt.savefig('training_error.png')
else:
    # 加载模型进行预测
    lstm_model.load_state_dict(torch.load('save_model.pth'))
    lstm_model.eval()  # 评估模式
    results = []
    reals = []
    losss = []
    test_inout_seq = create_inout_sequences(test_data_normalized, train_window, pre_len)
    for seq, labels in train_inout_seq:
        pred = lstm_model(seq)[0].item()
        results.append(pred)
        mae = calculate_mae(pred, labels.detach().numpy())  # MAE误差计算绝对值(预测值  - 真实值)
        reals.append(labels.detach().numpy())
        losss.append(mae)

    print("模型预测结果:", results)
    print("预测误差MAE:", losss)

    plt.style.use('ggplot')

    # 创建折线图
    plt.plot(results, label='real', color='blue')  # 实际值
    plt.plot(reals, label='forecast', color='red', linestyle='--')  # 预测值

    # 增强视觉效果
    plt.grid(True)
    plt.title('real vs forecast')
    plt.xlabel('time')
    plt.ylabel('value')
    plt.legend()
    plt.savefig('test------results.png')

train_data = true_data[:int(train_size * len(true_data))]

test_data = true_data[-int(test_size * len(true_data)):]是在干什么

这两行代码的作用是将数据集 true_data 划分为训练集 train_data 和测试集 test_data。具体来说:

代码解释:

  1. train_data = true_data[:int(train_size * len(true_data))]:

    • train_size 是一个比例值(例如0.8,表示80%),表示训练集占总数据集的比例。

    • len(true_data) 返回 true_data 的长度。

    • train_size * len(true_data) 计算出训练集的大小。

    • int(train_size * len(true_data)) 将计算结果转换为整数,表示训练集的实际样本数量。

    • true_data[:int(train_size * len(true_data))] 使用切片操作从 true_data 的开头到训练集的样本数量,提取出训练集。

  2. test_data = true_data[-int(test_size * len(true_data)):]:

    • test_size 是另一个比例值(例如0.2,表示20%),表示测试集占总数据集的比例。

    • test_size * len(true_data) 计算出测试集的大小。

    • int(test_size * len(true_data)) 将计算结果转换为整数,表示测试集的实际样本数量。

    • true_data[-int(test_size * len(true_data)):] 使用切片操作从 true_data 的末尾到测试集的样本数量,提取出测试集。

示例:

假设 true_data 有100个样本,train_size 为0.8,test_size 为0.2:

  • train_size * len(true_data) = 0.8 * 100 = 80

  • test_size * len(true_data) = 0.2 * 100 = 20

那么:

  • train_data = true_data[:80] 会提取 true_data 的前80个样本作为训练集。

  • test_data = true_data[-20:] 会提取 true_data 的后20个样本作为测试集。

注意事项:

  • 数据顺序 :如果 true_data 是有序的(例如时间序列数据),这种划分方式可能会导致训练集和测试集之间存在时间上的重叠,从而引入数据泄露。在这种情况下,应该按照时间顺序进行划分。

  • 随机性 :如果 true_data 是无序的,这种划分方式是合理的。但如果数据没有被打乱,建议在划分之前先打乱数据,以确保训练集和测试集能够代表整体数据的分布。

  • 假设 input_data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]tw = 3pre_len = 2

  • 第一次循环:

    • i = 0

    • train_seq = [1, 2, 3]

    • train_label = [4, 5]

    • inout_seq = [([1, 2, 3], [4, 5])]

  • 第二次循环:

    • i = 1

    • train_seq = [2, 3, 4]

    • train_label = [5, 6]

    • inout_seq = [([1, 2, 3], [4, 5]), ([2, 3, 4], [5, 6])]

  • 以此类推,直到 i = 7 时,train_seq = [8, 9, 10]train_label = [],此时 i + tw + pre_len 超出 input_data 的范围,循环结束。

相关推荐
红衣小蛇妖1 小时前
神经网络-Day44
人工智能·深度学习·神经网络
忠于明白1 小时前
Spring AI 核心工作流
人工智能·spring·大模型应用开发·spring ai·ai 应用商业化
大写-凌祁2 小时前
论文阅读:HySCDG生成式数据处理流程
论文阅读·人工智能·笔记·python·机器学习
柯南二号2 小时前
深入理解 Agent 与 LLM 的区别:从智能体到语言模型
人工智能·机器学习·llm·agent
珂朵莉MM2 小时前
2021 RoboCom 世界机器人开发者大赛-高职组(初赛)解题报告 | 珂学家
java·开发语言·人工智能·算法·职场和发展·机器人
IT_陈寒2 小时前
Element Plus 2.10.0 重磅发布!新增Splitter组件
前端·人工智能·后端
jndingxin2 小时前
OpenCV CUDA模块图像处理------创建一个模板匹配(Template Matching)对象函数createTemplateMatching()
图像处理·人工智能·opencv
盛寒2 小时前
N元语言模型 —— 一文讲懂!!!
人工智能·语言模型·自然语言处理
weixin_177297220693 小时前
家政小程序开发——AI+IoT技术融合,打造“智慧家政”新物种
人工智能·物联网
Jay Kay3 小时前
ReLU 新生:从死亡困境到强势回归
人工智能·数据挖掘·回归