使LSTM细胞可培养

我使用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)

然而,在我看来,对于张量流中实际发生的事情存在一些不确定性。 据我所知,这段代码给了我一个计算图,其中有3层LSTM单元,每层有2个LSTM单元。 我有以下疑问:

  • 这3个LSTM层之间的权重是否作为变量处理?
  • 如果这些权重被视为变量,他们在训练期间是否被修改?
  • LSTM单元有操作员,如忘记等。这些操作也被视为变量,因此在训练时进行调整?

  • 关于语法的一点注意事项:从[cell] * num_layers ,您需要在一个循环中定义多个层,而不是使用[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)
    

    针对您的主要问题:

  • 您的代码为您提供了一个3层( num_layers )的网络,其中每个层包含一个长度为2( n_hidden )的隐藏状态的LSTM。 更多关于这一点。
  • 在三个LSTM层之间没有权重:每个LSTM将其输出馈送到下一个LSTM的输入。
  • 除非你告诉TF不要训练某些东西,否则网络中的所有权重和偏差都将被视为可训练变量并通过反向传播进行训练。
  • LSTM中的忘记和更新等操作对网络输入和网络先前隐藏状态的线性组合执行一些功能。 这个“线性组合”部分涉及由网络训练的权重和偏差。
  • 看看LSTM


    我们来看看LSTM网络架构。 这是一个非常好的概述,我建议阅读。 基本上,单个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'大小也由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 ,然后在h_k输出一些信息量。 我还建议寻找门控周期性单元(GRU)网络,其性能类似于LSTM,但要理解的结构稍微简单一些。

    现在谈谈多层网络如何堆叠起来。 基本上,你有这样的东西:

    x_k ---> (network 0) --h0_k--> (network_1) --h1_k--> (network_2) --h2_k-->
    

    因此,您的观察进入第一个网络,然后网络的输出作为输入馈送到下一个网络,该网络将其与其自身的内部状态混合以产生输出,然后该输出成为第三网络的输入,等等直到最后。 这应该有助于学习数据中的时间结构。 我没有很好的引用。

    通常情况下,如果您正在进行分类(例如),那么您会在最后一个网络的输出结果上抛出一个最终的完全连接层,以获得一定程度的信心,即您观察的过程位于您正在分类的每个类别内。

    可训练的变量


    你可以打印出你的网络将要学习的所有可训练变量,如下所示:

    for var in tf.trainable_variables():
        print('{}nShape: {}'.format(var.name, var.get_shape()))
    

    Tensorflow通过结合不同的操作来做一些奇特的事情,所以你可能会看到一些奇怪的形状,显然缺少重量矩阵和偏见,但它都在那里。 基本上你正在学习每个门中使用的权重和偏差。 在上面,这将是:

  • 每一层的重量: W_fW_iW_cW_o
  • 偏见: b_c b_fb_ib_cb_o
  • 以及您在最后一个LSTM图层顶部添加的附加输出图层权重/偏差
  • 我更熟悉TF如何处理GRU架构,它基本上将所有的门组合成一个单一的大矩阵运算,所以你有一个组合的权重矩阵和一个用于所有门的组合权向量。 然后将结果分成每个门,将它们应用到正确的位置。 只是一个FYI的情况下,它看起来像你没有权重和每个单元格的每个单独步骤的偏见。

    链接地址: http://www.djcxy.com/p/32129.html

    上一篇: make LSTM cell trainable

    下一篇: Confused about weight and bias dependencies affecting learning