首页 > 解决方案 > Keras LSTM 似乎适合时间序列输入的结尾而不是预测目标

问题描述

首先,我有丰富的 python 经验以及构建和使用机器学习网络的中等经验。话虽这么说,这是我制作的第一个 LSTM,除了一些可用的千篇一律的例子,因此感谢您的帮助。我觉得这是一个简单解决方案的问题,而且我只是看这段代码太久才看到它。

这个模型是在 python3.5 venv 中使用 Keras 和 tensorflow 后端制作的。

简而言之,我正在尝试使用数据本身以及这些数据的一些数学排列来预测一些时间数据,从而创建四个输入特征。我正在从之前的 60 个数据点构建时间序列输入,并将预测目标指定为未来的 60 个数据点。

完整训练数据的形状(输入)(目标):(2476224, 60, 4) (2476224)

单个数据“点”(输入)(目标)的形状:(1, 60, 4) (1)

似乎正在发生的事情是,经过训练的模型适合我的输入时间序列的尾随值(当前值),而不是我提供的目标(未来 60 个周期)。

有趣的是,损失函数似乎是根据正确的预测目标计算的,但模型并没有收敛到正确的解决方案。

我不知道为什么模型应该这样做。我的第一个想法是我错误地预处理了我的数据并提供了错误的目标。我已经广泛测试了我的数据输入格式,并且非常有信心我为模型提供了正确的目标和输入信息。

在一个例子中,我稍微提高了学习率,以使模型收敛到局部最小值。这种收敛的测试损失与我首选的学习率的损失非常相似(仍然很高)。但预测仍然是“当前值”。为什么会这样?

这是我创建模型的方式:

def create_model():
   lstm_model = Sequential()
   lstm_model.add(CuDNNLSTM(100, batch_input_shape=(batch_size, time_step, train_input.shape[2]),
                       stateful=True, return_sequences=True,
                       kernel_initializer='random_uniform'))
   lstm_model.add(Dropout(0.4))
   lstm_model.add(CuDNNLSTM(60))
   lstm_model.add(Dropout(0.4))
   lstm_model.add(Dense(20, activation='relu'))
   lstm_model.add(Dense(1, activation='linear'))
   optimizer = optimizers.Adagrad(lr=params["lr"])
   lstm_model.compile(loss='mean_squared_error', optimizer=optimizer)
   return lstm_model

这就是我预处理数据的方式。第一个函数 build_timeseries 构造了我的输入输出对。我相信这工作正常(但如果我错了,请纠正我)。第二个函数修剪对以适应批量大小。我对测试输入/目标做同样的事情。

train_input, train_target = build_timeseries(train_input, time_step, pred_horiz, 0)
train_input = trim_dataset(train_input, batch_size)
train_target = trim_dataset(train_target, batch_size)
def build_timeseries(mat, TIME_STEPS, PRED_HORIZON, y_col_index):
    # y_col_index is the index of column that would act as output column
    dim_0 = mat.shape[0]  # num datasets
    dim_1 = mat.shape[1]  # num features
    dim_2 = mat.shape[2]  # num datapoints

    # Reformatted matrix
    mat = mat.swapaxes(1, 2)

    x = np.zeros((dim_0*(dim_2-PRED_HORIZON), TIME_STEPS, dim_1))
    y = np.zeros((dim_0*(dim_2-PRED_HORIZON),))

    k = 0
    for i in range(dim_0):  # Iterate through datasets
        for j in range(TIME_STEPS, dim_2-PRED_HORIZON):
            x[k] = mat[i, j-TIME_STEPS:j]
            y[k] = mat[i, j+PRED_HORIZON, y_col_index]
            k += 1
    print("length of time-series i/o", x.shape, y.shape)
    return x, y

def trim_dataset(mat, batch_size):
    no_of_rows_drop = mat.shape[0] % batch_size
    if(no_of_rows_drop > 0):
        return mat[no_of_rows_drop:]
    else:
        return mat

最后,这就是我所说的实际模型。

history = model.fit(train_input, train_target, epochs=params["epochs"], verbose=2, batch_size=batch_size,
                    shuffle=True, validation_data=(test_input, test_target), callbacks=[es, mcp])

随着模型的收敛,我希望它能够预测接近我喂给它的指定目标的值。然而,相反,它的预测与时间序列数据的尾随值(或当前值)更接近。但是,另一方面,该模型似乎正在根据指定的目标评估损失......为什么它会以这种方式工作,我该如何解决它?任何帮助表示赞赏。

标签: pythonkerastime-serieslstmprediction

解决方案


推荐阅读