为什么我从Keras LSTM网络得到完全不同的预测取决于预测的顺序?

为什么我从Keras LSTM网络得到完全不同的预测取决于预测的顺序?,keras,deep-learning,lstm,prediction,batchsize,Keras,Deep Learning,Lstm,Prediction,Batchsize,我有一个构建LSTM模型的脚本,将其用于训练数据,预测一些测试数据。 (只是为了好玩,在列车数据上绘制预测图,因为它们应该接近列车数据,只是为了知道我的模型是否构建良好) 1) 第一个问题是,对测试和列车数据的预测完全不同,这取决于我是在列车上预测还是先测试 2) 第二个问题可能与第一个问题相关,因此每次我运行脚本时,对测试数据的预测都是完全不同的。我知道神经网络有某种随机性,但正如你在我的结果图中所看到的,它完全不同: edit1:我试图按照评论中的建议设置“stateful=False”,但

我有一个构建LSTM模型的脚本,将其用于训练数据,预测一些测试数据。 (只是为了好玩,在列车数据上绘制预测图,因为它们应该接近列车数据,只是为了知道我的模型是否构建良好)

1) 第一个问题是,对测试和列车数据的预测完全不同,这取决于我是在列车上预测还是先测试

2) 第二个问题可能与第一个问题相关,因此每次我运行脚本时,对测试数据的预测都是完全不同的。我知道神经网络有某种随机性,但正如你在我的结果图中所看到的,它完全不同:

edit1:我试图按照评论中的建议设置“stateful=False”,但没有成功。

edit2:我已经更新了脚本和绘图,并在新代码中提供了一些基本的正弦波样本数据。即使在这个简单的例子中,问题仍然存在

我得到了一个输入信号X,它是一个正弦波,有100个时间步长,振幅和频率都是随机的。 我的目标y与X相关(在每个时间步中),在本例中也是一个正弦波。 我的数据的形状是

X_train.shape = (100, 1, 1)
y_train.shape = (100,)
X_test.shape = (100, 1, 1)
y_test.shape = (100,)
我正在使用LSTM网络试图拟合一个完整的正弦波,所以批量大小=100,并预测测试信号的每个点,所以预测的批量大小=1。此外,我还在每个历元后手动重置LSTM的状态,如下所述:

为了建立我的网络,我遵循了这里提到的“keras规则”:

我知道解决问题的基本方法,如下所示: 但对我来说什么都不管用

我很感谢在这方面的任何帮助,也很感谢提出更好的问题,以防我做错了什么,因为这是我在stack上的第一篇文章

谢谢大家! 下面是我的代码示例:

import numpy as np
import matplotlib.pyplot as plt
from keras import models, layers, optimizers
from keras.callbacks import Callback


# create training sample data
Fs = 100  # sample rate
z = np.arange(100)
f = 1  # frequency in Hz
X_train = np.sin(2 * np.pi * f * z / Fs)
y_train = 0.1 * np.sin(2 * np.pi * f * z / Fs)


# create test sample data
f = 1  # frequency in Hz
X_test = np.sin(2 * np.pi * f * z / Fs) * 2
y_test = 0.2 * np.sin(2 * np.pi * f * z / Fs)


# convert data into LSTM compatible format
y_train = np.array(y_train)
y_test = np.array(y_test)
X_train = X_train.reshape(X_train.shape[0], 1, 1)
X_test = X_test.reshape(X_test.shape[0], 1, 1)


# build and compile model
model = models.Sequential()
model.add(layers.LSTM(1, batch_input_shape=(len(X_train), X_train.shape[1], X_train.shape[2]),
                      return_sequences=False, stateful=False))
model.add(layers.Dense(X_train.shape[1], input_shape=(1,), activation='linear'))
model.compile(optimizer=optimizers.Adam(lr=0.01, decay=0.008, amsgrad=True), loss='mean_squared_error', metrics=['mae'])


# construct a class for keras callbacks, to make sure the cell state is reset after each epoch
class ResetStatesAfterEachEpoch(Callback):
    def on_epoch_end(self, epoch, logs=None):
        self.model.reset_states()

reset_state = ResetStatesAfterEachEpoch()
callbacks = [reset_state]


# fit model to training data
history = model.fit(X_train, y_train, epochs=20000, batch_size=len(X_train),
                        shuffle=False, callbacks=callbacks)


# re-define LSTM model with weights of fit model to predict for 1 point, so also re-define the batch size to 1
new_batch_size = 1
new_model = models.Sequential()
new_model.add(layers.LSTM(1, batch_input_shape=(new_batch_size, X_test.shape[1], X_test.shape[2]), return_sequences=False,
                          stateful=False))
new_model.add(layers.Dense(X_test.shape[1], input_shape=(1,), activation='linear'))

# copy weights to new model
old_weights = model.get_weights()
new_model.set_weights(old_weights)


# single point prediction on train data
y_pred_train = new_model.predict(X_train, batch_size=new_batch_size)

# single point prediction on test data
y_pred_test = new_model.predict(X_test, batch_size=new_batch_size)

# plot predictions
plt.figure()
plt.plot(y_test, 'r', label='ground truth test',
         linestyle='dashed', linewidth=0.8)
plt.plot(y_train, 'b', label='ground truth train',
         linestyle='dashed', linewidth=0.8)
plt.plot(y_pred_test, 'g',
         label='y pred test', linestyle='dotted',
         linewidth=0.8)
plt.plot(y_pred_train, 'k',
         label='y pred train', linestyle='-.',
         linewidth=0.8)
plt.title('pred order: test, train')
plt.xlabel('time steps')
plt.ylabel('y')
plt.legend(prop={'size': 8})
plt.show()
问题在于:

model.add(layers.LSTM(1, batch_input_shape=(len(X_train), X_train.shape[1], X_train.shape[2]),
                      return_sequences=False, stateful=True))

LSTM
层中设置
stateful=True
,这意味着每次预测后隐藏状态是not重置,这解释了您看到的效果。如果您不想要这种行为,您应该将其设置为默认值
stateful=False
,它将作为标准的非状态LSTM工作。

因此我找到了一个解决方案,我不知道为什么会这样(如果有人这样做并可以留下评论,我将不胜感激),但它可以工作

我添加了X_序列的导数(这里是cos),所以我得到了一个具有2个特性的多输入LSTM。最后一列X_列车如本规范所假设:

x = np.sin(2 * np.pi * f * z / Fs)
dx_dt = np.cos(2 * np.pi * f * z / Fs)
X_train = np.column_stack((x, dx_dt))
即使是像时移y一样的
y_序列=5*np.sin(2*np.pi*f*(z+51)/Fs)
也被预测为经过3000个时代的良好训练。LSTM 1层和3个神经元


这是最新的

在我的代码示例中,您可以看到我开始预测测试数据,然后预测列车数据。如果我以相反的方式启动脚本,那么首先在火车上预测,然后在测试数据上预测,结果是不同的。你可以在我提供的情节“标题”中看到不同之处Matias的回答解决了你的问题吗?注意:请使用@otheruser另一个来获取通知。谢谢。@Geeocode很遗憾没有。您能提供示例数据吗?我刚刚尝试运行相同的脚本,您建议的更改为stateful=False,但不幸没有成功。问题1)和问题2)仍然存在。我用这种情况的绘图更新了我的帖子。@Stuermar请确保更改代码中的所有有状态参数(有两个)。当然,它们都设置为False。