问题:
在使用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与之不同导致的。
解决方法:
将代码中的:
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批量大小必须与拟合批量大小相同?
(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]