LSTM的训练和测试长度(batch_size)不一样报错的解决方案

时间:2024-04-09 19:42:26

 问题:

在使用tf搭建lstm时,无论训练还是测试时,都必须保持batch_size不变,否则会报错,但搭建纯CNN时并不会出现这种情况,有什么解决方案吗?

下面代码是最开始模型的定义,由于这里对init_state进行了zero初始化,这里涉及到了batch_size,这里就是导致后来喂数据的时候,不能改变bathc_size的原因。

with tf.variable_scope('LSTM_layer'):
    convnets = tf.reshape(convnets, shape=[-1, n_timewin, 4*4*128], name='Reshape_for_lstm')
    #lstm cell inputs:[batchs, time_steps, hidden_units]
    with tf.variable_scope('LSTM_Cell'):
    lstm_cell = tf.contrib.rnn.BasicLSTMCell(num_units=num_units, forget_bias=1.0,
state_is_tuple=True)
    init_state = lstm_cell.zero_state(batch_size, dtype=tf.float32) #全初始化为0state
    outputs, final_state = tf.nn.dynamic_rnn(lstm_cell, convnets, initial_state=init_state, time_major=False)            
    outputs = tf.transpose(outputs, [1,0,2])
    outputs = outputs[-1]

例如训练时候图片中的batch_size为32,然后我喂了11个数据进去,会出一下错误(见图),这是由于训练时候:init_state = lstm_cell.zero_state(batch_size, dtype=tf.float32),这里会有batch_size,而测试时候batchsize与之不同导致的。

LSTM的训练和测试长度(batch_size)不一样报错的解决方案

解决方法:

将代码中的:

outputs,final_state = tf.nn.dynamic_rnn(lstm_cell,convnets, initial_state=init_state, time_major=False)

替换成下行即可在训练的过程中改变batch_size:

outputs, final_state = tf.nn.dynamic_rnn(lstm_cell,convnets, dtype=tf.float32, time_major=False)

其实我改变batch_size的初衷是,我的训练集不可能刚好是batch_size的整数倍,所以最后一个batch的样本不得不放弃,或者采取其它的操作对于如何改变时间步,dynamic_rnn有个参数为sequence_length,用feed_dict给它喂对应batch的序列长度就可以了

 

思维发散:

LSTM/RNN在训练还是测试时是否需要保持batch size和 time step不变呢?

答案是:在具体操作时,发现训练还是测试时其实可以不需要保持batch size和 time step不变(详见讨论:Tensorflow中文社区):

目前可行的两种方法:

1、“batch size和 time step都是可以变的。新建一个rnn和之前的共享参数,利用variable_scope,来共享变量。

2、采用tf.placeholder,训练和测试feed不同就行了:self.batch_size = tf.placeholder(tf.int32, [ ], name='batch_size ')

 

其他解决方法参考:

(1)关于不同Batch_Size在LSTM训练与预测中使用(Keras框架)

https://www.jianshu.com/p/dc04ca7639f8

(2) 题 为什么用于预测的Keras LSTM批量大小必须与拟合批量大小相同?

http://landcareweb.com/questions/43238/wei-shi-yao-yong-yu-yu-ce-de-keras-lstmpi-liang-da-xiao-bi-xu-yu-ni-he-pi-liang-da-xiao-xiang-tong

(3) How to use Different Batch Sizes when Training and Predicting with LSTMs

https://machinelearningmastery.com/use-different-batch-sizes-training-predicting-python-keras/

此问题解决方案概括如下:这个问题的最佳解决方案是“复制权重”。如果您想使用不同批量的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。

您可以做的是,复制拟合模型的权重,并使用相同的体系结构重新初始化新模型LSTM模型,并将批处理大小设置为等于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。

(4) 用LSTM做時間序列預測的思路,tensorflow程式碼實現及傳入資料格式

https://www.itread01.com/content/1545582186.html

简而言之这个方法就是不指定batch_size和time_step,而是直接:

    batch_size = tf.shape(X)[0]
    time_step = tf.shape(X)[1]