Pourquoi la taille de lot LSTM de Keras utilisée pour la prédiction doit-elle être la même que la taille de lot ajustée?

lors de L'utilisation D'un LSTM de Keras pour prédire sur des données de séries chronologiques, j'ai eu des erreurs lorsque j'ai essayé de former le modèle en utilisant une taille de lot de 50, tout en essayant de prédire sur le même modèle en utilisant une taille de lot de 1 (c'est-à-dire en prédisant juste la valeur suivante).

pourquoi ne puis-je pas former et ajuster le modèle avec plusieurs lots à la fois, puis utiliser ce modèle pour prédire autre chose que la même taille de lot. Ça n'a pas l'air d'avoir du sens, mais alors je pourrais facilement être manque quelque chose à ce sujet.

Edit: c'est le modèle. batch_size 50, sl est la longueur de la séquence, qui est fixé à 20 actuellement.

    model = Sequential()
    model.add(LSTM(1, batch_input_shape=(batch_size, 1, sl), stateful=True))
    model.add(Dense(1))
    model.compile(loss='mean_squared_error', optimizer='adam')
    model.fit(trainX, trainY, epochs=epochs, batch_size=batch_size, verbose=2)

voici la ligne pour prédire sur le jeu de formation pour RMSE

    # make predictions
    trainPredict = model.predict(trainX, batch_size=batch_size)

voici la prédiction réelle des pas de temps invisibles

for i in range(test_len):
    print('Prediction %s: ' % str(pred_count))

    next_pred_res = np.reshape(next_pred, (next_pred.shape[1], 1, next_pred.shape[0]))
    # make predictions
    forecastPredict = model.predict(next_pred_res, batch_size=1)
    forecastPredictInv = scaler.inverse_transform(forecastPredict)
    forecasts.append(forecastPredictInv)
    next_pred = next_pred[1:]
    next_pred = np.concatenate([next_pred, forecastPredict])

    pred_count += 1

Ce problème est à la ligne:

forecastPredict = model.predict(next_pred_res, batch_size=batch_size)

l'erreur quand batch_size ici est défini à 1 est:

ValueError: Cannot feed value of shape (1, 1, 2) for Tensor 'lstm_1_input:0', which has shape '(10, 1, 2)' qui est la même erreur qui jette quand batch_size ici est fixée à 50 comme les autres tailles de lots.

L'erreur est:

    forecastPredict = model.predict(next_pred_res, batch_size=1)
  File "/home/entelechy/tf_keras/lib/python3.5/site-packages/keras/models.py", line 899, in predict
    return self.model.predict(x, batch_size=batch_size, verbose=verbose)
  File "/home/entelechy/tf_keras/lib/python3.5/site-packages/keras/engine/training.py", line 1573, in predict
    batch_size=batch_size, verbose=verbose)
   File "/home/entelechy/tf_keras/lib/python3.5/site-packages/keras/engine/training.py", line 1203, in _predict_loop
    batch_outs = f(ins_batch)
  File "/home/entelechy/tf_keras/lib/python3.5/site-packages/keras/backend/tensorflow_backend.py", line 2103, in __call__
    feed_dict=feed_dict)
  File "/home/entelechy/tf_keras/lib/python3.5/site-packages/tensorflow/python/client/session.py", line 767, in run
    run_metadata_ptr)
  File "/home/entelechy/tf_keras/lib/python3.5/site-packages/tensorflow/python/client/session.py", line 944, in _run
    % (np_val.shape, subfeed_t.name, str(subfeed_t.get_shape())))
ValueError: Cannot feed value of shape (1, 1, 2) for Tensor 'lstm_1_input:0', which has shape '(10, 1, 2)'

Edit: une Fois que j'ai mis le modèle à stateful=False alors je peux utiliser différentes tailles de lots pour l'ajustement / la formation et la prédiction. Quelle est la raison?

11
demandé sur McLeodx 2017-04-30 05:56:34

6 réponses

malheureusement, ce que vous voulez faire est impossible avec Keras ... J'ai aussi lutté beaucoup de temps sur ces problèmes et la seule façon est de plonger dans le trou de lapin et de travailler avec Tensorflow directement pour faire LSTM rolling prédiction.

D'abord, pour être clair sur la terminologie,batch_size signifie habituellement le nombre de séquences qui sont entraînées ensemble, et num_steps signifie Combien de pas de temps sont formés ensemble. Quand tu veux dire batch_size=1 et "juste prédire la valeur suivante", je pense que vous destiné à prédire avec num_steps=1.

Sinon, il doit être possible de s'entraîner et de prévoir avec batch_size=50 ce qui signifie que vous vous entraînez sur 50 séquences et faites 50 prédictions à chaque pas de temps, une pour chaque séquence (ce qui signifie formation/prédiction num_steps=1).

Cependant, je pense que ce que tu veux dire, c'est que vous souhaitez utiliser avec état LSTM pour former avec num_steps=50 et de faire de la prédiction avec num_steps=1. Théoriquement cela fait sens et devrait être possible, et cela est possible avec Tensorflow, tout simplement pas Keras.

Le problème: Keras exige une taille de lot explicite pour RNN. Vous devez spécifier batch_input_shape (batch_size, num_steps, les caractéristiques).

La raison: Keras doit attribuer un vecteur d'état caché de taille fixe dans le graphique de calcul avec la forme (batch_size, num_units) afin de maintenir les valeurs entre les lots de formation. D'autre part, lorsque stateful=False, le vecteur d'état caché peut être initialisé dynamiquement avec des zéros au début de chaque lot de sorte qu'il ne doit pas être une taille fixe. Plus de détails ici: http://philipperemy.github.io/keras-stateful-lstm/

Possible de contourner: Train et de prévoir avec num_steps=1. Exemple:https://github.com/keras-team/keras/blob/master/examples/lstm_stateful.py. Cela pourrait ne pas fonctionner du tout pour votre problème car le gradient pour la propagation arrière sera calculé sur un seul pas de temps. Voir: https://github.com/fchollet/keras/issues/3669

ma solution: utiliser Tensorflow: dans Tensorflow vous pouvez vous entraîner avec batch_size=50, num_steps=100, puis faites des prédictions avec batch_size=1, num_steps=1. Cela est possible en créant un graphique de modèle différent pour la formation et la prédiction partageant les mêmes matrices de poids RNN. Voir cet exemple pour la prédiction du prochain caractère:https://github.com/sherjilozair/char-rnn-tensorflow/blob/master/model.py#L11 et blog post http://karpathy.github.io/2015/05/21/rnn-effectiveness/. Notez qu'un graphique ne peut fonctionner qu'avec unbatch_size, mais vous pouvez configurer plusieurs modèles graphiques partageant les poids dans Tensorflow.

12
répondu Hai-Anh Trinh 2018-04-13 14:09:39

Malheureusement, ce que vous souhaitez est impossible parce que vous spécifiez le batch_size lorsque vous définissez le modèle... Cependant, j'ai trouvé un moyen simple de contourner ce problème: créer 2 modèles! Le premier est utilisé pour la formation et le second pour les prédictions, et leur faire partager des poids:

train_model = Sequential([Input(batch_input_shape=(batch_size,...),
<continue specifying your model>])

predict_model = Sequential([Input(batch_input_shape=(1,...),
<continue specifying exact same model>])

train_model.compile(loss='sparse_categorical_crossentropy', optimizer=Adam())
predict_model.compile(loss='sparse_categorical_crossentropy', optimizer=Adam())
train_model.save_weights('lstm_model.h5')
predict_model.load_weights('lstm_model.h5')

notez que vous souhaitez enregistrer et chargez les poids, et non l'ensemble du modèle (qui comprend l'architecture, l'optimiseur, etc...). De cette façon, vous obtenez le poids, mais vous pouvez saisir un lot à la fois... plus sur keras enregistrer/charger des modèles: https://keras.io/getting-started/faq/#how-can-i-save-a-keras-model

notez que vous devez installer h5py pour utiliser "save weights".

4
répondu Oren Matar 2017-05-28 14:40:08

une Autre solution est:

def create_model(batch_size):
    model = Sequential()
    model.add(LSTM(1, batch_input_shape=(batch_size, 1, sl), stateful=True))
    model.add(Dense(1))
    return model

model_train = create_model(batch_size=50)

model_train.compile(loss='mean_squared_error', optimizer='adam')
model_train.fit(trainX, trainY, epochs=epochs, batch_size=batch_size)

model_predict = create_model(batch_size=1)

weights = model_train.get_weights()
model_predict.set_weights(weights)
3
répondu josca 2017-09-05 11:47:59

j'ai trouvé ci-dessous utiles (et entièrement en ligne avec ci-dessus). La section "Solution 3: Copy Weights" a fonctionné pour moi:

Comment utiliser les Différentes Tailles de Lots lors de la Formation et de Prédire avec LSTMs, par Jason Brownlee

n_neurons = 10
# design network
model = Sequential()
model.add(LSTM(n_neurons, batch_input_shape=(n_batch, X.shape[1], X.shape[2]), stateful=True))
model.add(Dense(1))
model.compile(loss='mean_squared_error', optimizer='adam')
# fit network
for i in range(n_epoch):
    model.fit(X, y, epochs=1, batch_size=n_batch, verbose=1, shuffle=False)
    model.reset_states()
# re-define the batch size
n_batch = 1
# re-define model
new_model = Sequential()
new_model.add(LSTM(n_neurons, batch_input_shape=(n_batch, X.shape[1], X.shape[2]), stateful=True))
new_model.add(Dense(1))
# copy weights
old_weights = model.get_weights()
new_model.set_weights(old_weights)
# compile model
new_model.compile(loss='mean_squared_error', optimizer='adam')
0
répondu user2427317 2018-05-16 19:15:16

j'ai aussi le même problème et résolu.

d'une autre façon, vous pouvez enregistrer votre poids, lorsque vous testez votre résultat, vous pouvez recharger votre modèle avec la même architecture et set batch_size=1 comme ci-dessous:

 n_neurons = 10
 # design network
 model = Sequential()
 model.add(LSTM(n_neurons, batch_size=1, batch_input_shape=(n_batch,X.shape[1], X.shape[2]), statefull=True))
 model.add(Dense(1))
 model.compile(loss='mean_squared_error', optimizer='adam')
 model.load_weights("w.h5")

Il fonctionne bien. j'espère qu'il sera utile pour vous.

0
répondu Toàn Nguyễn 2018-06-22 10:17:10

la meilleure solution à ce problème est "copy Weights". Il peut être vraiment utile si vous voulez former et prédire avec votre modèle LSTM avec différentes tailles de lots.

par exemple, une fois que vous avez formé votre modèle avec la taille de lot 'n' Comme montré ci-dessous:

# configure network
n_batch = len(X)
n_epoch = 1000
n_neurons = 10
# design network
model = Sequential()
model.add(LSTM(n_neurons, batch_input_shape=(n_batch, X.shape[1], X.shape[2]), stateful=True))
model.add(Dense(1))
model.compile(loss='mean_squared_error', optimizer='adam')

et maintenant vous voulez prédire des valeurs inférieures à la taille de votre Lot où n=1.

ce que vous pouvez faire est que, Copier les poids de votre modèle fit et de réinitialiser le nouveau modèle LSTM modèle avec la même architecture et la taille de lot égale à 1.

# re-define the batch size
n_batch = 1
# re-define model
new_model = Sequential()
new_model.add(LSTM(n_neurons, batch_input_shape=(n_batch, X.shape[1], X.shape[2]),       stateful=True))
new_model.add(Dense(1))
# copy weights
old_weights = model.get_weights()
new_model.set_weights(old_weights)

pour plus d'information, veuillez lire: https://machinelearningmastery.com/use-different-batch-sizes-training-predicting-python-keras/

0
répondu Noman Dilawar 2018-07-04 08:13:08