SoFunction
Updated on 2024-10-29

PyTorch builds LSTM for multivariate multistep time-series load prediction

I. Preface

In the previous two articles PyTorch Build LSTM for Time Series Prediction (Load Prediction) and PyTorch Build LSTM for Multivariate Time Series Prediction (Load Prediction), we have implemented univariate single-step long time series prediction and multivariate single-step long time series prediction using LSTM respectively.

This post considers the implementation of multivariate multi-step time series prediction by building LSTM with PyTorch.

Series of articles:

PyTorch builds bi-directional LSTM for time series load forecasting

PyTorch builds LSTM for multivariate temporal load prediction

PyTorch deep learning LSTM from input to Linear output

PyTorch builds LSTM for time series load forecasting

II. Data processing

The dataset is the electrical load data for a certain area for a certain period of time, which includes information such as temperature and humidity in addition to the load.

In this paper, we predict the load for the next 4 moments (in adjustable steps) based on the load at the first 24 moments and the environmental variables at that moment.

def load_data(file_name):
    global MAX, MIN
    df = pd.read_csv((()) + '/data/new_data/' + file_name, encoding='gbk')
    columns = 
    ((), inplace=True)
    MAX = (df[columns[1]])
    MIN = (df[columns[1]])
    df[columns[1]] = (df[columns[1]] - MIN) / (MAX - MIN)
    return df
class MyDataset(Dataset):
    def __init__(self, data):
         = data
    def __getitem__(self, item):
        return [item]
    def __len__(self):
        return len()
def nn_seq(file_name, B, num):
    print('data processing...')
    data = load_data(file_name)
    load = data[[1]]
    load = ()
    data = ()
    seq = []
    for i in range(0, len(data) - 24 - num, num):
        train_seq = []
        train_label = []
        for j in range(i, i + 24):
            x = [load[j]]
            for c in range(2, 8):
                (data[j][c])
            train_seq.append(x)
        for j in range(i + 24, i + 24 + num):
            train_label.append(load[j])
        train_seq = (train_seq)
        train_label = (train_label).view(-1)
        ((train_seq, train_label))
    # print(seq[-1])
    Dtr = seq[0:int(len(seq) * 0.7)]
    Dte = seq[int(len(seq) * 0.7):len(seq)]
    train_len = int(len(Dtr) / B) * B
    test_len = int(len(Dte) / B) * B
    Dtr, Dte = Dtr[:train_len], Dte[:test_len]
    train = MyDataset(Dtr)
    test = MyDataset(Dte)
    Dtr = DataLoader(dataset=train, batch_size=B, shuffle=False, num_workers=0)
    Dte = DataLoader(dataset=test, batch_size=B, shuffle=False, num_workers=0)
    return Dtr, Dte

Where num denotes the step size to be predicted, e.g. num=4 means predicting the load for the next 4 moments.

Arbitrarily output one of the data:

(tensor([[0.5830, 1.0000, 0.9091, 0.6957, 0.8333, 0.4884, 0.5122],
        [0.6215, 1.0000, 0.9091, 0.7391, 0.8333, 0.4884, 0.5122],
        [0.5954, 1.0000, 0.9091, 0.7826, 0.8333, 0.4884, 0.5122],
        [0.5391, 1.0000, 0.9091, 0.8261, 0.8333, 0.4884, 0.5122],
        [0.5351, 1.0000, 0.9091, 0.8696, 0.8333, 0.4884, 0.5122],
        [0.5169, 1.0000, 0.9091, 0.9130, 0.8333, 0.4884, 0.5122],
        [0.4694, 1.0000, 0.9091, 0.9565, 0.8333, 0.4884, 0.5122],
        [0.4489, 1.0000, 0.9091, 1.0000, 0.8333, 0.4884, 0.5122],
        [0.4885, 1.0000, 0.9091, 0.0000, 1.0000, 0.3256, 0.3902],
        [0.4612, 1.0000, 0.9091, 0.0435, 1.0000, 0.3256, 0.3902],
        [0.4229, 1.0000, 0.9091, 0.0870, 1.0000, 0.3256, 0.3902],
        [0.4173, 1.0000, 0.9091, 0.1304, 1.0000, 0.3256, 0.3902],
        [0.4503, 1.0000, 0.9091, 0.1739, 1.0000, 0.3256, 0.3902],
        [0.4502, 1.0000, 0.9091, 0.2174, 1.0000, 0.3256, 0.3902],
        [0.5426, 1.0000, 0.9091, 0.2609, 1.0000, 0.3256, 0.3902],
        [0.5579, 1.0000, 0.9091, 0.3043, 1.0000, 0.3256, 0.3902],
        [0.6035, 1.0000, 0.9091, 0.3478, 1.0000, 0.3256, 0.3902],
        [0.6540, 1.0000, 0.9091, 0.3913, 1.0000, 0.3256, 0.3902],
        [0.6181, 1.0000, 0.9091, 0.4348, 1.0000, 0.3256, 0.3902],
        [0.6334, 1.0000, 0.9091, 0.4783, 1.0000, 0.3256, 0.3902],
        [0.6297, 1.0000, 0.9091, 0.5217, 1.0000, 0.3256, 0.3902],
        [0.5610, 1.0000, 0.9091, 0.5652, 1.0000, 0.3256, 0.3902],
        [0.5957, 1.0000, 0.9091, 0.6087, 1.0000, 0.3256, 0.3902],
        [0.6427, 1.0000, 0.9091, 0.6522, 1.0000, 0.3256, 0.3902]]), tensor([0.6360, 0.6996, 0.6889, 0.6434]))

The data format is (X, Y). Where X has a total of 24 rows, indicating the load values of the previous 24 moments and the environmental variables at that moment. y has a total of four values, indicating the four load values to be predicted. Note that at this point input_size=7 and output_size=4.

III. LSTM model

A deeper understanding of the model in the input and output (from input to Linear output) of the LSTM in PyTorch is used here:

class LSTM():
    def __init__(self, input_size, hidden_size, num_layers, output_size, batch_size):
        super().__init__()
        self.input_size = input_size
        self.hidden_size = hidden_size
        self.num_layers = num_layers
        self.output_size = output_size
        self.num_directions = 1
        self.batch_size = batch_size
         = (self.input_size, self.hidden_size, self.num_layers, batch_first=True)
         = (self.hidden_size, self.output_size)
    def forward(self, input_seq):
        h_0 = (self.num_directions * self.num_layers, self.batch_size, self.hidden_size).to(device)
        c_0 = (self.num_directions * self.num_layers, self.batch_size, self.hidden_size).to(device)
        # print(input_seq.size())
        seq_len = input_seq.shape[1]
        # input(batch_size, seq_len, input_size)
        input_seq = input_seq.view(self.batch_size, seq_len, self.input_size)
        # output(batch_size, seq_len, num_directions * hidden_size)
        output, _ = (input_seq, (h_0, c_0))
        # print('=', ())
        # print(self.batch_size * seq_len, self.hidden_size)
        output = ().view(self.batch_size * seq_len, self.hidden_size)  # (5 * 30, 64)
        pred = (output)  # pred()
        # print('pred=', )
        pred = (self.batch_size, seq_len, -1)
        pred = pred[:, -1, :]
        return pred

IV. Training and forecasting

The training and prediction code is pretty much the same as the previous ones, except that you need to pay attention to the size of input_size and output_size.

100 rounds were trained to predict the load values for the next four moments with a MAPE of 7.53%:

V. Source code and data

The source code and data I put on GitHub.LSTM-Load-Forecasting

Above is the detailed content of PyTorch build LSTM to realize multivariate multi-step time-series load prediction, more information about LSTM multivariate multi-step time-series load prediction, please pay attention to my other related articles!