发新帖

tensorflow lstm 为什么测试时,必须保持batch_size不变

[复制链接]
318 4

快来加入 TensorFlowers 大家庭!

您需要 登录 才可以下载或查看,没有帐号?加入社区

x
在使用tf搭建lstm时,无论训练还是测试时,都必须保持batch_size不变,否则会报错,但搭建纯CNN时并不会出现这种情况,有什么解决方案吗?
文韬武略已获得悬赏 10 金币+5 金币

最佳答案

batch size和 time step都是可以变的,一种方案是新建一个rnn和之前的共享参数,利用variable_scope,我一般是这么干的,另一种是利用dynamic_rnn的一个tf自带的wrap,但是我没试过。我记得tf官方rnn教程里就是用第 ...
本楼点评(3) 收起
  • yunhai_luo楼主能澄清一下怎么“必须保持batch_size不变”吗?是指训练和测试各自的batch_size在各自的运行中不变?还是指测试的batch_size等于训练的batch_size?会报什么错?
    2018-5-23 14:50 回复
  • 小筑123回复 yunhai_luo : 在训练和测试的时候,都必须保持相同的且固定不变的batch_size,比如测试的时候,由于验证的数据比较少,我可能会将所有数据一次性输入feed_dict,那此时喂得数据的batch_size就变了,会报错
    2018-5-26 17:38 回复
  • 小筑123回复 yunhai_luo :报错信息参见下一楼回复,谢谢
    2018-5-26 17:48 回复

精彩评论15

小筑123  TF荚荚  发表于 2018-5-26 17:46:59 | 显示全部楼层
本帖最后由 小筑123 于 2018-5-26 17:48 编辑

图片中的batch_size为32,然后我喂了11个数据进去
C:\Users\YangW\Desktop\lstm_batch.png
而且我发现在定义模型的时候,会涉及到 init_state = lstm_cell.zero_state(batch_size, dtype=tf.float32)
这里会有batch_size,感觉导致报错的原因就在这里,请问有其它解决方案吗?
lstm_batch.png
本楼点评(1) 收起
  • yunhai_luo具体适用于你的解决方案我给不出来,不好意思,主要是个人对TF构建LSTM不熟。但确有一个可供参考的思路:楼主的主要问题在于在不同批次间传递了状态,所以状态存储的大小与批次大小有关,需要指定/固定,模型构建好了以后不方便更改。对于训练转使用的这个特殊情况,可以使用重建模型并复制变量的办法。在Keras架构中,对模型的变量可以取出和导入:用trained_weights = train_model.get_weights()取出训练好的变量,然后构建适用于新batch_size的
    新模型,用infer_model.set_weights(trained_weights)导入变量。至于楼主的模型在TF下怎么做,我确实无从谈起。如果楼主解决了,希望能分享出来供大家学习,先行谢过!
    2018-5-27 16:12 回复
文韬武略  TF荚荚  发表于 2018-5-28 10:26:33 来自手机  | 显示全部楼层
batch size和 time step都是可以变的,一种方案是新建一个rnn和之前的共享参数,利用variable_scope,我一般是这么干的,另一种是利用dynamic_rnn的一个tf自带的wrap,但是我没试过。我记得tf官方rnn教程里就是用第一种方法的,仔细看看代码肯定能搞定的。
本楼点评(6) 收起
  • yunhai_luo如果改变batch_size(stateful时)和time_step的话会不会改变模型的预测方式和预测能力呢?
    2018-5-28 13:39 回复
  • 小筑123回复 yunhai_luo : 本质上是不会变得,因为RNN的参数在不同的时间步上是共享的,其次跟batch_size没有什么关系
    2018-5-29 08:29 回复
  • 小筑123谢谢您提供的一种思路,那个教程其实我之前也看过,是通过模型的复用实现的,在复用模型的时候,给与不同的batch_size和time_steps,但在训练的过程中改变batch_size是没法做到的。我实现rnn的方式就是通过dynamic_rnn实现的,我又仔细看了下api的说明,发现其实是可以做到在训练的时候改变bath_size的,详细参见下楼。感谢您的回复
    2018-5-29 08:32 回复
  • yunhai_luo回复 小筑123 :嗯,多谢楼主回复。是不是也就是说time_step的设置对于模型预测能力本质上没有影响?当然模型预测能力跟batch_size无关应该是意料之中的期望。
    2018-5-29 12:51 回复
  • 小筑123回复 yunhai_luo :  我觉得time_step更多的是根据你样本的时间序列长度来定的,样本在时间维上有多长,就可以给到多长。但time_step太长的话,也会出现问题,虽然说lstm具有很强的长时依赖提取能力,但过长会导致训练难度的加大和难以拟合,也会出现梯度爆炸或消失的情况,time_step是要根据具体问题而定的
    2018-5-29 19:30 回复
  • yunhai_luo回复 小筑123 :多谢楼主!是我理解time_step不足。
    2018-5-30 00:07 回复
小筑123  TF荚荚  发表于 2018-5-29 08:40:10 | 显示全部楼层
本帖最后由 小筑123 于 2018-5-29 08:45 编辑

       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]


这是最开始模型的定义,由于这里对init_state进行了zero初始化,这里涉及到了batch_size,这里就是导致后来喂数据的时候,不能改变bathc_size的原因,通过查dynamic_rnn的api说明,它是可以不提供initial_state,让其自行填充为0的,只需要指定dtype即可。

将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的序列长度就可以了





本楼点评(0) 收起
M丶Sulayman  TF豆豆  发表于 2018-5-29 15:50:01 | 显示全部楼层
小筑123 发表于 2018-5-29 08:40
with tf.variable_scope('LSTM_layer'):
            convnets = tf.reshape(convnets, shape=[-1,  ...

那这样说起来,其他模型是不是也存在这种参数呢?
本楼点评(1) 收起
  • 小筑123不知道你指的其它模型是什么模型,涉及到rnn的都需要注意这个问题。纯CNN下,bathc_size随时可以变
    2018-5-29 19:31 回复
您需要登录后才可以回帖 登录 | 加入社区

本版积分规则

快速回复 返回顶部 返回列表