我使用机器学习(尝试过Tensorflow和Tflearn库,后者我知道只是Tensorflow的封装)来预测未来一周某个区域的拥堵情况(如果你想了解更多背景,可以查看我之前的问题)。我的训练集由400K条标记的条目组成(每条记录包含日期和每分钟的拥堵值)。
我的问题是现在预测和现实之间存在时间差距。
如果我画一个图表来展示现实和预测,你会发现我的预测虽然与现实的形状相同,但却是提前的。它在现实之前就开始增加/减少。这让我开始思考我的训练可能存在问题。看起来我的预测并没有在我训练结束时开始。
我的两个数据集(训练/测试)位于两个不同的文件中。首先,我在训练集上进行训练(为了方便起见,假设它在第100分钟结束,我的测试集从第101分钟开始),一旦我的模型保存,我就会进行预测,通常它应该从第101分钟开始预测,还是我哪里错了?因为看起来它在我的训练停止后很久才开始预测(如果继续我的例子,它会从第107分钟的值开始预测)。
目前,一个不太好的解决方法是从训练集中删除与延迟相同数量的值(以这个例子来说,就是7个),这样做确实有效,不再有延迟,但我不知道为什么会出现这个问题,或者如何修复它以防止以后再次发生。
根据在不同网站上找到的一些建议,似乎我的训练数据集中存在间隙(在这种情况下是缺少时间戳)可能是问题所在。确实有一些间隙(总共大约7到9%的数据集缺失),我使用Pandas添加了缺失的时间戳(我还为它们赋予了最后已知时间戳的拥堵值),虽然我认为这可能有了一些帮助(间隙变小了),但问题并没有解决。
我尝试了多步预测、多变量预测、LSTM、GRU、MLP、Tensorflow、Tflearn,但这些都没有改变,让我认为问题可能出在我的训练上。以下是我的模型训练代码。
def fit_lstm(train, batch_size, nb_epoch, neurons): X, y = train[:, 0:-1], train[:, -1] X = X.reshape(X.shape[0], 1, X.shape[1]) print X.shape print y.shape model = Sequential() model.add(LSTM(neurons, batch_input_shape=(None, X.shape[1], X.shape[2]), stateful=False)) model.add(Dense(1)) model.compile(loss='mean_squared_error', optimizer='adam') for i in range(nb_epoch): model.fit(X, y, epochs=1, batch_size=batch_size, verbose=0, shuffle=False) model.reset_states() return model
两个形状是:
(80485, 1, 1)
(80485,)
(在这个例子中,我只使用了8万条数据作为训练集,以提高速度)。
我使用的参数是1个神经元,批量大小为64,5个epoch。我的数据集由两个文件组成。第一个是训练文件,包含两列:
timestamp | values
第二个文件形状相同,但属于测试集(分开以避免对预测产生任何影响),该文件仅在所有预测完成后使用,用于比较现实和预测。测试集从训练集停止的地方开始。
你有关于这个问题可能原因的想法吗?
编辑:在我的代码中,我有这个函数:
# 反转差分 yhat = inverse_difference(raw_values, yhat, len(test_scaled)+1-i)# 反转差分值def inverse_difference(history, yhat, interval=1): return yhat + history[-interval]
它应该用于反转差分(从缩放值转换为真实值)。当像粘贴的例子中那样使用它(使用测试集)时,我得到了完美的结果,准确率超过95%,没有间隙。
由于在现实中我们不会知道这些值,我不得不进行更改。我首先尝试使用训练集,但遇到了本文中解释的问题:
为什么会这样?对这个问题有解释吗?
回答:
找到了问题所在。问题出在“def inverse_difference(history, yhat, interval=1):”函数上。实际上,它使我的结果看起来像是我的训练的最后几行。这就是为什么我有间隙,因为我的数据中有一个模式(高峰总是大致在同一时间),我以为它在做预测,而实际上它只是在返回训练中的值。