Jak prognozować przyszłe wartości horyzontu czasowego za pomocą Keras?

11

Właśnie zbudowałem tę sieć neuronową LSTM za pomocą 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()

następnie generuje ten wynik: Prognozowanie danych testowych

Po zbudowaniu i przeszkoleniu dobrego modelu na danych historycznych nie wiem, jak wygenerować prognozę dla przyszłych wartości? Na przykład zapotrzebowanie na następne 10 dni. Dane są codziennie.

to jest przykład kształtu danych

Uwaga: jest to przykład kształtu danych, zielony to etykieta, a żółty to cechy.
po dropna()(usuń wartości zerowe) pozostaje 100 wierszy danych, użyłem 80 w szkoleniu i 20 w teście.

Nbenz
źródło
Kiedy dzielisz szereg czasowy, ile masz instancji?
JahKnows
Przepraszam, nie mam pana, czy możesz wyjaśnić więcej? dziękuję
Nbenz
Po zmianie struktury danych na problem z prognozowaniem, ile masz linii przykładów?
JahKnows,
Czy możesz podać mi jedną sekwencję czasową punktów, a pokażę ci, jak z nimi prognozować.
JahKnows,
Możesz ponownie sprawdzić pytanie, które edytowałem, dodając przykład formatu i kształtu danych. dzięki
Nbenz,

Odpowiedzi:

5
Ta odpowiedź idzie w innym kierunku, ale mam nadzieję, że nadal odpowiada na twoje pytanie. Wykorzystuje ideę kroczącej prognozy / prognozy.

Ponieważ używasz słowa horyzont , zakładam, że masz na myśli, że chcesz przewidzieć 10 dni w przyszłości na danym etapie czasu. Można to zrobić na kilka sposobów. W przypadku tego rodzaju problemu szeregów czasowych często przyjmuje się założenie, że tylko pewna historia wpłynie na kilka kolejnych kroków czasowych (pomijając efekty sezonowe).

Przykład słownie:

Więc w twoim przypadku możesz wykorzystać np. Poprzednie 60 dni i przewidzieć następne 10. Biorąc za przykład swoje 100 wierszy danych, oznacza to, że możesz faktycznie (100 - 60 - 9) = 31przewidywać każde przewidywanie 10 kroków w przód (będziemy potrzebować tych 31 przewidywania_bloki później). Ze 100 rzędów tracimy pierwsze 60 pasujących do pierwszego modelu. Z pozostałych 40 wierszy danych możemy przewidzieć 10 kroków do przodu (wiersze 61–70), a następnie przesuwać całość o jeden wiersz dalej i powtarzać. Ostatnia prognoza 10 przyszłych punktów dotyczyłaby rzędów 91–100. Po tym nie możemy już przewidzieć 10 kroków, więc przestajemy - i dlatego musimy odjąć te dodatkowe 9. [Istnieją oczywiście sposoby dalszego przewidywania, jak wykorzystać wszystkie dane]

Przykład z tysiącem słów:

Pozwól mi pomalować obraz; aby wyjaśnić ideę przewidywania zmiany okna.

Dla każdego zestawu pociągów (np. Od t=0do t=5na czerwono - zestaw 1) chcesz przewidzieć następujące kroki czasu H (odpowiadające t = 6 na pomarańczowo - zestaw testowy 1). W tym twój horyzont jest po prostu jeden tj H=1.

Podstawowy szkic prognozy braku próby

Z tego, co rozumiem, chciałbyś przewidzieć następne 10 dni, co oznacza, że ​​potrzebujesz H=10.

Aby wypróbować to na przykładzie, myślę, że musisz wprowadzić dwie zmiany.

Zmień nr 1

Kształt pociągu i zestawów testowych będzie musiał pasować do nowego horyzontu. Każda próbka danych wejściowych modelu ( x_traini x_testmoże pozostać taka sama jak poprzednio. Jednak każda próbka w zestawie testowym będzie musiała zawierać kolejne H=10wartości etykiety, a nie tylko jedną wartość.

Oto przybliżony przykład tego, jak możesz to zrobić:

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

Ponieważ wykonujesz testy poza próbą, twoje prognozy są już interesujące do analizy. Po uruchomieniu możesz utworzyć równoważne zestawy danych testowych z nowymi danymi, o których wspomniałeś.

Nie znając zbyt dobrze danych, nie wiem, czy powinieneś przewidywać wartości y tego samego wiersza, co danych wejściowych, czy następnego. Dodatkowo, w zależności od twoich danych, możesz dołączyć poprzednie wartości dla ykażdego z x_trainbloków. W takim przypadku po prostu zamieniłbyś xcały stół, tj . data[cols]Gdzie new_cols = ['Demand'] + cols.

Zmień nr 2

Musisz zmusić model do odzwierciedlenia tego horyzontu, zmuszając go do uzyskania Hwartości wyjściowych .

Oto przykład, jak określić model:

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

Uwaga: W specyfikacji modelu nie trzeba dodawać końcowej linii liniowej Activation, ponieważ poprzednia gęsta warstwa domyślnie zawiera aktywację liniową. Zobacz doskonałą dokumentację tutaj .

To duży temat i jest wiele rzeczy, które możesz wypróbować. Zgadzam się z komentarzami do twojego pytania, że ​​będziesz potrzebował znacznie więcej danych, aby RNN mógł reprezentować znaczenie modelu.

Jeśli nie robisz tego tylko po to, aby dowiedzieć się o LSTM itp., Innym praktycznym podejściem może być przyjrzenie się prostszym modelom szeregów czasowych, takim jak model ARIMA (nie zastraszaj się skomplikowaną nazwą - jest znacznie prostszy niż LSTM) . Takie modele można dość łatwo zbudować za pomocą Pythona, używając pakietu statsmodels , który ma niezłą implementację .

n1k31t4
źródło