Tensorflow中基于CuDnnGRU的RNN实现的简单示例

Thr*_*bit 6 tensorflow rnn

我将以下代码用于标准GRU实施:

def BiRNN_deep_dynamic_FAST_FULL_autolength(x,batch_size,dropout,hidden_dim):

seq_len=length_rnn(x)

with tf.variable_scope('forward'):
    lstm_cell_fwd =tf.contrib.rnn.GRUCell(hidden_dim,kernel_initializer=tf.contrib.layers.xavier_initializer(),bias_initializer=tf.contrib.layers.xavier_initializer())
    lstm_cell_fwd = tf.contrib.rnn.DropoutWrapper(lstm_cell_fwd, output_keep_prob=dropout)
with tf.variable_scope('backward'):
    lstm_cell_back =tf.contrib.rnn.GRUCell(hidden_dim,kernel_initializer=tf.contrib.layers.xavier_initializer(),bias_initializer=tf.contrib.layers.xavier_initializer())
    lstm_cell_back = tf.contrib.rnn.DropoutWrapper(lstm_cell_back, output_keep_prob=dropout)

outputs,_= tf.nn.bidirectional_dynamic_rnn(cell_fw=lstm_cell_fwd,cell_bw= lstm_cell_back,inputs=x,sequence_length=seq_len,dtype=tf.float32,time_major=False)
outputs_fwd,outputs_bck=outputs

### fwd matrix is the matrix that keeps all the last [-1] vectors
fwd_matrix=tf.gather_nd(outputs_fwd, tf.stack([tf.range(batch_size), seq_len-1], axis=1))       ###  99,64

outputs_fwd=tf.transpose(outputs_fwd,[1,0,2])
outputs_bck=tf.transpose(outputs_bck,[1,0,2])

return outputs_fwd,outputs_bck,fwd_matrix
Run Code Online (Sandbox Code Playgroud)

谁能提供一个简单的示例来说明如何以类似方式使用tf.contrib.cudnn_rnn.CudnnGRU Cell?只是换出单元格是行不通的。

第一个问题是CuDnnGRU单元没有任何丢弃包装,这很好。其次,它似乎不适用于tf.nn.bidirectional_dynamic_rnn。任何帮助表示赞赏。

小智 8

CudnnGRU不是RNNCell实例。更类似于dynamic_rnn

下面的张量操纵是等效的,其中input_tensor是时间主要张量,即shape [max_sequence_length, batch_size, embedding_size]。CudnnGRU期望输入张量是时间主张量(与更标准的批处理主格式(即shape相对[batch_size, max_sequence_length, embedding_size])),并且无论如何,将时间主张量与RNN ops一起使用是一个好习惯,因为它们速度更快。

CudnnGRU:

rnn = tf.contrib.cudnn_rnn.CudnnGRU(
  num_rnn_layers, hidden_size, direction='bidirectional')

rnn_output = rnn(input_tensor)
Run Code Online (Sandbox Code Playgroud)

CudnnCompatibleGRUCell:

rnn_output = input_tensor
sequence_length = tf.reduce_sum(
  tf.sign(inputs),
  reduction_indices=0)  # 1 if `input_tensor` is batch-major.

  for _ in range(num_rnn_layers):
    fw_cell = tf.contrib.cudnn_rnn.CudnnCompatibleGRUCell(hidden_size)
    bw_cell = tf.contrib.cudnn_rnn.CudnnCompatibleGRUCell(hidden_size)
    rnn_output = tf.nn.bidirectional_dynamic_rnn(
      fw_cell, bw_cell, rnn_output, sequence_length=sequence_length,
      dtype=tf.float32, time_major=True)[1]  # Set `time_major` accordingly
Run Code Online (Sandbox Code Playgroud)

请注意以下几点:

  1. 如果您使用的是LSTM,则无需使用CudnnCompatibleLSTMCell; 您可以使用标准LSTMCell。但是对于GRU,Cudnn实现具有本质上不同的数学运算,尤其是权重更高(请参阅文档)。
  2. 与不同dynamic_rnnCudnnGRU不允许您指定序列长度。仍然要快一个数量级,但是您在提取输出时必须要小心(例如,如果您对填充和长度变化的每个序列的最终隐藏状态感兴趣,则需要每个序列的长度)。
  3. rnn_output在这两种情况下,都可能是一个包含很多(不同)东西的元组。请参考文档,或只是打印出来,以检查所需的输出部分。