使用GRU,LSTM,Conv1D深度学习模型进行时间序列预测的多步输出

时间:2020-07-02 10:33:01

标签: keras lstm multi-step

我正在测试将深度学习应用于多元多步时间序列预测的不同方法,这些方法专门应用于使用天气数据的光伏发电预测。

我开发了一些模型,这些模型在以15分钟为增量来预测第二天的PV功率方面略有成功,即:ANN,LSTM和Conv1D。它们都在模型的末尾使用密集层,该密集层是所需输出的大小,以便生成所需长度的预测向量。昨晚我采访了一位有关该主题的专家,他对这种方法感到惊讶,并建议培训GRU-RNN以进行提前1步的预测,并使用for循环生成多个输出步骤。

现在我的问题是双重的,为什么我在互联网上找不到使用这种方法的人(我只是不擅长搜索?),我的监督员推测这种方法会导致不稳定的预测。但是我采访的专家建议在每个附加的预测步骤之后再进行一些网络培训。我发现远程接近的唯一资源是this one by Jason from machinelearningmastery

说实话,我不确定如何采取建议的方法。让我向您展示我到目前为止的情况(最后使用密集层来预测多个时间步长):

为简单起见,我使用时间分辨率为15分钟的单变量数据(仅是历史PV功率输出)。而且,我每天过滤掉任何数据点(最早的日出和最近的日落)为0,使我每天有80个季度的时间(实际上是81个小时,但是80无限方便得多)。我决定使用价值20天的历史光伏功率数据来训练模型。因此,当我制作滑动窗口时,它看起来像这样:x_train.shape = (394, 1600, 1), y_train.shape = (394, 80),测试集是相似的,但样本只有一半。我拥有三年的数据,因此我决定将去年全年作为测试集,以保持我的数据平衡(星期三,夏季天数相等)。我到处都读到LSTM需要3D输入张量的形状(batch_size,时间步长,特征),我相信我没有在这里犯错误。

另外,我同意,两年的数据应该有394个以上的样本,但是当您考虑到整个数据集中存在大量NaN扩散时(可怜的质量记录)。 (我删除了x或y都包含单个NaN的所有滑动窗口),确保所有滑动窗口都包含整天,这进一步将可用的滑动窗口减少了80倍。

出于完整性考虑,以下是我用来制作滑动窗口的代码:

def multivariate_data(dataset, target, start_index, end_index, history_size,
                      target_size, step, single_step=False):
  data = []
  labels = []

  start_index = start_index + history_size
  if end_index is None:
    end_index = len(dataset) - target_size

  for i in range(start_index, end_index, step):
    indices = range(i-history_size, i)
    data.append(dataset[indices])

    if single_step:
      labels.append(target[i+target_size])
    else:
      labels.append(target[i:i+target_size])

  return np.array(data), np.array(labels)

def remove_nan(X,Y):
    x = []
    y = []
    for sample in range(X.shape[0]):
        if np.isnan(X[sample,:,:]).any() | np.isnan(Y[sample,:]).any():
            None
        else:
            x.append(X[sample,:,:])
            y.append(Y[sample,:])
    x = np.array(x)
    y = np.array(y)
    return x, y

TARGET_COL = df[:,0]
HISTORY_SIZE = TIME_STEPS_PER_DAY * 20
TARGET_SIZE = TIME_STEPS_PER_DAY
STEP = TIME_STEPS_PER_DAY

x_train, y_train = multivariate_data(df, TARGET_COL, 0, TRAIN_TEST_SPLIT, HISTORY_SIZE, TARGET_SIZE, STEP)
x_test, y_test = multivariate_data(df, TARGET_COL, TRAIN_TEST_SPLIT, None, HISTORY_SIZE, TARGET_SIZE, STEP)

x_train, y_train = remove_nan(x_train, y_train)
x_test, y_test = remove_nan(x_test, y_test)

print('training input and output shape ' + str(x_train.shape), str(y_train.shape))
print('testing input and output shape ' + str(x_test.shape), str(y_test.shape))

这是LSTM模型,其末端具有致密层,可产生长度为80的向量,作为模型的预测。

initializer = keras.initializers.TruncatedNormal(mean=0., stddev=0.05)
bias = keras.initializers.Constant(0.1)

lstm = Sequential()
lstm.add(Input(shape = (x_train.shape[1], x_train.shape[2])))

lstm.add(LSTM(units = 1,
                   kernel_initializer = keras.initializers.Orthogonal(),
                   bias_initializer = keras.initializers.Constant(value=0.1),
                   kernel_regularizer = keras.regularizers.l1_l2(l1=1e-4, l2=1e-4),
                   return_sequences = True))

lstm.add(LSTM(units = 1,
                   kernel_initializer = keras.initializers.Orthogonal(),
                   bias_initializer = keras.initializers.Constant(value=0.1),
                   kernel_regularizer = keras.regularizers.l1_l2(l1=1e-4, l2=1e-4),
                   return_sequences = True))

lstm.add(Flatten())

lstm.add(Dense(units = 100,  activation = 'relu',
               kernel_initializer = initializer,
               bias_initializer = bias))

lstm.add(Dropout(rate = 0.2))

lstm.add(Dense(units = y_test.shape[1], activation = 'relu',
               kernel_initializer = initializer,
               bias_initializer = bias))

lstm.compile(loss = 'mse', optimizer = 'adam')
lstm.summary()

摘要如下:

Model: "sequential_38"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
lstm_48 (LSTM)               (None, 1600, 1)           12        
_________________________________________________________________
lstm_49 (LSTM)               (None, 1600, 1)           12        
_________________________________________________________________
flatten_43 (Flatten)         (None, 1600)              0         
_________________________________________________________________
dense_69 (Dense)             (None, 100)               160100    
_________________________________________________________________
dropout_42 (Dropout)         (None, 100)               0         
_________________________________________________________________
dense_70 (Dense)             (None, 80)                8080      
=================================================================
Total params: 168,204
Trainable params: 168,204
Non-trainable params: 0
_________________________________________________________________

让我怀疑自己做错了的两件奇怪的事情是,我尝试使用多个单位(> 5)的任何尝试都导致该模型仅学会预测数据集的平均PV功率。我在数据集中拥有的每个样本的日期。我发现的几乎所有指南或资源都对模型中的最后一个LSTM层使用return_sequences = False并将历史向量用作模型的输出,但这会导致上述问题。这种配置是迫使模型每天产生唯一的预测的唯一方法,而且模式也很精确。

It looks like this,当我绘制226个不同日期的预测时,彼此重叠。 I made another post about this problem on stackoverflow,但我们从未找到解决方案。如果您阅读并认为,那是白痴!他应该在做...,请告诉我!

0 个答案:

没有答案