【问题标题】:Tensorflow: What's the difference between the use of tf.mat_fn() or tf.nn.dynamic_rnn() to apply layers before an LSTM?Tensorflow:在 LSTM 之前使用 tf.mat_fn() 或 tf.nn.dynamic_rnn() 应用层有什么区别?
【发布时间】:2016-11-30 11:45:39
【问题描述】:

这个问题是关于使用 Tensorflow 的编码策略。我想创建一个由以下组成的小型分类器网络:

  • 1:一个输入
  • 2:一个简单的全连接层(W*x+B)
  • 3:一个 LSTM 层
  • 4:softmax 层
  • 5:一个输出

在 tensorflow 中,要使用 tf.nn.dynamic_rnn() 类,我们需要将一批序列发送到网络。到目前为止,它运行良好(我喜欢这个库)。

但由于我想在我的序列的每个特征上应用一个简单的层(我的描述中的第二层),我想知道:

  • 我是否在我的 LSTM 层之前使用这个简单的层,并将两者都传递给 tf.nn.dynamic_rnn() 操作...

  • 我是否使用了函数tf.map_fn() 两次(一次用于解包批次,一次用于解包序列),如果理解得当,能够解包我的序列并在每个特征行上应用一层。

通常,它应该给我同样的结果?如果是这样,我应该使用什么?

感谢您的宝贵时间!

【问题讨论】:

    标签: python tensorflow deep-learning lstm


    【解决方案1】:

    我最近遇到了一个类似的场景,我想链接循环层和非循环层。

    我是否在我的 LSTM 层之前使用这个简单的层并将两者都传递给 tf.nn.dynamic_rnn() 操作...

    这行不通。函数dynamic_rnn 需要一个单元格作为它的第一个参数。单元格是从tf.nn.rnn_cell.RNNCell 继承的类。此外,dynamic_rnn 的第二个输入参数应该是至少具有 3 个维度的张量,其中前两个维度是批处理和时间 (time_major=False) 或时间和批处理 (time_major=True)。

    我是否使用函数 tf.map_fn() 两次(一次用于解包批次,一次用于解包序列),如果理解得当,可以解包我的序列并在每个特征行上应用一层。

    这可能有效,但在我看来不是一个有效且干净的解决方案。首先,没有必要“解包”,因为您可能希望对成批的特征和时间步执行一些操作,其中批次中的每个观察都独立于其他观察。

    我对这个特定问题的解决方案是创建一个tf.nn.rnn_cell.RNNCell 的子类。在我的例子中,我想要一个简单的前馈层,它可以迭代所有的时间步,并且可以在dynamic_rnn 中使用:

    import tensorflow as tf
    
    class FeedforwardCell(tf.nn.rnn_cell.RNNCell):
      """A stateless feedforward cell that can be used with MultiRNNCell
      """
      def __init__(self, num_units, activation=tf.tanh, dtype=tf.float32):
        self._num_units = num_units
        self._activation = activation
        # Store a dummy state to make dynamic_rnn happy.
        self.dummy = tf.constant([[0.0]], dtype=dtype)
    
      @property
      def state_size(self):
        return 1
    
      @property
      def output_size(self):
        return self._num_units
    
      def zero_state(self, batch_size, dtype):
        return self.dummy
    
      def __call__(self, inputs, state, scope=None):
        """Basic feedforward: output = activation(W * input)."""
        with tf.variable_scope(scope or type(self).__name__):  # "FeedforwardCell"
          output = self._activation(tf.nn.rnn_cell._linear(
            [inputs], self._num_units, True))
          return output, self.dummy
    

    这个类的一个实例可以在一个带有“普通”RNN 单元的列表中传递给tf.nn.rnn_cell.MultiRNNCell 初始化器。生成的对象实例可以作为cell 输入参数传递给dynamic_rnn

    需要注意的重要一点:dynamic_rnn 期望循环单元在被调用时返回一个状态。因此,我在FeedforwardCell 中使用dummy 作为假状态变量。

    我的解决方案可能不是将循环层和非循环层链接在一起的最顺畅或最佳方式。我很想听听其他 Tensorflow 用户的建议。

    编辑 如果您选择使用dynamic_rnnsequence_length 输入参数,那么state_size 应该是self._num_units 并且dummy 状态应该具有[batch_size, self.state_size] 的形状。换句话说,状态不能是标量。注意bidirectional_dynamic_rnn 要求sequence_length 参数不是None,而dynamic_rnn 没有这个要求。 (这在 TF 文档中的记录很薄弱。)

    【讨论】:

      猜你喜欢
      • 2020-03-04
      • 2017-07-31
      • 1970-01-01
      • 2011-10-22
      • 1970-01-01
      • 2017-08-19
      • 1970-01-01
      • 2011-02-07
      • 1970-01-01
      相关资源
      最近更新 更多