web-dev-qa-db-fra.com

Prédire un pas de temps en avant multiple d'une série temporelle à l'aide de LSTM

Je veux prédire certaines valeurs prévisibles chaque semaine (faible RSB). Je dois prédire toute la série chronologique d'une année formée par les semaines de l'année (52 valeurs - Figure 1)

 Figure 1: Year time series by week

Ma première idée était de développer un modèle LSTM multiple (figure 2) à l'aide de Keras sur TensorFlow. J'entraîne le modèle avec une couche d'entrée 52 (la série chronologique donnée de l'année précédente) et une couche de sortie prévue 52 (la série temporelle de l'année suivante). Train_X a la forme (X_examples, 52, 1), en d’autres termes, X_examples à former, 52 empreintes de pas de 1 entité chacune. Je comprends que Keras considérera les 52 entrées comme une série temporelle du même domaine. La forme du train_Y est la même (y_examples, 52, 1). J'ai ajouté une couche TimeDistributed. Je pensais que l'algorithme prédirait les valeurs sous forme de série temporelle au lieu de valeurs isolées (ai-je raison?)

Le code du modèle en keras est:

y = y.reshape(y.shape[0], 52, 1)
X = X.reshape(X.shape[0], 52, 1)
# design network
model = Sequential()
model.add(LSTM(n_neurons, input_shape=(X.shape[1], X.shape[2]), return_sequences=True))
model.add(TimeDistributed(Dense(1)))
model.compile(loss='mean_squared_error', optimizer='adam')
# fit network
model.fit(X, y, epochs=n_epochs, batch_size=n_batch, verbose=2)

 Figure 2: Many-to-many LSTM architecture

Le problème est que l'algorithme n'apprend pas l'exemple. Il prédit des valeurs très similaires aux valeurs des attributs. Est-ce que je modélise correctement le problème? 

Deuxième question: Une autre idée est d’entraîner l’algorithme avec 1 entrée et 1 sortie, mais comment puis-je prédire toute la série chronologique de 2015 sans regarder dans «1 entrée»? Les données de test auront une forme différente de celle des données d'apprentissage.

10
Lucas Brito

Partageant les mêmes préoccupations concernant le manque de données, vous pouvez le faire comme ceci.

Premièrement, c'est une bonne idée de garder vos valeurs entre -1 et +1, donc je les normaliserais en premier. 

Pour le modèle LSTM, vous devez vous assurer que vous utilisez return_sequences=True.
Il n’ya rien de «faux» dans votre modèle, mais il peut avoir besoin de plus ou moins de couches ou d’unités pour atteindre vos objectifs. (Il n'y a pas de réponse claire à cela, cependant). 

Former le modèle pour prédire la prochaine étape:

Tout ce dont vous avez besoin est de passer Y comme un X décalé:

entireData = arrayWithShape((samples,52,1))
X = entireData[:,:-1,:]
y = entireData[:,1:,:]

Entraînez le modèle à l'aide de ceux-ci.

Prédire le futur:

Maintenant, pour prédire l'avenir, puisque nous devons utiliser des éléments prédits comme entrées pour plus d'éléments prédits, nous allons utiliser une boucle et rendre le modèle stateful=True.

Créez un modèle égal au précédent avec les modifications suivantes:

  • Toutes les couches LSTM doivent avoir stateful=True 
  • La forme de l'entrée de lot doit être (batch_size,None, 1) - Cela permet des longueurs variables

Copiez les poids du modèle précédemment formé:

newModel.set_weights(oldModel.get_weights())

Ne prédisez qu'un échantillon à la fois et n'oubliez jamais d'appeler model.reset_states() avant de commencer une séquence.

Commencez par prédire avec la séquence que vous connaissez déjà (ceci assurera que le modèle prépare correctement ses états pour prédire l'avenir)

model.reset_states()
predictions = model.predict(entireData)

De la manière dont nous nous sommes entraînés, la dernière étape des prédictions sera le premier élément futur:

futureElement = predictions[:,-1:,:]

futureElements = []
futureElements.append(futureElement)

Maintenant, nous faisons une boucle où cet élément est l’entrée. (En raison de stateful, le modèle comprendra que c'est une nouvelle étape d'entrée de la séquence précédente au lieu d'une nouvelle séquence) 

for i in range(howManyPredictions):
    futureElement = model.predict(futureElement)
    futureElements.append(futureElement)

Ce lien contient un exemple complet prédisant l’avenir de deux fonctions: https://github.com/danmoller/TestRepo/blob/master/TestBookLSTM.ipynb

13
Daniel Möller

J'ai des données de 10 ans. Si mes données de formation sont les suivantes: valeurs de 4 semaines pour prédire la 5ème et que je continue à changer, je peux avoir près de 52 X 9 exemples pour former le modèle et 52 pour prédire (année dernière)

Cela signifie en réalité que vous ne disposez que de 9 exemples de formation avec 52 fonctionnalités chacun (à moins que vous ne souhaitiez vous entraîner sur des données d'entrée qui se chevauchent fortement). Quoi qu’il en soit, je ne pense pas que cela suffise à justifier une formation LSTM

Je suggérerais d'essayer un modèle beaucoup plus simple. Vos données d’entrée et de sortie ont une taille fixe. Vous pouvez donc essayer sklearn.linear_model.LinearRegression , qui gère plusieurs entités en entrée (dans votre cas 52) par exemple d’entraînement et plusieurs cibles (également 52).

Mise à jour: Si vous devez utilisez un LSTM, puis consultez Réseau neuronal LSTM pour la prévision des séries temporelles , une implémentation KerasLSTM qui prend en charge plusieurs prédictions futures en même temps ou de façon itérative réintroduire chaque prédiction en entrée. Sur la base de vos commentaires, cela devrait être exactement ce que vous voulez.

L'architecture du réseau dans cette implémentation est la suivante:

model = Sequential()

model.add(LSTM(
    input_shape=(layers[1], layers[0]),
    output_dim=layers[1],
    return_sequences=True))
model.add(Dropout(0.2))

model.add(LSTM(
    layers[2],
    return_sequences=False))
model.add(Dropout(0.2))

model.add(Dense(
    output_dim=layers[3]))
model.add(Activation("linear"))

Cependant, je recommanderais quand même d’exécuter une régression linéaire ou peut-être un simple réseau à feed feed avec une couche cachée et de comparer la précision avec le LSTM. Surtout si vous prévoyez une sortie à la fois et que vous la réintroduisez comme entrée, vos erreurs pourraient facilement s'accumuler et vous donner de très mauvaises prédictions plus loin.

1
Imran