Comment prédire les valeurs futures de l'horizon temporel avec Keras?

11

Je viens de construire ce réseau neuronal LSTM avec Keras

    import numpy as np
    import pandas as pd 
    from sklearn import preprocessing
    from keras.layers.core import Dense, Dropout, Activation
    from keras.activations import linear
    from keras.layers.recurrent import LSTM
    from keras.models import Sequential
    from matplotlib import pyplot

    #read and prepare data from datafile
    data_file_name = "DailyDemand.csv"
    data_csv = pd.read_csv(data_file_name, delimiter = ';',header=None, usecols=[1,2,3,4,5])
    yt = data_csv[1:]
    data = yt
    data.columns = ['MoyenneTransactHier', 'MaxTransaction', 'MinTransaction','CountTransaction','Demand']
    # print (data.head(10))
    pd.options.display.float_format = '{:,.0f}'.format
    data = data.dropna ()
    y=data['Demand'].astype(int)
    cols=['MoyenneTransactHier', 'MaxTransaction', 'MinTransaction','CountTransaction']
    x=data[cols].astype(int)

    #scaling data
    scaler_x = preprocessing.MinMaxScaler(feature_range =(-1, 1))
    x = np.array(x).reshape ((len(x),4 ))
    x = scaler_x.fit_transform(x)
    scaler_y = preprocessing.MinMaxScaler(feature_range =(-1, 1))
    y = np.array(y).reshape ((len(y), 1))
    y = scaler_y.fit_transform(y)
    print("longeur de y",len(y))
    # Split train and test data
    train_end = 80
    x_train=x[0: train_end ,]
    x_test=x[train_end +1: ,]
    y_train=y[0: train_end]
    y_test=y[train_end +1:] 
    x_train=x_train.reshape(x_train.shape +(1,))
    x_test=x_test.reshape(x_test.shape + (1,))

    print("Data well prepared")
    print ('x_train shape ', x_train.shape)
    print ('y_train', y_train.shape)

    #Design the model - LSTM Network
    seed = 2016
    np.random.seed(seed)
    fit1 = Sequential ()
    fit1.add(LSTM(
        output_dim = 4,
        activation='tanh',
        input_shape =(4, 1)))
    fit1.add(Dense(output_dim =1))
    fit1.add(Activation(linear))
    #rmsprop or sgd
    batchsize = 1
    fit1.compile(loss="mean_squared_error",optimizer="rmsprop")
    #train the model
    fit1.fit(x_train , y_train , batch_size = batchsize, nb_epoch =20, shuffle=True)

    print(fit1.summary ())

    #Model error
    score_train = fit1.evaluate(x_train ,y_train ,batch_size =batchsize)
    score_test = fit1.evaluate(x_test , y_test ,batch_size =batchsize)
    print("in  train  MSE = ",round(score_train,4))
    print("in test  MSE = ",round(score_test ,4))

    #Make prediction
    pred1=fit1.predict(x_test)
    pred1 = scaler_y.inverse_transform(np.array(pred1).reshape ((len(pred1), 1)))
    real_test = scaler_y.inverse_transform(np.array(y_test).reshape ((len(y_test), 1))).astype(int)

    #save prediction
    testData = pd.DataFrame(real_test)
    preddData = pd.DataFrame(pred1)
    dataF = pd.concat([testData,preddData], axis=1)
    dataF.columns =['Real demand','Predicted Demand']
    dataF.to_csv('Demandprediction.csv')

    pyplot.plot(pred1, label='Forecast')
    pyplot.plot(real_test,label='Actual')
    pyplot.legend()
    pyplot.show()

puis il génère ce résultat: Prédiction sur les données de test

Après avoir construit et formé un bon modèle sur les données historiques, je ne sais pas comment générer la prédiction pour les valeurs futures? Par exemple, la demande des 10 prochains jours. Les données sont quotidiennes.

ceci est un exemple de la façon dont les données sont façonnées

NB: ceci est un exemple de la forme des données, le vert est l'étiquette et le jaune les caractéristiques.
après dropna()(supprimer les valeurs nulles), il reste 100 lignes de données, j'en ai utilisé 80 dans la formation et les 20 dans le test.

Nbenz
la source
Lorsque vous divisez votre série chronologique, combien d'instances avez-vous?
JahKnows
Désolé monsieur, je ne vous ai pas, pouvez-vous expliquer plus? merci
Nbenz
Après avoir restructuré vos données pour un problème de prévision, combien de lignes d'exemples avez-vous?
JahKnows
Pouvez-vous me donner une séquence temporelle unique de points et je vais vous montrer comment faire des prévisions avec eux.
JahKnows
Vous pouvez vérifier à nouveau la question que je l'ai modifiée en ajoutant un exemple du format et de la forme des données. merci
Nbenz

Réponses:

5
Cette réponse va un peu dans une direction différente, mais j'espère qu'elle répond toujours à votre question. Il utilise l'idée d'une prévision / prédiction continue.

Parce que vous utilisez le mot horizon , je suppose que vous voulez dire que vous aimeriez prévoir 10 jours dans le futur à un pas de temps donné. Il y a plusieurs façons de procéder. Avec ce type de problème de séries chronologiques, il est courant de supposer que seule une certaine histoire influencera les prochaines étapes temporelles (en négligeant les effets saisonniers).

Exemple en mots:

Donc, dans votre cas, vous pouvez utiliser, par exemple, les 60 derniers jours et prédire les 10 prochains. En prenant vos 100 lignes de données comme exemple, cela signifie que vous pouvez réellement faire des (100 - 60 - 9) = 31prédictions, chaque prédiction de 10 pas de temps à l'avance (nous en aurons besoin 31 blocs prédictifs plus tard). À partir de 100 rangs, nous perdons les 60 premiers pour s'adapter au premier modèle. Sur les 40 lignes de données restantes, nous pouvons prédire 10 pas en avant (lignes 61 à 70), puis nous déplaçons le tout une ligne plus loin et répétons. La dernière prédiction de 10 futurs points serait pour les lignes 91-100. Après cela, nous ne pouvons plus prédire 10 étapes, alors nous nous arrêtons - et c'est pourquoi nous devons soustraire ce 9. supplémentaire. [Il y a bien sûr des moyens de continuer à faire des prédictions, comme d'utiliser toutes les données]

Exemple avec mille mots:

Permettez-moi de peindre l'image; pour aider à expliquer l'idée d'une prédiction de fenêtre mobile.

Pour chaque train (par exemple de t=0à t=5en rouge - train 1), vous voulez prédire les pas de temps H suivants (correspondant à t = 6 en orange - jeu de test 1). En cela, votre horizon est simplement un ie H=1.

Croquis de base d'une prévision glissante hors échantillon

D'après ce que je comprends, vous souhaitez prédire les 10 prochains jours, ce qui signifie que vous avez besoin H=10.

Pour essayer cela avec votre exemple, je pense que vous devrez apporter deux modifications.

Changement # 1

La forme de votre train et de vos ensembles de tests devra correspondre au nouvel horizon. Chaque échantillon de votre entrée de modèle (le x_trainet x_testpeut rester le même qu'auparavant. Cependant, chaque échantillon de votre ensemble de test devra contenir les H=10valeurs suivantes de l'étiquette, pas seulement une seule valeur.

Voici un exemple approximatif de la façon dont vous pouvez procéder:

# Define our horizon
H = 10

# Create data split, using values from my example above
window_size = 60
num_pred_blocks = 31    # as computed above

# Loop over the train and test samples to create the sliding window sets
x_train = []
y_train = []
for i in range(num_pred_blocks):
    x_train_block = x_train[i:(i + window_size)]    # 31 blocks of 60 * num-columns
    x_train.append(x_train_block)
    y_train_block = y_train[(i + window_size):(i + window_size + H)]    # 31 blocks of 10 * 1
    y_train.append(y_train_block)

Parce que vous effectuez des tests hors échantillon, vos prévisions sont déjà intéressantes à regarder. Une fois que cela s'exécute, vous pouvez ensuite créer les jeux de données de test équivalents avec les nouvelles données que vous avez mentionnées.

Sans trop bien connaître vos données, je ne sais pas si vous devez prédire les valeurs y de la même ligne que l'entrée ou de la ligne suivante. De plus, en fonction de vos données, vous pouvez inclure les valeurs passées de ydans chacun des x_trainblocs. Dans ce cas, vous échangeriez simplement xla table entière, c'est-à-dire data[cols]new_cols = ['Demand'] + cols.

Changement # 2

Vous devrez faire en sorte que le modèle reflète cet horizon, en le forçant à afficher des Hvaleurs.

Voici un exemple de la façon de spécifier le modèle:

# Define our horizon
H = 10

# Create the model using the parameterised horizon
fit1 = Sequential ()
fit1.add(LSTM(output_dim = 4, activation='tanh', input_shape =(4, 1)))
fit1.add(Dense(output_dim=30, activation='sigmoid')
fit1.add(Dense(output_dim=H))    # our horizon is produced!

Remarque: Dans la spécification de votre modèle, vous n'avez pas besoin d'ajouter le linéaire final Activation, car la couche dense précédente comprend par défaut une activation linéaire. Voir l'excellente documentation ici .

C'est un gros sujet et il y a beaucoup de choses que vous pourriez essayer. Je suis d'accord avec les commentaires sur votre question, selon lesquels vous aurez besoin de beaucoup plus de données pour permettre à un RNN de faire une représentation significative du modèle.

Si vous ne faites pas cela uniquement pour en savoir plus sur les LSTM, etc., une autre approche pratique pourrait consister à étudier des modèles de séries chronologiques plus simples tels qu'un modèle ARIMA (ne vous laissez pas intimider par le nom compliqué - c'est beaucoup plus simple qu'un LSTM) . De tels modèles peuvent être construits assez facilement avec Python, en utilisant le package statsmodels , qui a une belle implémentation .

n1k31t4
la source