【发布时间】:2019-08-13 12:42:00
【问题描述】:
我正在阅读使用 Scikit-Learn 和 TensorFlow 进行动手机器学习的第 14 章。它说:
尽管使用
OutputProjectionWrapper是将 RNN 输出序列的维度减少到每个时间步(每个实例)仅一个值的最简单解决方案,但它并不是最有效的。有一个更棘手但更有效的解决方案:您可以重塑 RNN 输出,然后应用具有适当输出大小的单个全连接层。 [...] 这可以显着提高速度,因为只有一个全连接层,而不是每个时间步长一个。
这对我来说毫无意义。对于OutputProjectionWrapper,我们需要在每个时间步执行 2 次操作:
- 根据之前的隐藏状态和输入计算新的隐藏状态。
- 通过将密集层应用于计算的隐藏状态来计算输出。
当然,当我们在顶层使用普通的BasicRNNCell + 密集层时,我们只需要在每个时间步(第一个)上执行一次操作,但是我们需要将每个输出张量通过我们的密集层进行管道传输。所以我们需要在这两种情况下执行相同数量的操作。
另外,我无法理解以下部分:
这可以显着提高速度,因为只有一个全连接层,而不是每个时间步长一个。
在这两种情况下我们不是只有一个全连接层吗?据我了解OutputProjectionWrapper 在每个时间步都使用相同的共享层。我什至不知道它如何为每个时间步创建不同的层,因为OutputProjectionWrapper 没有关于我们将使用的时间步长的信息。
如果有人能解释这些方法之间的区别,我将不胜感激。
UPD 这是问题的伪代码。我错过了什么吗?
# 2 time steps, x1 and x2 - inputs, h1 and h2 - hidden states, y1 and y2 - outputs.
# OutputProjectionWrapper
h1 = calc_hidden(x1, 0)
y1 = dense(h1)
h2 = calc_hidden(x2, h1)
y2 = dense(h2)
# BasicRNNCell + dense layer on top of all time steps
h1 = calc_hidden(x1, 0)
y1 = h1
h2 = calc_hidden(x2, h1)
y2 = h2
y1 = dense(y1)
y2 = dense(y2)
UPD 2 我创建了两个小代码 sn-ps(一个带有 OutputProjectionWrapper,另一个带有 BasicRNNCell 和 tf.layers.dense 在顶部) - 两者都创建了 14 个具有相同形状的变量.所以这些方法之间肯定没有内存差异。
【问题讨论】:
标签: tensorflow machine-learning deep-learning recurrent-neural-network