张量流 BasicLSTMCell 中的 num_units 是啥?

Posted

技术标签:

【中文标题】张量流 BasicLSTMCell 中的 num_units 是啥?【英文标题】:What is num_units in tensorflow BasicLSTMCell?张量流 BasicLSTMCell 中的 num_units 是什么? 【发布时间】:2016-10-20 10:35:48 【问题描述】:

在 MNIST LSTM 示例中,我不明白“隐藏层”是什么意思。当你表示随着时间的推移展开的 RNN 时形成的想象层是?

为什么大多数情况下是num_units = 128

【问题讨论】:

我想指出,该教程的作者(即 OP 链接到的那个)已将变量的名称更改为 num_unitsnum_hidden。现在该变量前面有一条注释,上面写着hidden layer num of features 好的,我已经做了相应的修改。 【参考方案1】:

BasicLSTMCell 的参数n_hidden 是 LSTM 的隐藏单元数。

正如你所说,你真的应该阅读 Colah 的 blog post 以了解 LSTM,但这里有一点提醒。


如果您有一个形状为[T, 10] 的输入x,您将为LSTM 提供从t=0t=T-1 的值序列,每个值的大小为10

在每个时间步,您将输入与形状为[10, n_hidden] 的矩阵相乘,得到一个n_hidden 向量。

你的 LSTM 在每个时间步得到t

之前的隐藏状态h_t-1,大小为n_hidden(在t=0,之前的状态是[0., 0., ...]) 输入,转换为大小n_hidden 它将汇总这些输入并产生下一个隐藏状态h_t,大小为n_hidden

来自 Colah 的博文:


如果您只想让代码正常工作,请继续使用n_hidden = 128,您会没事的。

【讨论】:

"输入,转换为大小 n_hidden" 当像你说的那样使用矩阵乘法完成时非常酷。但是在我提到的 mnist 代码示例中,他似乎在处理批处理中的所有向量值: x = tf.transpose(x, [1, 0, 2]) ... ,以获得 28 x 128 x 28 形状。我不明白。 RNN 迭代图像的每一行。在RNN函数的代码中,他们想要得到一个长度为128(图像的步数,或行数)的列表,每个元素的形状为[batch_size, row_size],其中row_size=28(大小的一行图像)。 tf 中的输入层大小有上限吗?将尺寸增加到千以上时,我会遇到段错误,并且可以减少。另外,不应该是“......他们想要一个长度为 28 的列表......”吗? ^ 是的,你是对的,它应该是28。输入大小的唯一限制是 GPU 的内存。如果你想使用更高的输入维度,你应该调整你的批量大小,使其适合你的记忆 tf.nn.dynamic_rnn 将向rnn 提供每个时间步长的数据..【参考方案2】:

隐藏单元的数量是神经网络学习能力的直接表示——它反映了学习参数的数量128 的值可能是任意或凭经验选择的。您可以通过实验更改该值并重新运行程序以查看它如何影响训练准确度(您可以获得超过 90% 的测试准确度,而隐藏单元很多)。使用更多单元使其更有可能完美地记住完整的训练集(尽管需要更长的时间,并且存在过度拟合的风险)。

要理解的关键是,在著名的Colah's blog post 中有些微妙(发现“每一行都有一个完整的向量”),X 是一个 array 数据(现在通常称为tensor)——它并不是一个标量值。例如,在显示tanh 函数的地方,它意味着该函数在整个数组中广播(隐式for 循环)——而不是简单地每次执行一次时间步长。

因此,隐藏单元代表网络中的有形存储,主要体现在权重数组的大小上。而且因为 LSTM 实际上确实有一些自己的内部存储与学习的模型参数分开,它必须知道有多少单元——这最终需要与权重的大小一致。在最简单的情况下,RNN 没有内部存储——因此它甚至不需要提前知道它被应用到了多少个“隐藏单元”。


类似问题的好答案here。 您可以查看the source for BasicLSTMCell in TensorFlow 以了解其具体使用方式。

旁注:This notation 在统计和机器学习以及其他使用通用公式处理大批量数据的领域非常常见(3D 图形是另一个示例)。对于希望看到明确写出 for 循环的人来说,这需要一点时间来适应。

【讨论】:

其他问题:涉及多少总内存?权重如何连接到 LSTM 单元?注意:请参阅 TensorBoard 图形可视化。 我推荐LSTM: A Search Space Odyssey第1-3节。 这里的 cmets 中似乎有后续:RNNS IN TENSORFLOW, A PRACTICAL GUIDE AND UNDOCUMENTED FEATURES 我说对了吗:“一个简单的 RNN 不需要事先知道多少隐藏单元”?它是否不需要知道构建在单元之间映射的权重——它的数量会根据单元的数量呈指数增长(即使在最简单的 RNN 中也是如此)。我认为当我写这个答案时我不理解架构的那个方面(见我的第一条评论)。但请注意,由于基于数组的表示法,图形可视化往往没有帮助。 ...有点有趣的是,使用基于数组的表示法,具有指数信号计数的数据路径可以用一条黑线表示。【参考方案3】:

我认为“num_hidden”一词会让 TF 用户感到困惑。其实它与展开的LSTM单元无关,它只是张量的维度,它是从时间步输入张量转换并馈入LSTM单元的。

【讨论】:

【参考方案4】:

来自this brilliant article

num_units 可以解释为前馈神经网络中隐藏层的类比。前馈神经网络隐藏层的节点数相当于网络每个时间步长LSTM单元中LSTM单元的num_units个数。

也可以在那里查看image!

【讨论】:

LSTM 的优秀框图,你能用图表解释一下每个 LSTM 单元的 num_units 单元内到底是什么,因为每个 LSTM 单元分别包含输入门、输出门和遗忘门。 @Biranchi,LSTM 单元内部是 LSTM 单元。在引用的文章中,每个 LSTM 单元中的每个num_units 都接收图像某一行的一个像素。图像大小为 28x28 像素。在示例中,他们使用了 28 个num_units 和 28 个 LSTM 单元。基本上每个单元格都适用于图像的给定行。 这张图完美概括了一切【参考方案5】:

LSTM 在随时间传播时保留两条信息:

hidden 状态;这是 LSTM 使用其(forget, input, and output) 门在时间上积累的内存,以及 上一个时间步的输出。

Tensorflow 的num_units 是 LSTM 隐藏状态的大小(如果不使用投影,这也是输出的大小)。

为了让num_units这个名字更直观,你可以把它想象成LSTM单元格中隐藏单元的数量,或者单元格中的记忆单元数量。

查看this 很棒的帖子以获得更清晰的信息

【讨论】:

【参考方案6】:

这个术语num_unitsnum_hidden_units 有时在实现中使用变量名称nhid 表示,这意味着LSTM 单元的输入是维度为nhid 的向量(或者对于批处理实现,它会形状矩阵batch_size x nhid)。因此,输出(来自 LSTM 单元)也将具有相同的维度,因为 RNN/LSTM/GRU 单元不会改变输入向量或矩阵的维度。

如前所述,该术语是从前馈神经网络 (FFN) 文献中借用的,在用于 RNN 的上下文中时会引起混淆。但是,这个想法是,即使是 RNN,也可以在每个时间步视为 FFN。在这个视图中,隐藏层确实包含num_hidden 单元,如下图所示:

来源:Understanding LSTM


更具体地说,在下面的示例中,num_hidden_unitsnhid 将是 3,因为 隐藏状态的大小(中间层)是 3D 矢量

【讨论】:

您说“LSTM 单元的输入是维度为nhid 的向量”。但输入通常是[batch, T, input] 的形状,input 可以是任何形状。因此,当输入动态展开时,我们将输入[b,t, input]。 RNN 会将其转换为[b,t, nhid]。因此,输出将是形状 nhid 而不是输入。【参考方案7】:

由于我在合并来自不同来源的信息时遇到了一些问题,因此我创建了下面的图形,该图形显示了博客文章 (http://colah.github.io/posts/2015-08-Understanding-LSTMs/) 和 (https://jasdeep06.github.io/posts/Understanding-LSTM-in-Tensorflow-MNIST/) 的组合,我认为这些图形非常有用,但存在解释 number_units 的错误。

几个 LSTM 单元形成一个 LSTM 层。如下图所示。由于您主要处理的是非常广泛的数据,因此不可能将所有内容整合到模型中。因此,数据被分成小块作为批次,一个接一个地处理,直到读入包含最后一部分的批次。在图的下半部分可以看到读取批次的输入(深灰色)从批次 1 到批次 batch_size 一个接一个。上面的单元 LSTM 单元 1 到 LSTM 单元 time_step 表示 LSTM 模型的描述单元 (http://colah.github.io/posts/2015-08-Understanding-LSTMs/)。单元的数量等于固定时间步的数量。例如,如果您获取一个总共有 150 个字符的文本序列,您可以将其分成 3 个(batch_size)并且每个批次的序列长度为 50(time_steps 的数量以及 LSTM 单元的数量)。如果您随后对每个字符进行一次热编码,则每个元素(输入的深灰色框)将代表一个向量,该向量具有词汇表的长度(特征数)。这些向量将流入各个细胞中的神经元网络(细胞中的绿色元素),并将它们的维度更改为隐藏单元数量的长度(number_units)。因此输入具有维度(batch_size x time_step x features)。长时记忆(单元状态)和短时记忆(隐藏状态)具有相同的维度(batch_size x number_units)。由细胞产生的浅灰色块具有不同的维度,因为神经网络(绿色元素)中的转换是在隐藏单元(batch_size x time_step x number_units)的帮助下发生的。输出可以从任何单元格返回,但大多数情况下只有最后一个块(黑色边框)的信息是相关的(不是在所有问题中),因为它包含来自先前时间步长的所有信息。

【讨论】:

好答案,您通常对输入数据进行嵌入,因此为简单起见假设每个单词。因此,假设每个单词都有 150 维的分布式表示,即上图中的特征。然后 num_units 将充当 RNN/LSTM 单元的维数(比如 128)。所以 150 -> 128。因此输出尺寸将为 128。批量大小和 time_steps 保持不变。【参考方案8】:

大多数 LSTM/RNN 图只显示隐藏单元,但从不显示这些单元的单元。因此,混乱。 每个隐藏层都有隐藏单元,其数量与时间步数一样多。 此外,每个隐藏单元都由多个隐藏单元组成,如下图所示。因此,RNN中隐藏层矩阵的维数为(时间步数,隐藏单元数)。

【讨论】:

如果你有句子“the dog ate the food”并且每个单词对应一个输入,那么整个句子是在单个时间步(例如 t = 0)输入的,而不是每个在下一个时间步输入一个单元的单词,即“the”(t = 0)、“dog”(t = 1)等。老实说,我真的很困惑。【参考方案9】:

隐藏单元的概念如图https://imgur.com/Fjx4Zuo所示。

【讨论】:

【参考方案10】:

我认为这是您问题的正确答案。 LSTM 总是让人困惑。

您可以参考此博客以获取更多详细信息Animated RNN, LSTM and GRU

【讨论】:

惊人的插图。谢谢分享。它最终解释了这些让大家感到困惑的单位是什么。我一直不明白为什么不这样解释RNN。 这个答案与这篇文章中的其他答案相矛盾。【参考方案11】:

在@SangLe 回答之后,我制作了一张图片(参见原始图片的来源),显示了教程中经典表示的单元格 (Source1: Colah's Blog) 和一个具有 2 个单元的等效单元格 (Source2: Raimi Karim 's post)。希望它能澄清细胞/单元之间的混淆以及网络架构的真正含义。

【讨论】:

这个答案与这篇文章中的其他答案相矛盾。

以上是关于张量流 BasicLSTMCell 中的 num_units 是啥?的主要内容,如果未能解决你的问题,请参考以下文章

如何计算张量流中RNN的困惑度

关于tensorflow里面的tf.contrib.rnn.BasicLSTMCell 中num_units参数问题

在张量流中读取数据

自定义张量流解码器 TypeError: __call__() 缺少 1 个必需的位置参数:'inputs'

在张量流代码中将标量标记为一个热点?

张量流中添加方法的问题:AttributeError:模块'tensorflow.python.framework.ops'没有属性'_TensorLike'