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)
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()