【问题标题】:What does it mean to unroll a RNN dynamically?动态展开 RNN 是什么意思?
【发布时间】:2016-12-20 17:09:37
【问题描述】:

“动态展开 RNN”是什么意思。我已经在 Tensorflow 源代码中看到了这一点,但我正在寻找一种普遍适用于 RNN 的概念解释。

在tensorflowrnn方法中,有记载:

如果提供sequence_length向量,动态计算是 执行。这种计算方法不计算 RNN 步骤 超过 minibatch 的最大序列长度(从而节省 计算时间),

但在dynamic_rnn 方法中提到:

参数sequence_length是可选的,用于 通过批处理元素时的复制状态和零输出 序列长度。所以它更多的是为了正确性而不是性能, 不像rnn()

那么这是否意味着rnn 对于可变长度序列的性能更高? dynamic_rnnrnn 的概念区别是什么?

【问题讨论】:

  • +1 我还想知道dynamic_rnn 是否在非动态对应物上引入了任何近似值。换句话说,在学术环境中,我们可以依靠例如BasicLSTMCell + dynamic_rnn 与参考 LSTM 执行相同,还是需要考虑任何权衡?

标签: neural-network tensorflow


【解决方案1】:

从文档中我了解到他们的意思是rnn 方法中的参数sequence_length 会影响性能,因为设置后,它将执行动态计算并且之前会停止。

例如,如果rnn最大的输入序列长度为50,如果其他序列较短,最好为每个序列设置sequence_length,这样每个序列的计算将在序列结束并且在达到 50 个时间步之前不会计算填充零。但是,如果未提供sequence_length,它将认为每个序列具有相同的长度,因此会将用于填充的零视为序列中的正常项。

这并不意味着dynamic_rnn 的性能较差,文档说参数sequence_length 不会影响性能,因为计算已经是动态的。

也照this post about RNNs in Tensorflow

在内部,tf.nn.rnn 为固定 RNN 长度创建展开图。这意味着,如果您使用具有 200 个时间步长的输入调用 tf.nn.rnn,那么您正在创建一个具有 200 个 RNN 步长的静态图。首先,图形创建很慢。其次,您无法传递比您最初指定的更长的序列(> 200)。

tf.nn.dynamic_rnn 解决了这个问题。它使用 tf.While 循环在执行时动态构建图形。这意味着图形创建速度更快,并且您可以提供可变大小的批次。性能呢?您可能认为静态 rnn 比其动态对应物更快,因为它预先构建了图形。根据我的经验,情况并非如此。

简而言之,只需使用 tf.nn.dynamic_rnn。 tf.nn.rnn 没有任何好处,如果它在未来被弃用,我也不会感到惊讶。

dynamic_rnn 甚至更快(或相等),所以他建议还是使用dynamic_rnn

【讨论】:

  • "tf.nn.rnn 创建一个展开图" -- 这可以清除一些问题。
  • 似乎 dynamic_rnn 为图表增加了灵活性,因为您可以每次将输入设置为不同的长度,让您可以执行诸如分桶之类的操作。我很想看看固定 rnn 与分桶 dynamic_rnn 之间的性能比较以及性能差异的解释。
【解决方案2】:

LSTM(或 GRU)单元是两者的基础。

将RNN想象成一个堆叠的深度网络

  • 权重共享(=权重和偏差矩阵在所有层中都相同)
  • 从“侧面”进入每一层的输入
  • 输出在更高层(即解码器)中解释,每层一个

这个网络的深度应该取决于(实际上等于)实际的输入和输出长度。仅此而已,因为无论如何,所有层的权重都是相同的。

现在,构建它的经典方法是将输入输出对分组为固定的最大长度(即 model_with_buckets())。 DynRNN 打破了这个约束,适应了实际的序列长度。

所以这里没有真正的权衡。除非您可能必须重写旧代码才能适应。

【讨论】:

  • 我的理解是,它会适应批次中最长项目的实际序列长度,而不是适应每一行的长度。至少对于 TensorFlow。因此仍然需要分桶。
【解决方案3】:

为了更好地理解动态展开,考虑一下您是否会从头开始创建 RNN,但使用 Tesorflow(我的意思是不使用任何 RNN 库)输入 2 个时间戳

  1. 创建两个占位符,X1 和 X2
  2. 创建两个可变权重 Wx 和 Wy 以及偏差
  3. 计算输出,Y1 = fn(X1 x Wx + b) 和 Y2 = fn(X2 x Wx + Y1 x Wy + b)。

很明显,我们得到了两个输出,每个时间戳一个。请记住,Y2 通过 Y1 间接依赖于 X2。

现在假设您有 50 个输入时间戳,从 X1 到 X50。在这种情况下,您必须创建 50 个输出,从 Y1 到 Y50。这就是 Tensorflow 通过动态展开所做的 它通过 tf.dynamic_rnn() 单元为您创建这 50 个输出。

我希望这会有所帮助。

【讨论】:

    猜你喜欢
    • 2015-01-03
    • 2015-12-05
    • 2017-06-29
    • 2013-05-23
    • 1970-01-01
    • 2018-04-30
    • 1970-01-01
    • 1970-01-01
    • 2016-08-04
    相关资源
    最近更新 更多