L'entrée du calque séquentiel est incompatible avec le calque: erreur de formes dans LSTM

Dec 22 2020

Je suis nouveau dans les réseaux de neurones et je souhaite les utiliser pour comparer avec d'autres méthodes d'apprentissage automatique. J'ai une série chronologique de données multivariées avec une plage d'environ deux ans. Je veux prédire «y» pour les prochains jours en fonction des autres variables utilisant LSTM. Le dernier jour de mes données est le 31/07/2020.

df.tail()

              y   holidays  day_of_month    day_of_week month   quarter
   Date                     
 2020-07-27 32500      0      27                 0        7        3
 2020-07-28 33280      0      28                 1        7        3
 2020-07-29 31110      0      29                 2        7        3
 2020-07-30 37720      0      30                 3        7        3
 2020-07-31 32240      0      31                 4        7        3

Pour entraîner le modèle LSTM, j'ai également divisé les données en données de train et de test.

from sklearn.model_selection import train_test_split
split_date = '2020-07-27' #to predict the next 4 days
df_train = df.loc[df.index <= split_date].copy()
df_test = df.loc[df.index > split_date].copy()
X1=df_train[['day_of_month','day_of_week','month','quarter','holidays']]
y1=df_train['y']
X2=df_test[['day_of_month','day_of_week','month','quarter','holidays']]
y2=df_test['y']

X_train, y_train =X1, y1
X_test, y_test = X2,y2

Étant donné que je travaille avec LSTM, une mise à l'échelle est nécessaire:

scaler = MinMaxScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)

Passons maintenant à la partie difficile: le modèle.

num_units=50
activation_function = 'sigmoid'
optimizer = 'adam'
loss_function = 'mean_squared_error'
batch_size = 10
num_epochs = 100

 # Initialize the RNN
regressor = Sequential()

 # Adding the input layer and the LSTM layer
regressor.add(LSTM(units = num_units, return_sequences=True ,activation = activation_function, 
input_shape=(X_train.shape[1], 1)))

 # Adding the output layer
regressor.add(Dense(units = 1))

 # Compiling the RNN
regressor.compile(optimizer = optimizer, loss = loss_function)

# Using the training set to train the model
regressor.fit(X_train_scaled, y_train, batch_size = batch_size, epochs = num_epochs)

Cependant, je reçois l'erreur suivante:

ValueError: Input 0 of layer sequential_11 is incompatible with the layer: expected ndim=3, found 
ndim=2. Full shape received: [None, 5]

Je ne comprends pas comment nous choisissons les paramètres ou la forme de l'entrée. J'ai vu des vidéos et lu des pages Github et tout le monde semble exécuter LSTM d'une manière différente, ce qui le rend encore plus difficile à mettre en œuvre. L'erreur précédente vient probablement de la forme, mais à part ça, tout le reste est-il correct? Et comment puis-je résoudre ce problème? Merci

EDIT: Cette question similaire ne résout pas mon problème .. J'ai essayé la solution à partir de là

x_train = X_train_scaled.reshape(-1, 1, 5)
x_test  = X_test_scaled.reshape(-1, 1, 5)

(Mon X_test et y_test n'ont qu'une seule colonne). Et la solution ne semble pas non plus fonctionner. J'obtiens cette erreur maintenant:

ValueError: Input 0 is incompatible with layer sequential_22: expected shape= 
(None, None, 1), found shape=[None, 1, 5]

Réponses

2 YoanB.M.Sc Dec 22 2020 at 21:18

CONTRIBUTION:

Le problème est que vous modélisez une entrée de forme 3D (batch, sequence, features)mais que vous êtes en X_trainfait une tranche de bloc de données, donc un tableau 2D:

X1=df_train[['day_of_month','day_of_week','month','quarter','holidays']]
X_train, y_train =X1, y1

Je suppose que vos colonnes sont censées être vos fonctionnalités, donc ce que vous feriez généralement, c'est "empiler des tranches" de votre df pour que vous X_trainressembliez à quelque chose comme ça:

Voici un ensemble de données 2D factice de forme (15,5):

data = np.zeros((15,5))

array([[0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0.]])

Vous pouvez le remodeler pour ajouter une dimension de lot, par exemple (15,1,5):

data = data[:,np.newaxis,:] 

array([[[0., 0., 0., 0., 0.]],

       [[0., 0., 0., 0., 0.]],

       [[0., 0., 0., 0., 0.]],

       [[0., 0., 0., 0., 0.]],

       [[0., 0., 0., 0., 0.]],

       [[0., 0., 0., 0., 0.]],

       [[0., 0., 0., 0., 0.]],

       [[0., 0., 0., 0., 0.]],

       [[0., 0., 0., 0., 0.]],

       [[0., 0., 0., 0., 0.]],

       [[0., 0., 0., 0., 0.]],

       [[0., 0., 0., 0., 0.]],

       [[0., 0., 0., 0., 0.]],

       [[0., 0., 0., 0., 0.]],

       [[0., 0., 0., 0., 0.]]])

Mêmes données, mais présentées d'une manière différente. Maintenant, dans cet exemple, batch = 15et sequence = 1, je ne sais pas quelle est la longueur de la séquence dans votre cas, mais cela peut être n'importe quoi.

MAQUETTE :

Maintenant dans votre modèle, keras input_shapeattendez (batch, sequence, features)-vous à ce que vous réussissiez ceci:

input_shape=(X_train.shape[1], 1)

Voici ce que vous modélisez: (None, Sequence = X_train.shape[1] , num_features = 1) Nonec'est pour la dimension du lot. Je ne pense pas que ce soit ce que vous essayez de faire une fois que vous avez remodelé, vous devriez également corriger input_shapepour correspondre au nouveau tableau.

1 mujjiga Dec 24 2020 at 21:27

C'est un problème de régression multivariée que vous résolvez en utilisant LSTM. Avant de sauter dans le code, voyons ce que cela signifie

Énoncé du problème:

  • Vous avez des 5fonctionnalités holidays, day_of_month, day_of_week,month,quarterpar jour pendant des kjours
  • Pour n'importe quel jour n, étant donné les caractéristiques des derniers 'm' jours, vous voulez prédire le jour ydu nème jour

Création d'un jeu de données de fenêtre:

  • Nous devons d'abord décider du nombre de jours que nous voulons donner à notre modèle. C'est ce qu'on appelle la longueur de la séquence (fixons-la à 3 pour cet exemple).
  • Nous devons diviser les jours de longueur de séquence pour créer l'ensemble de données de train et de test. Cela se fait en utilisant une fenêtre coulissante où la taille de la fenêtre est la longueur de la séquence.
  • Comme vous pouvez le voir, il n'y a pas de prédictions disponibles pour les derniers penregistrements où pest la longueur de la séquence.
  • Nous ferons les créations de jeux de données de fenêtre en utilisant la timeseries_dataset_from_arrayméthode.
  • Pour plus d'informations, suivez les documents officiels de tf .

Modèle LSTM

Donc, en images, ce que nous voulons réaliser est montré ci-dessous:

Pour chaque déroulement de cellule LSTM, nous passons dans les 5 caractéristiques de la journée, et nous déroulons dans le mtemps où mest la longueur de la séquence. Nous prédisons yle dernier jour.

Code:

import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers, models
import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split

# Model
regressor =  models.Sequential()
regressor.add(layers.LSTM(5, return_sequences=True))
regressor.add(layers.Dense(1))
regressor.compile(optimizer='sgd', loss='mse')

# Dummy data
n = 10000
df = pd.DataFrame(
    {
      'y': np.arange(n),
      'holidays': np.random.randn(n),
      'day_of_month': np.random.randn(n),
      'day_of_week': np.random.randn(n),
      'month': np.random.randn(n),
      'quarter': np.random.randn(n),     
    }
)

# Train test split
train_df, test_df = train_test_split(df)
print (train_df.shape, test_df.shape)\

# Create y to be predicted 
# given last n days predict todays y

# train data
sequence_length = 3
y_pred = train_df['y'][sequence_length-1:].values
train_df = train_df[:-2]
train_df['y_pred'] = y_pred

# Validataion data
y_pred = test_df['y'][sequence_length-1:].values
test_df = test_df[:-2]
test_df['y_pred'] = y_pred

# Create window datagenerators

# Train data generator
train_X = train_df[['holidays','day_of_month','day_of_week','month','month']]
train_y = train_df['y_pred']
train_dataset = tf.keras.preprocessing.timeseries_dataset_from_array(
    train_X, train_y, sequence_length=sequence_length, shuffle=True, batch_size=4)

# Validation data generator
test_X = test_df[['holidays','day_of_month','day_of_week','month','month']]
test_y = test_df['y_pred']
test_dataset = tf.keras.preprocessing.timeseries_dataset_from_array(
    test_X, test_y, sequence_length=sequence_length, shuffle=True, batch_size=4)

# Finally fit the model
regressor.fit(train_dataset, validation_data=test_dataset, epochs=3)

Production:

(7500, 6) (2500, 6)
Epoch 1/3
1874/1874 [==============================] - 8s 3ms/step - loss: 9974697.3664 - val_loss: 8242597.5000
Epoch 2/3
1874/1874 [==============================] - 6s 3ms/step - loss: 8367530.7117 - val_loss: 8256667.0000
Epoch 3/3
1874/1874 [==============================] - 6s 3ms/step - loss: 8379048.3237 - val_loss: 8233981.5000
<tensorflow.python.keras.callbacks.History at 0x7f3e94bdd198>