Como prever os valores futuros do horizonte temporal com Keras?

11

Acabei de construir esta rede neural LSTM com 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()

então gera este resultado: Previsão nos dados de teste

Depois de criar e treinar um bom modelo com os dados históricos, não sei como posso gerar a previsão de valores futuros? Por exemplo, a demanda dos próximos 10 dias. Os dados são diários.

este é um exemplo de como os dados são modelados

Nota: este é um exemplo de como os dados são modelados, o verde é o rótulo e o amarelo são os recursos.
depois de dropna()(excluir valores nulos) permanecerem 100 linhas de dados, usei 80 no treinamento e 20 no teste.

Nbenz
fonte
Quando você divide suas séries temporais, quantas instâncias você tem?
JahKnows
Desculpe senhor, eu não tenho você, você pode explicar mais? obrigado
Nbenz
Depois de reestruturar seus dados para um problema de previsão, quantas linhas de exemplos você tem?
JahKnows
Você pode me dar uma única sequência de pontos e eu mostrarei como fazer previsões com eles.
precisa saber é o seguinte
Você pode verificar novamente a pergunta que eu editei, adicionando um exemplo do formato e da forma dos dados. graças
Nbenz

Respostas:

5
Esta resposta vai um pouco em uma direção diferente, mas espero que ainda responda à sua pergunta. Ele usa a ideia de uma previsão / previsão contínua.

Como você usa a palavra horizonte , assumirei que você quer dizer que gostaria de prever 10 dias no futuro em um determinado momento. Existem algumas maneiras de fazer isso. Com esse tipo de problema de série temporal, é comum supor que apenas uma determinada história influenciará os próximos passos (negligenciando os efeitos sazonais).

Exemplo em palavras:

Portanto, no seu caso, você pode usar, por exemplo, os 60 dias anteriores e prever os próximos 10. Tomando suas 100 linhas de dados como exemplo, isso significa que você pode realmente fazer (100 - 60 - 9) = 31previsões, cada previsão de 10 passos à frente (precisaremos destes 31 predictive_blocks mais tarde). De 100 linhas, perdemos os 60 primeiros para caber no primeiro modelo. Das 40 linhas de dados restantes, podemos prever 10 etapas à frente (linhas 61 a 70); depois, mudamos a coisa toda uma linha ainda mais e repetimos. A última previsão de 10 pontos futuros seria para as linhas 91-100. Depois disso, não podemos mais prever 10 etapas, então paramos - e é por isso que temos que subtrair esses 9. extras. [É claro que existem maneiras de continuar fazendo previsões, para usar todos os dados]

Exemplo com mil palavras:

Deixe-me pintar a imagem; para ajudar a explicar a ideia de uma previsão de mudança de janela.

Para cada conjunto de trens (por exemplo, de t=0para t=5no conjunto de trens vermelho 1), você deseja prever os seguintes intervalos de tempo H (correspondentes a t = 6 no conjunto de testes laranja 1). Neste, o seu horizonte é simplesmente um ie H=1.

Esboço básico de uma previsão fora da amostra

Pelo que entendi, você gostaria de prever os próximos 10 dias, o que significa que precisa H=10.

Para tentar fazer isso com o seu exemplo, acho que você precisará fazer duas alterações.

Alteração # 1

A forma do seu trem e conjuntos de teste precisará corresponder ao novo horizonte. Cada amostra da entrada do seu modelo ( x_traine x_testpode permanecer a mesma de antes. No entanto, cada amostra no seu conjunto de testes precisará conter os próximos H=10valores do rótulo, não apenas um valor único.

Aqui está um exemplo aproximado de como você pode fazer isso:

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

Como você está testando fora da amostra, suas previsões já são interessantes para analisar. Depois que isso for executado, você poderá criar os conjuntos de dados de teste equivalentes com os novos dados mencionados.

Sem conhecer seus dados muito bem, não sei se você deve prever os valores y da mesma linha que a entrada ou da linha seguinte. Além disso, dependendo dos seus dados, você pode incluir os valores passados ​​de yem cada um dos x_trainblocos. Nesse caso, você simplesmente trocaria xa tabela inteira data[cols], ou seja , onde new_cols = ['Demand'] + cols.

Alteração 2

Você precisará fazer o modelo refletir esse horizonte, forçando-o a gerar Hvalores.

Aqui está um exemplo de como especificar o modelo:

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

Nota: Na especificação do modelo, você não precisa adicionar o linear final Activation, pois a camada Densa anterior, por padrão, inclui uma ativação linear. Veja a excelente documentação aqui .

Este é um tópico importante e há muitas coisas que você pode experimentar. Concordo com os comentários da sua pergunta, de que você precisará de muito mais dados para permitir que uma RNN faça uma representação significativa do modelo.

Se você não está apenas fazendo isso para aprender sobre LSTMs etc., outra abordagem prática pode ser procurar modelos mais simples de séries temporais , como um modelo ARIMA (não se deixe intimidar pelo nome complicado - é muito mais simples que um LSTM) . Tais modelos podem ser construídos facilmente com o Python, usando o pacote statsmodels , que possui uma boa implementação .

n1k31t4
fonte