Deep learning 为什么用于预测的Keras LSTM批次大小必须与拟合批次大小相同?

Deep learning 为什么用于预测的Keras LSTM批次大小必须与拟合批次大小相同?,deep-learning,keras,lstm,Deep Learning,Keras,Lstm,当使用Keras LSTM对时间序列数据进行预测时,当我尝试使用50的批量大小对模型进行训练,然后尝试使用1的批量大小对同一模型进行预测(即仅预测下一个值)时,会出现错误 为什么我不能同时对多个批次的模型进行训练和拟合,然后使用该模型预测除相同批次大小之外的任何其他情况。这似乎没有什么意义,但我很容易就忽略了这一点 编辑:这是模型batch_size为50,sl为序列长度,当前设置为20 model = Sequential() model.add(LSTM(1, batch_i

当使用Keras LSTM对时间序列数据进行预测时,当我尝试使用50的批量大小对模型进行训练,然后尝试使用1的批量大小对同一模型进行预测(即仅预测下一个值)时,会出现错误

为什么我不能同时对多个批次的模型进行训练和拟合,然后使用该模型预测除相同批次大小之外的任何其他情况。这似乎没有什么意义,但我很容易就忽略了这一点

编辑:这是模型
batch_size
为50,
sl
为序列长度,当前设置为20

    model = Sequential()
    model.add(LSTM(1, batch_input_shape=(batch_size, 1, sl), stateful=True))
    model.add(Dense(1))
    model.compile(loss='mean_squared_error', optimizer='adam')
    model.fit(trainX, trainY, epochs=epochs, batch_size=batch_size, verbose=2)
以下是预测RMSE训练集的路线

    # make predictions
    trainPredict = model.predict(trainX, batch_size=batch_size)
下面是对看不见的时间步长的实际预测

for i in range(test_len):
    print('Prediction %s: ' % str(pred_count))

    next_pred_res = np.reshape(next_pred, (next_pred.shape[1], 1, next_pred.shape[0]))
    # make predictions
    forecastPredict = model.predict(next_pred_res, batch_size=1)
    forecastPredictInv = scaler.inverse_transform(forecastPredict)
    forecasts.append(forecastPredictInv)
    next_pred = next_pred[1:]
    next_pred = np.concatenate([next_pred, forecastPredict])

    pred_count += 1
该问题与以下内容有关:

forecastPredict=model.predict(下一步预测,批量大小=批量大小)

当此处的“批次大小”设置为1时,错误为:

ValueError:无法为张量'lstm_1_input:0'输入形状(1,1,2)的值,该张量具有形状'(10,1,2)
,这与
batch_size
此处设置为50时引发的错误相同,与其他批量大小相同

总误差为:

    forecastPredict = model.predict(next_pred_res, batch_size=1)
  File "/home/entelechy/tf_keras/lib/python3.5/site-packages/keras/models.py", line 899, in predict
    return self.model.predict(x, batch_size=batch_size, verbose=verbose)
  File "/home/entelechy/tf_keras/lib/python3.5/site-packages/keras/engine/training.py", line 1573, in predict
    batch_size=batch_size, verbose=verbose)
   File "/home/entelechy/tf_keras/lib/python3.5/site-packages/keras/engine/training.py", line 1203, in _predict_loop
    batch_outs = f(ins_batch)
  File "/home/entelechy/tf_keras/lib/python3.5/site-packages/keras/backend/tensorflow_backend.py", line 2103, in __call__
    feed_dict=feed_dict)
  File "/home/entelechy/tf_keras/lib/python3.5/site-packages/tensorflow/python/client/session.py", line 767, in run
    run_metadata_ptr)
  File "/home/entelechy/tf_keras/lib/python3.5/site-packages/tensorflow/python/client/session.py", line 944, in _run
    % (np_val.shape, subfeed_t.name, str(subfeed_t.get_shape())))
ValueError: Cannot feed value of shape (1, 1, 2) for Tensor 'lstm_1_input:0', which has shape '(10, 1, 2)'

编辑:一旦我将模型设置为
stateful=False
,我就可以使用不同的批量大小进行拟合/训练和预测。原因是什么?

不幸的是,你想用Keras做的事是不可能的。。。我也在这个问题上挣扎了很多时间,唯一的办法就是潜入兔子洞,直接使用Tensorflow进行LSTM滚动预测

首先,为了明确术语,
batch_size
通常表示一起训练的序列数,
num_steps
表示一起训练的时间步长数。当您的意思是“批量大小=1”和“仅预测下一个值”时,我想您的意思是使用
num\u步骤=1进行预测

否则,应该可以使用
batch_size=50
进行训练和预测,这意味着您正在对50个序列进行训练,并在每个时间步进行50次预测,每个序列一次(意味着训练/预测
num_steps=1

但是,我认为您的意思是希望使用有状态LSTM使用
num_steps=50
进行训练,并使用
num_steps=1
进行预测。从理论上讲,这是有意义的,而且应该是可能的,这在Tensorflow中是可能的,而不是Keras

问题:Keras需要有状态RNN的显式批量大小。必须指定批次输入形状(批次大小、数量步数、特征)

原因:Keras必须在具有形状的计算图中分配一个固定大小的隐藏状态向量(batch_size,num_units),以便在训练批次之间保持值。另一方面,当
stateful=False
时,隐藏状态向量可以在每个批处理开始时动态初始化为零,因此不需要固定大小。详情如下:

可能的解决办法:使用
num\u steps=1进行训练和预测。示例:。对于您的问题,这可能有效,也可能无效,因为反向传播的梯度将仅在一个时间步长上计算。见:


我的解决方案:使用Tensorflow:在Tensorflow中,您可以使用
batch\u size=50,num\u steps=100
进行训练,然后使用
batch\u size=1,num\u steps=1进行预测。这可以通过为共享相同RNN权重矩阵的训练和预测创建不同的模型图来实现。关于下一个角色预测和博客文章,请参见此示例。请注意,一个图形仍然只能与一个指定的批处理大小一起工作,但您可以在Tensorflow中设置多个共享权重的模型图形。

遗憾的是,您所希望的是不可能的,因为您在定义模型时指定了批处理大小。。。 然而,我发现了一个解决这个问题的简单方法:创建两个模型!第一个用于训练,第二个用于预测,并让它们共享权重:

train_model = Sequential([Input(batch_input_shape=(batch_size,...),
<continue specifying your model>])

predict_model = Sequential([Input(batch_input_shape=(1,...),
<continue specifying exact same model>])

train_model.compile(loss='sparse_categorical_crossentropy', optimizer=Adam())
predict_model.compile(loss='sparse_categorical_crossentropy', optimizer=Adam())
请注意,您只想保存和加载权重,而不是整个模型(包括体系结构、优化器等)。这样你可以得到重量,但你可以一次输入一批。。。 有关keras保存/加载模型的更多信息:


请注意,您需要安装h5py才能使用“保存权重”。

另一个简单的解决方法是:

def create_model(batch_size):
    model = Sequential()
    model.add(LSTM(1, batch_input_shape=(batch_size, 1, sl), stateful=True))
    model.add(Dense(1))
    return model

model_train = create_model(batch_size=50)

model_train.compile(loss='mean_squared_error', optimizer='adam')
model_train.fit(trainX, trainY, epochs=epochs, batch_size=batch_size)

model_predict = create_model(batch_size=1)

weights = model_train.get_weights()
model_predict.set_weights(weights)
我发现下面的内容很有帮助(并且与上面的内容完全一致)。“解决方案3:复制权重”一节对我很有用:

我也有同样的问题并解决了

另一种方法是,您可以保存权重,当您测试结果时,您可以使用相同的体系结构重新加载模型,并设置
batch_size=1
,如下所示:

 n_neurons = 10
 # design network
 model = Sequential()
 model.add(LSTM(n_neurons, batch_size=1, batch_input_shape=(n_batch,X.shape[1], X.shape[2]), statefull=True))
 model.add(Dense(1))
 model.compile(loss='mean_squared_error', optimizer='adam')
 model.load_weights("w.h5")

它将很好地工作。我希望它能对你有所帮助。

解决这个问题的最好办法是“复制权重”。如果您想使用具有不同批量大小的LSTM模型进行训练和预测,这将非常有用

例如,一旦您使用“n”批次大小对模型进行了培训,如下所示:

# configure network
n_batch = len(X)
n_epoch = 1000
n_neurons = 10
# design network
model = Sequential()
model.add(LSTM(n_neurons, batch_input_shape=(n_batch, X.shape[1], X.shape[2]), stateful=True))
model.add(Dense(1))
model.compile(loss='mean_squared_error', optimizer='adam')
现在您希望预测值小于批处理大小,其中n=1。

您可以做的是,复制fit模型的权重,并使用相同的体系结构重新初始化新模型LSTM模型,并将batch size设置为1

# re-define the batch size
n_batch = 1
# re-define model
new_model = Sequential()
new_model.add(LSTM(n_neurons, batch_input_shape=(n_batch, X.shape[1], X.shape[2]),       stateful=True))
new_model.add(Dense(1))
# copy weights
old_weights = model.get_weights()
new_model.set_weights(old_weights)
现在,您可以轻松预测和训练具有不同批量大小的LSTM


有关更多信息,请阅读:

批大小与您描述的不一样,请添加详细信息和代码。添加错误和相关代码如果您传递的批大小为1,请确保它仍然是一个与训练数组形状完全相同的数组,只是50变为1。确保在(1,sl)中没有丢失一维变换(50,1,sl)。应该保留(1,1,sl)。@Daniel hey谢谢你的回复。是的,我去了
# configure network
n_batch = len(X)
n_epoch = 1000
n_neurons = 10
# design network
model = Sequential()
model.add(LSTM(n_neurons, batch_input_shape=(n_batch, X.shape[1], X.shape[2]), stateful=True))
model.add(Dense(1))
model.compile(loss='mean_squared_error', optimizer='adam')
# re-define the batch size
n_batch = 1
# re-define model
new_model = Sequential()
new_model.add(LSTM(n_neurons, batch_input_shape=(n_batch, X.shape[1], X.shape[2]),       stateful=True))
new_model.add(Dense(1))
# copy weights
old_weights = model.get_weights()
new_model.set_weights(old_weights)