PyTorch-LSTM时间序列预测中如何预测真正的未来值

本文详细讲解了如何在已训练模型基础上预测真实未来值,涉及单变量和多变量预测,包括利用真实值、预测值及混合真实预测的方法,并介绍了多模型和LSTM在不同场景的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

I. 前言

之前写过几篇有关PyTorch搭建LSTM实现时间序列预测的文章,具体链接如下:

系列文章:

  1. 深入理解PyTorch中LSTM的输入和输出(从input输入到Linear输出)
  2. PyTorch搭建LSTM实现时间序列预测(负荷预测)
  3. PyTorch中利用LSTMCell搭建多层LSTM实现时间序列预测
  4. PyTorch搭建LSTM实现多变量时间序列预测(负荷预测)
  5. PyTorch搭建双向LSTM实现时间序列预测(负荷预测)
  6. PyTorch搭建LSTM实现多变量多步长时间序列预测(一):直接多输出
  7. PyTorch搭建LSTM实现多变量多步长时间序列预测(二):单步滚动预测
  8. PyTorch搭建LSTM实现多变量多步长时间序列预测(三):多模型单步预测
  9. PyTorch搭建LSTM实现多变量多步长时间序列预测(四):多模型滚动预测
  10. PyTorch搭建LSTM实现多变量多步长时间序列预测(五):seq2seq
  11. PyTorch中实现LSTM多步长时间序列预测的几种方法总结(负荷预测)
  12. PyTorch-LSTM时间序列预测中如何预测真正的未来值
  13. PyTorch搭建LSTM实现多变量输入多变量输出时间序列预测(多任务学习)
  14. PyTorch搭建ANN实现时间序列预测(风速预测)
  15. PyTorch搭建CNN实现时间序列预测(风速预测)
  16. PyTorch搭建CNN-LSTM混合模型实现多变量多步长时间序列预测(负荷预测)
  17. PyTorch搭建Transformer实现多变量多步长时间序列预测(负荷预测)
  18. PyTorch时间序列预测系列文章总结(代码使用方法)
  19. TensorFlow搭建LSTM实现时间序列预测(负荷预测)
  20. TensorFlow搭建LSTM实现多变量时间序列预测(负荷预测)
  21. TensorFlow搭建双向LSTM实现时间序列预测(负荷预测)
  22. TensorFlow搭建LSTM实现多变量多步长时间序列预测(一):直接多输出
  23. TensorFlow搭建LSTM实现多变量多步长时间序列预测(二):单步滚动预测
  24. TensorFlow搭建LSTM实现多变量多步长时间序列预测(三):多模型单步预测
  25. TensorFlow搭建LSTM实现多变量多步长时间序列预测(四):多模型滚动预测
  26. TensorFlow搭建LSTM实现多变量多步长时间序列预测(五):seq2seq
  27. TensorFlow搭建LSTM实现多变量输入多变量输出时间序列预测(多任务学习)
  28. TensorFlow搭建ANN实现时间序列预测(风速预测)
  29. TensorFlow搭建CNN实现时间序列预测(风速预测)
  30. TensorFlow搭建CNN-LSTM混合模型实现多变量多步长时间序列预测(负荷预测)
  31. PyG搭建图神经网络实现多变量输入多变量输出时间序列预测
  32. PyTorch搭建GNN-LSTM和LSTM-GNN模型实现多变量输入多变量输出时间序列预测
  33. PyG Temporal搭建STGCN实现多变量输入多变量输出时间序列预测
  34. 时序预测中Attention机制是否真的有效?盘点LSTM/RNN中24种Attention机制+效果对比
  35. 详解Transformer在时序预测中的Encoder和Decoder过程:以负荷预测为例
  36. (PyTorch)TCN和RNN/LSTM/GRU结合实现时间序列预测
  37. PyTorch搭建Informer实现长序列时间序列预测
  38. PyTorch搭建Autoformer实现长序列时间序列预测
  39. PyTorch搭建GNN(GCN、GraphSAGE和GAT)实现多节点、单节点内多变量输入多变量输出时空预测

文章写出后有不少人加了我的微信,也探讨了不少问题。这其中大家问得最多的问题是:到底怎么预测真正的未来值呢?而不是简单预测测试集里面的数据。这个问题其实很好解决,但貌似很多人不知道怎么写代码,也不知道怎么在原有代码的基础上改代码。所以,这篇文章我详细讲一下如何预测真正的未来值。

II. 分析

模型训练自不必说。

在对测试集进行预测时,我们已经提前处理好了数据,具体测试代码如下:

def test(args, Dte, lis, path):
    # Dtr, Dte, lis1, lis2 = load_data(args, flag, args.batch_size)
    pred = []
    y = []
    print('loading models...')
    input_size, hidden_size, num_layers = args.input_size, args.hidden_size, args.num_layers
    output_size = args.output_size
    if args.bidirectional:
        model = BiLSTM(input_size, hidden_size, num_layers, output_size, batch_size=args.batch_size).to(device)
    else:
        model = LSTM(input_size, hidden_size, num_layers, output_size, batch_size=args.batch_size).to(device)
    # models = LSTM(input_size, hidden_size, num_layers, output_size, batch_size=args.batch_size).to(device)
    model.load_state_dict(torch.load(path)['models'])
    model.eval()
    print('predicting...')
    for (seq, target) in tqdm(Dte):
        target = list(chain.from_iterable(target.data.tolist()))
        y.extend(target)
        seq = seq.to(device)
        with torch.no_grad():
            y_pred = model(seq)
            y_pred = list(chain.from_iterable(y_pred.data.tolist()))
            pred.extend(y_pred)

    y, pred = np.array(y), np.array(pred)
    m, n = lis[0], lis[1]
    y = (m - n) * y + n
    pred = (m - n) * pred + n
    print('mape:', get_mape(y, pred))
    # plot
    plot(y, pred)

核心代码:

for (seq, target) in tqdm(Dte):
    target = list(chain.from_iterable(target.data.tolist()))
    y.extend(target)
    seq = seq.to(device)
    with torch.no_grad():
        y_pred = model(seq)
        y_pred = list(chain.from_iterable(y_pred.data.tolist()))
        pred.extend(y_pred)

Dte为测试集,对于Dte中的每一个seq我们都知道了其标签target,但在预测未来值时我们只能得到seq,并不知道label。

当前时间为2022/6/6的21:00,我们用前24个小时的负荷值预测未来12个小时的负荷值。现在假设测试集的截止时间就为6/6的21:00,现在我们需要预测22:00到6/7 9:00的负荷值。根据模型的需求,我们需要构造一个seq,seq里面包含了6/6 21:00往前24个时刻的负荷值,这个是真实存在的。

具体代码:

def predict_one_step(model):
    data = data_process.load_data()

    train = data[:int(len(data) * 0.7)]
    test = data[int(len(data) * 0.7):len(data)]
    # 取test的最后24个负荷值
    load = test[test.columns[1]]
    load = load.tolist()
    m, n = np.max(load), np.min(load)
    load = (load - n) / (m - n)
    test = test.values.tolist()
    seq = []
    for i in range(len(test) - 24, len(test)):
        seq.append([load[i]])
    seq = [seq]
    seq = torch.FloatTensor(seq)
    seq = MyDataset(seq)
    seq = DataLoader(dataset=seq, batch_size=1, shuffle=False, num_workers=0)
    # print(new_seq)
    seq = [x for x in iter(seq)][0]
    print(seq.shape)  # (1, 24, 1) batch_size=1, seq_len=24, input_size=1
    # 开始预测
    seq = seq.to(device)
    with torch.no_grad():
        y_pred = model(seq)
        y_pred = list(chain.from_iterable(y_pred.data.tolist()))
    # y_pred为一个列表,长度为12
    return y_pred * (m - n) + n

上述代码的作用是利用测试集中最后24个时刻的值预测未来12个时刻的负荷值,这12值还没被观测到,是真正意义上的未来值。值得注意的是,为了满足模型的需要,即使只预测一个样本,我们也需要将其处理成如下格式的Tensor:

(batch_size=1, seq_len=24, input_size=1)

这里input_size=1,即我们在预测未来值时只考虑负荷值,不考虑其他诸如温度、湿度以及压强等环境因素。

现在我们已经预测完了今晚22:00到6/7 9:00的负荷值,如果我们想接着预测6/7 10:00~21:00的负荷值又该如何操作呢?一般来讲,有以下三种可能:

(1)假设电网有能力实时收集到真实用电负荷值,到明天9:00时,我们已经观测到了今晚22:00到明天9:00的真实值,且这些真实值保存在了数据库中,假设保存在了数组true_list中。那么我们完全可以利用今晚22:00到明天9:00的真实值预测未来12小时的负荷值,具体代码如下:

def predict_1(model, true_list, MAX, MIN):
    # 取真实值中最后24个负荷值
    true_list = true_list[-24:]
    # 构造seq
    true_list = (true_list- MIN) / (MAX - MIN)
    seq = [[x] for x in true_list]
    seq = [seq]
    seq = torch.FloatTensor(seq)
    seq = MyDataset(seq)
    seq = DataLoader(dataset=seq, batch_size=1, shuffle=False, num_workers=0)
    # print(new_seq)
    seq = [x for x in iter(seq)][0]
    print(seq.shape)  # (1, 24, 1) batch_size=1, seq_len=24, input_size=1
    # 开始预测
    seq = seq.to(device)
    with torch.no_grad():
        y_pred = model(seq)
        y_pred = list(chain.from_iterable(y_pred.data.tolist()))
    # y_pred为一个列表,长度为12
    return y_pred * (MAX - MIN) + MIN

简单来说就是利用真实值列表true_list中最后24个值进行预测。需要注意的是,我们是利用训练集中的最大最小值来对新数据进行归一化与反归一化的。此时,我们是可以计算MAPE的,因为真实值和预测值都存在。

(2)在现实生活中,往往很难及时收集到用电负荷信息,比如我们预测到了明天9:00,在明天9:00时,我们收集不到今晚22:00到明天9:00间的真实负荷值,此时我们就需要利用预测值来进行预测。也就是用一开始得到的今晚22:00到明天9:00间的预测值来预测未来12小时的负荷值,我们假设预测值保存在pred_list中,那么将上面代码中的true_list换成pred_list就可以得到未来12小时的负荷预测值。值得注意的是,此时是不能计算MAPE的,因为真实值尚未观测到。

(3)在明天9:00时,我们也不是一点真实值都没收集到,比如我们收集到了今晚22:00到明早3:00的负荷值,4:00到9:00的真实负荷值虽然已经产生,但电网还没有收集到数据库中。此时我们拥有6个真实值以及6个预测值,那么此时我们就可以用6个真实值加6个预测值,以及今晚9:00之前的12个真实值组成1个seq进行预测。一个大的前提:尽量使用真实值进行预测。

III. 多变量预测

上面的例子都是单变量预测,如果是多变量预测,情况将变得复杂一点。假设我们利用负荷值、温度、湿度以及压强四个变量来预测负荷。在我们预测今晚22:00到明早9:00的负荷值时,我们可以利用测试集中的数据进行预测。但当我们需要预测明早9:00之后的负荷值时,我们需要同时考虑是否收集到了真实的温度、湿度以及压强值。一般来讲,这些环境变量的收集比负荷数据的收集更加容易,也就是上述第二节中的第一种情况。

如果我们无法及时收集到负荷值,我们可以利用预测值进行预测;如果我们无法及时收集到温度、湿度以及压强值,我们也只能利用预测值进行预测。这就意味着,我们需要额外训练三个模型来分别预测温度、湿度以及压强,由于这三个变量和负荷一一对应,也属于时序数据,我们也可以采用LSTM进行预测,如果其变化幅度不大也可以采用传统的机器学习算法进行预测。

LSTM可以用于时间序列预测,包括未来多天的数据预测。以下是一个简单的LSTM模型示例,用于预测未来5天的股票价格。 1. 准备数据 首先,我们需要准备时间序列数据,包括历史数据和待预测未来数据。我们可以使用pandas库读取csv文件,并将数据转换为numpy数组。 ```python import pandas as pd import numpy as np # 读取csv文件 df = pd.read_csv('stock_prices.csv') # 将数据转换为numpy数组 data = df['price'].values ``` 我们需要将数据分成训练集和测试集,以便评估模型的性能。在这个例子中,我们将使用前1000个数据点作为训练集,后面的100个数据点作为测试集。 ```python # 划分训练集和测试集 train_size = 1000 train_data = data[:train_size] test_data = data[train_size:] ``` 我们还需要对数据进行归一化处理,以便模型更好地学习数据的模式。在这个例子中,我们将使用MinMaxScaler进行归一化处理。 ```python from sklearn.preprocessing import MinMaxScaler # 归一化处理 scaler = MinMaxScaler() train_data = scaler.fit_transform(train_data.reshape(-1, 1)) test_data = scaler.transform(test_data.reshape(-1, 1)) ``` 2. 构建模型 接下来,我们需要构建LSTM模型。在这个例子中,我们将使用一个包含两个LSTM层和一个全连接层的简单模型。 ```python from tensorflow.keras.models import Sequential from tensorflow.keras.layers import LSTM, Dense # 构建模型 model = Sequential() model.add(LSTM(64, input_shape=(5, 1), return_sequences=True)) model.add(LSTM(32)) model.add(Dense(1)) model.compile(optimizer='adam', loss='mse') ``` 在这个模型中,第一个LSTM层有64个神经元,接受5个时间步长(或者说5天)的输入数据。第二个LSTM层有32个神经元,将前一层的输出作为输入。最后,我们添加一个全连接层来输出预测结果。 3. 训练模型 接下来,我们需要使用训练数据来训练模型。在每个训练周期中,我们将使用前5天的数据来预测下一天的数据。 ```python # 训练模型 X_train = [] y_train = [] for i in range(5, len(train_data)): X_train.append(train_data[i-5:i]) y_train.append(train_data[i]) X_train = np.array(X_train) y_train = np.array(y_train) model.fit(X_train, y_train, epochs=100, batch_size=32) ``` 在这个例子中,我们将训练模型100个周期,每个周期使用32个样本进行训练。 4. 预测未来数据 最后,我们可以使用训练好的模型预测未来数据。在这个例子中,我们将使用最后5天的数据来预测未来5天的数据。 ```python # 预测未来数据 X_test = [] for i in range(len(test_data)-4, len(test_data)+1): X_test.append(test_data[i-5:i]) X_test = np.array(X_test) predicted_data = [] for i in range(5): predicted_value = model.predict(np.array([X_test[i]])) predicted_data.append(predicted_value) predicted_data = np.array(predicted_data).reshape(-1, 1) # 反归一化处理 predicted_data = scaler.inverse_transform(predicted_data) ``` 在这个例子中,我们将使用预测结果来更新测试集数据,并且重复进行预测,直到预测出5个未来数据点。最后,我们将预测结果反归一化处理,以便与原始数据进行比较。 完整代码示例: ```python import pandas as pd import numpy as np from sklearn.preprocessing import MinMaxScaler from tensorflow.keras.models import Sequential from tensorflow.keras.layers import LSTM, Dense # 读取csv文件 df = pd.read_csv('stock_prices.csv') # 将数据转换为numpy数组 data = df['price'].values # 划分训练集和测试集 train_size = 1000 train_data = data[:train_size] test_data = data[train_size:] # 归一化处理 scaler = MinMaxScaler() train_data = scaler.fit_transform(train_data.reshape(-1, 1)) test_data = scaler.transform(test_data.reshape(-1, 1)) # 构建模型 model = Sequential() model.add(LSTM(64, input_shape=(5, 1), return_sequences=True)) model.add(LSTM(32)) model.add(Dense(1)) model.compile(optimizer='adam', loss='mse') # 训练模型 X_train = [] y_train = [] for i in range(5, len(train_data)): X_train.append(train_data[i-5:i]) y_train.append(train_data[i]) X_train = np.array(X_train) y_train = np.array(y_train) model.fit(X_train, y_train, epochs=100, batch_size=32) # 预测未来数据 X_test = [] for i in range(len(test_data)-4, len(test_data)+1): X_test.append(test_data[i-5:i]) X_test = np.array(X_test) predicted_data = [] for i in range(5): predicted_value = model.predict(np.array([X_test[i]])) predicted_data.append(predicted_value) predicted_data = np.array(predicted_data).reshape(-1, 1) # 反归一化处理 predicted_data = scaler.inverse_transform(predicted_data) print(predicted_data) ```
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Cyril_KI

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值