我使用tf.contrib.rnn.MultiRNNCell
模块制作多层RNN。我使用以下行来定义3层RNN-LSTM网络:
n_hidden = 2
num_layers = 3
lstm_cell = tf.contrib.rnn.BasicLSTMCell(n_hidden)
stacked_lstm_cell = tf.contrib.rnn.MultiRNNCell([lstm_cell] * num_layers)
然而,对于tensorflow中实际发生的事情,我的想法存在一些不确定性。据我所知,这段代码给了我一个计算图,其中有3层LSTM单元,每层有2个LSTM单元。我有以下疑问:
答案 0 :(得分:2)
关于语法的一点注意事项:从TF~1.0开始,您需要在循环中定义多个层而不是使用[cell] * num_layers
语法,如下所示:
lstm_cells = []
for _ in range(num_layers):
cell = tf.contrib.rnn.BasicLSTMCell(n_hidden)
lstm_cells.append(cell)
stacked_lstm_cell = tf.contrib.rnn.MultiRNNCell(lstm_cells)
主要问题:
num_layers
)的网络,其中每个层都包含一个隐藏状态长度为2(n_hidden
)的LSTM。更多相关内容。让我们来看看LSTM网络架构。 This is a pretty great overview that I recommend reading。基本上,单个LSTM单元保持一个隐藏状态,表示它到目前为止所看到的“记忆”,并且在每个更新步骤中,它决定使用“隐藏状态下与现有信息混合的新信息量”。门”。它还使用门来确定它将输出什么。看一下单个单元的更新过程:
我们首先确定忘记了多少旧信息(我们的遗忘门):f_k = sigmoid(W_f * [h_k-1, x_k] + b_f)
我们在此处运行网络的历史记录h_k-1
与当前观察x_k
连接。您的历史记录向量h
的大小由n_hidden
定义。权重W_f
和偏见b_f
将通过培训程序学习。
我们确定要合并多少新信息(我们的输入门,i_k
),并创建一些新的候选单元状态(c'_k
):
i_k = sigmoid(W_i * [h_k-1, x_k] + b_i)
c`_k = tanh(W_c * [h_k-1, x_k] + b_c)
同样,我们正在使用旧的内部状态h_k-1
和新的观察x_k
来确定下一步该做什么。单元格状态c
和候选单元格状态c'
的大小也由<{1}}确定。 n_hidden
和W_*
是我们将要学习的更多参数。
将旧信息与新候选状态相结合,以提出新的单元格状态:b_*
这里我们正在进行逐元素乘法而不是点积或其他任何东西。基本上我们会选择保留多少旧信息(c_k = f_k * c_k-1 + i_k * c'_k
),以及要合并多少新信息(f_k * c_k-1
)。
最后,我们通过输出门确定我们想要输出多少单元状态:
i_k * c'_k
基本上我们将旧信息和新信息混合到内部“单元状态”o_k = sigmoid(W_o * [h_k-1, x_k] + b_o)
h_k = o_k * tanh(c_k)
中,然后在c_k
中输出一些信息。我建议您同时查看gated recurrent unit (GRU) network,其执行方式与LSTM相似,但结构稍微容易理解。
现在讨论多层网络的堆叠方式。基本上,你有一些看起来像这样的东西:
h_k
所以你的观察进入第一个网络,然后该网络的输出作为输入馈送到下一个网络,它将其与自己的内部状态混合以产生输出,然后输出成为第三个网络的输入,等等到最后。这应该有助于学习数据中的时间结构。我对此没有很好的引用。
通常,如果您正在进行分类(例如),您将在最后一个网络的输出上抛出最终完全连接的图层,以获得一定程度的信心,即您观察到的进程位于您正在分类的每个类别中。
您可以使用以下内容打印出您的网络将要学习的所有可训练变量:
x_k ---> (network 0) --h0_k--> (network_1) --h1_k--> (network_2) --h2_k-->
Tensorflow通过组合不同的操作做了一些奇特的事情,所以你可能会看到一些奇怪的形状,显然缺少重量矩阵和偏差,但它就在那里。基本上你正在学习每个门的重量和偏差。在上面,那将是:
for var in tf.trainable_variables():
print('{}\nShape: {}'.format(var.name, var.get_shape()))
,W_f
,W_i
和W_c
W_o
,b_f
,b_i
和b_c
我更熟悉TF如何处理GRU架构,它基本上将所有门组合成一个大矩阵运算,因此你有一个组合权重矩阵和一个组合偏置矢量用于所有门。然后它将结果分成每个单独的门,以便在正确的位置应用它们。只是一个FYI,以防你看起来每个单元的每个步骤都没有权重和偏差。