SoFunction
Updated on 2024-11-15

PyTorch builds LSTM for multivariate temporal load prediction

I. Preface

In a previous post PyTorch Build LSTM for Time Series Prediction (Load Prediction), we used LSTM to implement load prediction, but we simply used the load to predict the load, and we did not take advantage of some other environmental variables, such as temperature, humidity, and so on.

This post considers the implementation of multivariate time series forecasting by building LSTM with PyTorch.

Series of articles:

PyTorch builds LSTM for multivariate multistep time-series load prediction

PyTorch deep learning LSTM from input to Linear output

PyTorch builds LSTM for time series load forecasting

PyTorch builds bi-directional 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 at the next moment based on the load at the previous 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):
    print('Processing data:')
    data = load_data(file_name)
    load = data[[1]]
    load = ()
    data = ()
    seq = []
    for i in range(len(data) - 24):
        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)
        train_label.append(load[i + 24])
        train_seq = (train_seq)
        train_label = (train_label).view(-1)
        ((train_seq, train_label))
    # print(seq[:5])
    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

The above code used DataLoader to process the raw data and finally got the datasets Dtr and Dte with batch_size=B, Dtr is the training set and Dte is the test set.

Arbitrarily outputs a piece of data from the Dte:

[(tensor([[0.3513, 0.0000, 0.9091, 0.0000, 0.6667, 0.3023, 0.2439],
        [0.3333, 0.0000, 0.9091, 0.0435, 0.6667, 0.3023, 0.2439],
        [0.3396, 0.0000, 0.9091, 0.0870, 0.6667, 0.3023, 0.2439],
        [0.3427, 0.0000, 0.9091, 0.1304, 0.6667, 0.3023, 0.2439],
        [0.3838, 0.0000, 0.9091, 0.1739, 0.6667, 0.3023, 0.2439],
        [0.3700, 0.0000, 0.9091, 0.2174, 0.6667, 0.3023, 0.2439],
        [0.4288, 0.0000, 0.9091, 0.2609, 0.6667, 0.3023, 0.2439],
        [0.4474, 0.0000, 0.9091, 0.3043, 0.6667, 0.3023, 0.2439],
        [0.4406, 0.0000, 0.9091, 0.3478, 0.6667, 0.3023, 0.2439],
        [0.4657, 0.0000, 0.9091, 0.3913, 0.6667, 0.3023, 0.2439],
        [0.4540, 0.0000, 0.9091, 0.4348, 0.6667, 0.3023, 0.2439],
        [0.4939, 0.0000, 0.9091, 0.4783, 0.6667, 0.3023, 0.2439],
        [0.4328, 0.0000, 0.9091, 0.5217, 0.6667, 0.3023, 0.2439],
        [0.4238, 0.0000, 0.9091, 0.5652, 0.6667, 0.3023, 0.2439],
        [0.4779, 0.0000, 0.9091, 0.6087, 0.6667, 0.3023, 0.2439],
        [0.4591, 0.0000, 0.9091, 0.6522, 0.6667, 0.3023, 0.2439],
        [0.4651, 0.0000, 0.9091, 0.6957, 0.6667, 0.3023, 0.2439],
        [0.5102, 0.0000, 0.9091, 0.7391, 0.6667, 0.3023, 0.2439],
        [0.5067, 0.0000, 0.9091, 0.7826, 0.6667, 0.3023, 0.2439],
        [0.4635, 0.0000, 0.9091, 0.8261, 0.6667, 0.3023, 0.2439],
        [0.4224, 0.0000, 0.9091, 0.8696, 0.6667, 0.3023, 0.2439],
        [0.3796, 0.0000, 0.9091, 0.9130, 0.6667, 0.3023, 0.2439],
        [0.3292, 0.0000, 0.9091, 0.9565, 0.6667, 0.3023, 0.2439],
        [0.2940, 0.0000, 0.9091, 1.0000, 0.6667, 0.3023, 0.2439]]), tensor([0.3675]))]

Each row corresponds to a moment point load as well as an environment variable, at which point input_size=7.

III. LSTM model

A deeper understanding of the model in the input and output (from input to Linear output) of 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

def LSTM_train(name, b):
    Dtr, Dte = nn_seq(file_name=name, B=b)
    input_size, hidden_size, num_layers, output_size = 7, 64, 1, 1
    model = LSTM(input_size, hidden_size, num_layers, output_size, batch_size=b).to(device)
    loss_function = ().to(device)
    optimizer = ((), lr=0.05)
    # Training
    epochs = 30
    for i in range(epochs):
        cnt = 0
        print('Current', i)
        for (seq, label) in Dtr:
            cnt += 1
            seq = (device)
            label = (device)
            y_pred = model(seq)
            loss = loss_function(y_pred, label)
            optimizer.zero_grad()
            ()
            ()
            if cnt % 100 == 0:
                print('epoch', i, ':', cnt - 100, '~', cnt, ())
    state = {'model': model.state_dict(), 'optimizer': optimizer.state_dict()}
    (state, LSTM_PATH)

V. Testing

def test(name, b):
    global MAX, MIN
    Dtr, Dte = nn_seq(file_name=name, B=b)
    pred = []
    y = []
    print('loading model...')
    input_size, hidden_size, num_layers, output_size = 7, 64, 1, 1
    model = LSTM(input_size, hidden_size, num_layers, output_size, batch_size=b).to(device)
    model.load_state_dict((LSTM_PATH)['model'])
    ()
    print('predicting...')
    for (seq, target) in Dte:
        target = list(chain.from_iterable(()))
        (target)
        seq = (device)
        with torch.no_grad():
            y_pred = model(seq)
            y_pred = list(chain.from_iterable(y_pred.()))
            (y_pred)
    y, pred = ([y]), ([pred])
    y = (MAX - MIN) * y + MIN
    pred = (MAX - MIN) * pred + MIN
    print('accuracy:', get_mape(y, pred))
    # plot
    x = [i for i in range(1, 151)]
    x_smooth = ((x), (x), 900)
    y_smooth = make_interp_spline(x, [150:300])(x_smooth)
    (x_smooth, y_smooth, c='green', marker='*', ms=1, alpha=0.75, label='true')
    y_smooth = make_interp_spline(x, [150:300])(x_smooth)
    (x_smooth, y_smooth, c='red', marker='o', ms=1, alpha=0.75, label='pred')
    (axis='y')
    ()
    ()

I just trained 30 rounds with a MAPE of 7.83%:

VI. Source code and data

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

Above is the details of PyTorch build LSTM to realize multivariate temporal load prediction, more information about PyTorch LSTM multivariate temporal load prediction, please pay attention to my other related articles!