L'entrée du calque séquentiel est incompatible avec le calque: erreur de formes dans LSTM
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
CONTRIBUTION:
Le problème est que vous modélisez une entrée de forme 3D (batch, sequence, features)
mais que vous êtes en X_train
fait 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_train
ressembliez à 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 = 15
et 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_shape
attendez (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)
None
c'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_shape
pour correspondre au nouveau tableau.
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
5
fonctionnalitésholidays, day_of_month, day_of_week,month,quarter
par jour pendant desk
jours - Pour n'importe quel jour n, étant donné les caractéristiques des derniers 'm' jours, vous voulez prédire le jour
y
dun
è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
p
enregistrements oùp
est 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_array
mé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 m
temps où m
est la longueur de la séquence. Nous prédisons y
le 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>