如何使用Keras预测时间范围的未来值?


11

我刚刚用Keras 建立了LSTM神经网络

    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天的需求。每天都有数据。

这是数据如何成形的一个例子

注意:这是数据成形方式的一个示例,绿色是标签,黄色是要素。
dropna()(删除空值),它仍然是100个数据行,我用在训练80在测试的20。


分解时间序列时,您有多少个实例?
JahKnows

抱歉,先生,我不明白你的意思,你能再解释一下吗?谢谢
Nbenz 18'Apr 24'23

在针对预测问题重组了数据之后,您有多少行示例?
JahKnows

您能给我一个单一的时间点序列吗,我将向您展示如何进行积分预测。
JahKnows

您可以通过添加数据格式和形状的示例来再次检查我已对其进行编辑的问题。感谢
Nbenz '18

Answers:


5
这个答案有不同的方向,但我希望它仍然可以回答您的问题。它使用滚动预测/预测的思想。

因为您使用“ 地平线 ”一词,所以我假设您的意思是您希望在给定的时间步长预测未来10天。有几种方法可以做到这一点。对于这种时间序列问题,通常会做出这样的假设:只有特定历史会影响接下来的几个时间步长(忽略季节影响)。

用文字举例:

因此,在您的情况下,您可以使用例如前60天,并预测接下来的10天。以您的100行数据为例,这意味着您可以实际进行(100 - 60 - 9) = 31预测,每个预测都提前10个时间步长(我们将需要这些之后31个预测性区块)。从100行中,我们丢失了前60个以适合第一个模型。在剩余的40行数据中,我们可以预测10步(行61-70),然后将整个对象进一步移动一行并重复。10个未来点的最后预测将是第91-100行。之后,我们将无法再预测10个步骤,因此我们停止了-这就是为什么我们必须减去这9个步骤。[当然,还有使用所有数据的方法,可以继续进行预测。

一千个单词的示例:

让我画画。帮助解释窗口预测的想法。

对于每个列车组(例如,从t=0t=5红色-列车组1),您要预测以下H时间步长(对应于橙色中的t = 6-测试组1)。在这种情况下,您的视野仅仅是一个H=1

样本外滚动预测的基本示意图

据我了解,您希望预测未来10天的需求H=10

为了以您的示例进行尝试,我认为您需要进行两项更改。

变更#1

您的火车和测试仪的形状将需要与新的视野相匹配。模型输入的每个样本(x_trainx_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]where 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!

注意: 在模型规范中,您不需要添加最终的linear Activation,因为默认情况下,前面的Dense层默认包含线性激活。请参阅此处的出色文档

这是一个很大的话题,您可以尝试很多事情。我同意对您的问题的评论,即您将需要更多数据才能使RNN代表模型的意义。

如果您不只是要学习LSTM等,那么另一种实用的方法可能是研究更简单的时间序列模型,例如ARIMA模型(不要被复杂的名称所吓倒-它比LSTM更为简单) 。使用具有良好实现的statsmodels包,可以使用Python轻松构建此类模型。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.