Wie kann man mit Keras die zukünftigen Werte des Zeithorizonts vorhersagen?

11

Ich habe gerade dieses neuronale LSTM-Netzwerk mit Keras aufgebaut

    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()

dann erzeugt es dieses Ergebnis: Vorhersage der Testdaten

Nachdem ich ein gutes Modell für die historischen Daten erstellt und trainiert habe, weiß ich nicht, wie ich die Vorhersage für zukünftige Werte erstellen kann. Zum Beispiel die Nachfrage der nächsten 10 Tage. Daten sind täglich.

Dies ist ein Beispiel für die Form der Daten

NB: Dies ist ein Beispiel für die Form der Daten, das Grün ist die Beschriftung und das Gelb sind die Merkmale.
Nach dropna()(Löschen von Nullwerten) bleiben 100 Datenzeilen, ich habe 80 im Training und die 20 im Test verwendet.

Nbenz
quelle
Wie viele Instanzen haben Sie, wenn Sie Ihre Zeitreihen aufteilen?
JahKnows
Entschuldigung, Sir, ich habe Sie nicht, können Sie mehr erklären? danke
Nbenz
Wie viele Beispielzeilen haben Sie, nachdem Sie Ihre Daten für ein Prognoseproblem umstrukturiert haben?
JahKnows
Können Sie mir eine einzelne zeitliche Abfolge von Punkten geben und ich werde Ihnen zeigen, wie Sie mit ihnen Prognosen erstellen können.
JahKnows
Sie können die Frage, die ich bearbeitet habe, erneut überprüfen, indem Sie ein Beispiel für das Datenformat und die Datenform hinzufügen. danke
Nbenz

Antworten:

3
Diese Antwort geht ein bisschen in eine andere Richtung, aber ich hoffe, sie beantwortet immer noch Ihre Frage. Es verwendet die Idee einer rollierenden Prognose.

Da Sie das Wort Horizont verwenden , gehe ich davon aus, dass Sie zu einem bestimmten Zeitpunkt 10 Tage in die Zukunft vorhersagen möchten. Es gibt einige Möglichkeiten, dies zu tun. Bei dieser Art von Zeitreihenproblemen wird häufig davon ausgegangen, dass nur eine bestimmte Historie die nächsten Zeitschritte beeinflusst (wobei saisonale Effekte vernachlässigt werden).

Beispiel in Worten:

In Ihrem Fall können Sie also beispielsweise die vorherigen 60 Tage verwenden und die nächsten 10 vorhersagen. Am Beispiel Ihrer 100 Datenzeilen bedeutet dies, dass Sie tatsächlich (100 - 60 - 9) = 31Vorhersagen treffen können , wobei jede Vorhersage 10 Zeitschritte voraus ist (wir benötigen diese 31 prädiktive_Blöcke später). Aus 100 Reihen verlieren wir die ersten 60, um das erste Modell zu passen. Von den verbleibenden 40 Datenzeilen können wir 10 Schritte voraussagen (Zeilen 61-70), dann verschieben wir das Ganze eine Zeile weiter und wiederholen es. Die letzte Vorhersage von 10 zukünftigen Punkten wäre für die Zeilen 91-100. Danach können wir keine 10 Schritte mehr vorhersagen, also hören wir auf - und deshalb müssen wir diese zusätzlichen 9 subtrahieren. [Es gibt natürlich Möglichkeiten, die Vorhersage fortzusetzen, um alle Daten zu verwenden]

Beispiel mit tausend Worten:

Lassen Sie mich das Bild malen; um die Idee einer sich verschiebenden Fenstervorhersage zu erklären.

Für jeden Zugsatz (z. B. von t=0bis t=5in Rot - Zugsatz 1) möchten Sie die folgenden H Zeitschritte vorhersagen (entsprechend t = 6 in Orange - Testsatz 1). In diesem Fall ist Ihr Horizont einfach einer, dh H=1.

Grundlegende Skizze einer rollierenden Out-of-Sample-Prognose

Soweit ich weiß, möchten Sie die nächsten 10 Tage vorhersagen, was bedeutet, dass Sie sie benötigen H=10.

Um dies anhand Ihres Beispiels zu versuchen, müssen Sie meines Erachtens zwei Änderungen vornehmen.

Ändern Sie # 1

Die Form Ihres Zuges und Ihrer Testsets muss dem neuen Horizont entsprechen. Jedes Beispiel Ihrer Modelleingabe (das x_trainund x_testkann das gleiche wie zuvor bleiben. Jedes Beispiel in Ihrem Testsatz muss jedoch die nächsten H=10Werte des Etiketts enthalten, nicht nur einen einzelnen Wert.

Hier ist ein grobes Beispiel dafür, wie Sie dies tun könnten:

# 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)

Da Sie Tests außerhalb der Stichprobe durchführen, sind Ihre Vorhersagen bereits interessant zu analysieren. Sobald dies ausgeführt wird, können Sie die entsprechenden Testdatensätze mit den neuen Daten erstellen, die Sie erwähnt haben.

Ohne Ihre Daten zu gut zu kennen, weiß ich nicht, ob Sie die y-Werte derselben Zeile wie die Eingabe oder der folgenden Zeile vorhersagen sollten. Abhängig von Ihren Daten können Sie außerdem die vergangenen Werte von yin jeden der x_trainBlöcke aufnehmen. In diesem Fall würden Sie einfach xfür den gesamten Tisch tauschen, dh data[cols]wo new_cols = ['Demand'] + cols.

Ändern Sie # 2

Sie müssen dafür sorgen, dass das Modell diesen Horizont widerspiegelt, indem Sie es zu Ausgabewerten zwingen H.

Hier ist ein Beispiel für die Angabe des Modells:

# 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!

Hinweis: In Ihrer Modellspezifikation müssen Sie die endgültige lineare ActivationEbene nicht hinzufügen , da die vorhergehende dichte Ebene standardmäßig eine lineare Aktivierung enthält. Siehe die ausgezeichnete Dokumentation hier .

Dies ist ein großes Thema und es gibt viele Dinge, die Sie ausprobieren können. Ich stimme den Kommentaren zu Ihrer Frage zu, dass Sie viel mehr Daten benötigen, damit ein RNN eine aussagekräftige Darstellung des Modells erstellen kann.

Wenn Sie dies nicht nur tun, um mehr über LSTMs usw. zu erfahren, besteht ein weiterer praktischer Ansatz darin, einfachere Zeitreihenmodelle wie ein ARIMA-Modell zu untersuchen (lassen Sie sich nicht von dem komplizierten Namen einschüchtern - es ist viel einfacher als ein LSTM). . Solche Modelle können mit Python ganz einfach erstellt werden, indem das Paket statsmodels verwendet wird , das eine nette Implementierung hat .

n1k31t4
quelle