web-dev-qa-db-fra.com

Entrée LSTM multivariée dans pytorch

Je voudrais implémenter LSTM pour une entrée multivariée dans Pytorch .

Suite à cet article https://machinelearningmastery.com/how-to-develop-lstm-models-for-time-series-forecasting/ qui utilise des keras, les données d'entrée sont en forme de (nombre de échantillons, nombre de pas de temps, nombre de fonctions parallèles)

in_seq1 = array([10, 20, 30, 40, 50, 60, 70, 80, 90])
in_seq2 = array([15, 25, 35, 45, 55, 65, 75, 85, 95])
out_seq = array([in_seq1[i]+in_seq2[i] for i in range(len(in_seq1))])
. . . 
Input     Output
[[10 15]
 [20 25]
 [30 35]] 65
[[20 25]
 [30 35]
 [40 45]] 85
[[30 35]
 [40 45]
 [50 55]] 105
[[40 45]
 [50 55]
 [60 65]] 125
[[50 55]
 [60 65]
 [70 75]] 145
[[60 65]
 [70 75]
 [80 85]] 165
[[70 75]
 [80 85]
 [90 95]] 185

n_timesteps = 3
n_features = 2

En keras, cela semble facile:

model.add(LSTM(50, activation='relu', input_shape=(n_timesteps, n_features)))

Cela peut-il être fait autrement que de créer n_features De LSTM en tant que première couche et de les alimenter séparément (imaginez comme plusieurs flux de séquences), puis d'aplatir leur sortie en couche linéaire?

Je ne suis pas sûr à 100% mais par nature de LSTM, l'entrée ne peut pas être aplatie et passée en tableau 1D, car chaque séquence "joue selon des règles différentes" que le LSTM est censé apprendre.

Alors, comment une telle implémentation avec des kéros égale à PyTorch input of shape (seq_len, batch, input_size) (source https://pytorch.org/docs/stable/nn.html#lstm )


Modifier:

Cela peut-il être fait autrement que de créer n_features De LSTM en tant que première couche et de les alimenter séparément (imaginez comme plusieurs flux de séquences), puis d'aplatir leur sortie en couche linéaire?

Selon PyTorch docs le paramètre input_size signifie en fait le nombre de fonctionnalités (si cela signifie le nombre de séquences parallèles)

3
Tomas Trdla

l'entrée dans n'importe quelle cellule rnn dans pytorch est une entrée 3D, formatée comme (seq_len, batch, input_size) ou (batch, seq_len, input_size), si vous préférez la seconde (comme moi aussi lol) init lstm layer) ou une autre couche rnn) avec arg

bach_first = True

https://discuss.pytorch.org/t/could-someone-explain-batch-first-true-in-lstm/15402

vous n'avez pas non plus de relation récurrente dans la configuration. Si vous voulez créer plusieurs contre un compteur, créez une entrée si size (-1, n, 1) où -1 est la taille que vous voulez, n est le nombre de chiffres, un chiffre par tick comme l'entrée [[10] [20] [30]], sortie - 60, entrée [[30,] [70]] sortie 100 etc., l'entrée doit avoir des longueurs différentes de 1 à un certain maximum, afin d'apprendre la relation rnn

import random

import numpy as np

import torch


def rnd_io():    
    return  np.random.randint(100, size=(random.randint(1,10), 1))


class CountRNN(torch.nn.Module):

def __init__(self):
    super(CountRNN, self).__init__()

    self.rnn = torch.nn.RNN(1, 20,num_layers=1, batch_first=True)
    self.fc = torch.nn.Linear(20, 1)


def forward(self, x):        
    full_out, last_out = self.rnn(x)
    return self.fc(last_out)


nnet = CountRNN()

criterion = torch.nn.MSELoss(reduction='sum')

optimizer = torch.optim.Adam(nnet.parameters(), lr=0.0005)

batch_size = 100

batches = 10000 * 1000

printout = max(batches //(20* 1000),1)

for t in range(batches):

optimizer.zero_grad()

x_batch = torch.unsqueeze(torch.from_numpy(rnd_io()).float(),0)

y_batch = torch.unsqueeze(torch.sum(x_batch),0)

output = nnet.forward(x_batch) 

loss = criterion(output, y_batch)

if t % printout == 0:
    print('step : ' , t , 'loss : ' , loss.item())  
    torch.save(nnet.state_dict(), './rnn_summ.pth')  

loss.backward()

optimizer.step()
0
user8426627