Как предсказать будущие значения временного горизонта с помощью Keras?

11

Я только что построил эту нейронную сеть LSTM с 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()

тогда это генерирует этот результат: Прогноз на тестовых данных

После построения и обучения хорошей модели на исторических данных, я не знаю, как я могу сгенерировать прогноз для будущих значений? Например спрос на ближайшие 10 дней. Данные ежедневно.

это пример того, как данные формируются

NB: это пример того, как данные формируются, зеленый - это метка, а желтый - это особенности.
после dropna()(удалить нулевые значения) остается 100 строк данных, я использовал 80 в обучении и 20 в тесте.

Nbenz
источник
Когда вы нарушаете свое время серию вверх, сколько экземпляров у вас есть?
JahKnows
Извините , сэр, я не получил вас, вы можете объяснить больше? спасибо
Nbenz
После того, как вы реструктурировали ваши данные для проблемы прогнозирования, сколько у вас примеров?
JahKnows
Можете ли вы дать мне одну временную последовательность точек, и я покажу вам, как делать прогнозирование с ними.
JahKnows
Вы можете проверить еще раз вопрос, который я редактировал, добавив пример формата данных и формы. спасибо
Nbenz

Ответы:

5
Этот ответ идет немного в другом направлении, но я надеюсь, что он все еще отвечает на ваш вопрос. Он использует идею скользящего прогноза / прогноза.

Поскольку вы используете слово « горизонт» , я предполагаю, что вы имеете в виду, что вы хотели бы предсказать 10 дней в будущем с заданным временным шагом. Есть несколько способов сделать это. При такой проблеме временных рядов принято делать предположение о том, что только следующие данные будут влиять на следующие несколько временных шагов (без учета сезонных эффектов).

Пример на словах:

Таким образом, в вашем случае вы можете использовать, например, предыдущие 60 дней и прогнозировать следующие 10. Если взять в качестве примера 100 строк данных, это означает, что вы можете делать (100 - 60 - 9) = 31прогнозы, каждый прогноз на 10 временных шагов вперед (нам понадобятся эти 31 предсказательный_блок позже). Из 100 рядов мы теряем первые 60, чтобы соответствовать первой модели. Из оставшихся 40 строк данных мы можем предсказать 10 шагов вперед (строки 61-70), затем мы сдвигаем все на одну строку дальше и повторяем. Последний прогноз 10 будущих точек будет для строк 91-100. После этого мы больше не можем прогнозировать 10 шагов, поэтому мы останавливаемся - и именно поэтому мы должны вычесть эти дополнительные 9. [Конечно, есть способы продолжить делать прогноз, используя все данные]

Пример с тысячей слов:

Позвольте мне нарисовать картину; чтобы помочь объяснить идею предсказания сдвига окна.

Для каждого набора поездов (например, с t=0по t=5в красный - набор поездов 1) вы хотите предсказать следующие H временных шагов (соответствующих t = 6 в оранжевом - тестовый набор 1). В этом, ваш горизонт просто один есть H=1.

Эскиз базового прогноза на основе выборки

Насколько я понимаю, вы хотели бы, чтобы предсказать , в ближайшие 10 дней, то есть вам нужно H=10.

Для того, чтобы попробовать это с вашим примером, я думаю, что вам нужно будет сделать два изменения.

Изменение № 1

Форма вашего поезда и тестовых наборов должна соответствовать новому горизонту. Каждый образец ввода вашей модели ( x_trainи x_testможет оставаться прежним. Однако каждый образец в вашем наборе тестов должен содержать следующие H=10значения метки, а не только одно значение.

Вот грубый пример того, как вы могли бы сделать это:

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

Поскольку вы проводите внеплановое тестирование, ваши прогнозы уже интересны для анализа. После этого вы можете создать эквивалентные наборы тестовых данных с новыми данными, которые вы упомянули.

Не зная ваших данных слишком хорошо, я не знаю, должны ли вы предсказывать значения y той же строки, что и входные данные, или следующей строки. Кроме того, в зависимости от ваших данных, вы можете включить прошлые значения yв каждый из x_trainблоков. В этом случае вы бы просто поменяли xвсю таблицу, т.е. data[cols]где new_cols = ['Demand'] + cols.

Изменение № 2

Вам нужно будет заставить модель отражать этот горизонт, заставляя ее выводить Hзначения.

Вот пример того, как указать модель:

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

Примечание. В спецификации модели не требуется добавлять конечную линейную Activationлинию, поскольку предыдущий слой Dense по умолчанию включает линейную активацию. Смотрите отличную документацию здесь .

Это большая тема, и есть много вещей, которые вы можете попробовать. Я согласен с комментариями по вашему вопросу, что вам понадобится намного больше данных, чтобы RNN мог представить смысл модели.

Если вы не просто делаете это, чтобы узнать о LSTM и т. Д., Другим практическим подходом может быть изучение более простых моделей временных рядов, таких как модель ARIMA (не пугайтесь сложного имени - это намного проще, чем LSTM) , Такие модели можно легко построить с помощью Python, используя пакет statsmodels , который имеет хорошую реализацию .

n1k31t4
источник