2

I'm building a multilayered bidirectional RNN using Tensorflow .I'm a bit confused about the implementation though .

I have built two functions that creates multilayered bidirectional RNN the first one works fine , but I'm not sure about the predictions its making, as it is performing as a unidirectional multilayered RNN . below is my implementation :

def encoding_layer_old(rnn_inputs, rnn_size, num_layers, keep_prob, 
                   source_sequence_length, source_vocab_size, 
                   encoding_embedding_size):
    """
    Create encoding layer
    :param rnn_inputs: Inputs for the RNN
    :param rnn_size: RNN Size
    :param num_layers: Number of layers
    :param keep_prob: Dropout keep probability
    :param source_sequence_length: a list of the lengths of each sequence in the batch
    :param source_vocab_size: vocabulary size of source data
    :param encoding_embedding_size: embedding size of source data
    :return: tuple (RNN output, RNN state)
    """
    # Encoder embedding
    enc_embed = tf.contrib.layers.embed_sequence(rnn_inputs, source_vocab_size, encoding_embedding_size)
    
    def create_cell_fw(rnn_size):
        with tf.variable_scope("create_cell_fw"):
            lstm_cell = tf.contrib.rnn.LSTMCell(rnn_size,initializer=tf.random_uniform_initializer(-0.1,0.1,seed=2), reuse=False)
            drop = tf.contrib.rnn.DropoutWrapper(lstm_cell, output_keep_prob=keep_prob)
        return drop
    def create_cell_bw(rnn_size):
        with tf.variable_scope("create_cell_bw"):
            lstm_cell = tf.contrib.rnn.LSTMCell(rnn_size,initializer=tf.random_uniform_initializer(-0.1,0.1,seed=2), reuse=False)
            drop = tf.contrib.rnn.DropoutWrapper(lstm_cell, output_keep_prob=keep_prob)
        return drop    
    
    
    enc_cell_fw = tf.contrib.rnn.MultiRNNCell([create_cell_fw(rnn_size) for _ in range(num_layers)])
    enc_cell_bw = tf.contrib.rnn.MultiRNNCell([create_cell_bw(rnn_size) for _ in range(num_layers)])
    ((encoder_fw_outputs, encoder_bw_outputs),(encoder_fw_final_state,encoder_bw_final_state)) = tf.nn.bidirectional_dynamic_rnn(enc_cell_fw,enc_cell_bw, enc_embed, 
                                                        sequence_length=source_sequence_length,dtype=tf.float32)
    encoder_outputs = tf.concat([encoder_fw_outputs, encoder_bw_outputs], 2)
    print(encoder_outputs)
    #encoder_final_state_c=[]#tf.Variable([num_layers] , dtype=tf.int32)
    #encoder_final_state_h=[]#tf.Variable([num_layers] , dtype=tf.int32)
    encoder_final_state = ()
    for x in range((num_layers)):
        encoder_final_state_c=tf.concat((encoder_fw_final_state[x].c, encoder_bw_final_state[x].c), 1)#tf.stack(tf.concat((encoder_fw_final_state[x].c, encoder_bw_final_state[x].c), 1))
        encoder_final_state_h=tf.concat((encoder_fw_final_state[x].h, encoder_bw_final_state[x].h), 1)# tf.stack(tf.concat((encoder_fw_final_state[x].h, encoder_bw_final_state[x].h), 1))
        encoder_final_state =encoder_final_state+ (tf.contrib.rnn.LSTMStateTuple(c=encoder_final_state_c,h=encoder_final_state_h),)
    
    #encoder_final_state = tf.contrib.rnn.LSTMStateTuple(c=encoder_final_state_c,h=encoder_final_state_h)
    print('before')
    print(encoder_fw_final_state)
    return encoder_outputs, encoder_final_state

  

I have found another implementation here as shown below :

t

def encoding_layer(rnn_inputs, rnn_size, num_layers, keep_prob, 
                   source_sequence_length, source_vocab_size, 
                   encoding_embedding_size):
    """
    Create encoding layer
    :param rnn_inputs: Inputs for the RNN
    :param rnn_size: RNN Size
    :param num_layers: Number of layers
    :param keep_prob: Dropout keep probability
    :param source_sequence_length: a list of the lengths of each sequence in the batch
    :param source_vocab_size: vocabulary size of source data
    :param encoding_embedding_size: embedding size of source data
    :return: tuple (RNN output, RNN state)
    """
    # Encoder embedding
    enc_embed = tf.contrib.layers.embed_sequence(rnn_inputs, source_vocab_size, encoding_embedding_size)
    
    def create_cell_fw(rnn_size,x):
        with tf.variable_scope("create_cell_fw_"+str(x)):
            lstm_cell = tf.contrib.rnn.LSTMCell(rnn_size,initializer=tf.random_uniform_initializer(-0.1,0.1,seed=2) , reuse=tf.AUTO_REUSE )
            drop = tf.contrib.rnn.DropoutWrapper(lstm_cell, output_keep_prob=keep_prob)
        return drop
    def create_cell_bw(rnn_size,x):
        with tf.variable_scope("create_cell_bw_"+str(x)):
            lstm_cell = tf.contrib.rnn.LSTMCell(rnn_size,initializer=tf.random_uniform_initializer(-0.1,0.1,seed=2) ,reuse=tf.AUTO_REUSE )
            drop = tf.contrib.rnn.DropoutWrapper(lstm_cell, output_keep_prob=keep_prob)
        return drop
    enc_cell_fw = [create_cell_fw(rnn_size,x) for x in range(num_layers)]
    enc_cell_bw = [create_cell_bw(rnn_size,x) for x in range(num_layers)]
    
    output=enc_embed
    for n in range(num_layers):
            cell_fw = enc_cell_fw[n]
            cell_bw = enc_cell_bw[n]
            state_fw = cell_fw.zero_state(batch_size, tf.float32)
            state_bw = cell_bw.zero_state(batch_size, tf.float32)
            
            ((output_fw, output_bw),(encoder_fw_final_state,encoder_bw_final_state))= tf.nn.bidirectional_dynamic_rnn(cell_fw, cell_bw, output,source_sequence_length,
                                                              state_fw, state_bw, dtype=tf.float32)

            output = tf.concat([output_fw, output_bw], axis=2)
            final_state=tf.concat([encoder_fw_final_state,encoder_bw_final_state], axis=2 )
    return output , final_state

the problem with this implementation is that I get a shape error :

Trying to share variable bidirectional_rnn/fw/lstm_cell/kernel, but specified shape (168, 224) and found shape (256, 224).

it appears that other people have faced a similar when creating the RNN cells and the solution is to use the MultiRNNCell to create the layered cell . But if use MultiRNNCell I will not be able to use the second implementation since the multiRNNCell does not support indexing. thus I will not be ale to loop through the list of cells and create multiples RNNs .

I would really appreciate your help to guide me on this .

I'm using tensorflow 1.3

Community
  • 1
  • 1
mousa alsulaimi
  • 316
  • 1
  • 14

1 Answers1

0

Both codes does seem a little overly complex. Anyway I tried a much simpler version of it and it worked. In your code, try after removing reuse=tf.AUTO_REUSE from create_cell_fw and create_cell_bw. Below is my simpler implementation.

def encoding_layer(input_data, num_layers, rnn_size, sequence_length, keep_prob):

    output = input_data
    for layer in range(num_layers):
        with tf.variable_scope('encoder_{}'.format(layer),reuse=tf.AUTO_REUSE):

            cell_fw = tf.contrib.rnn.LSTMCell(rnn_size, initializer=tf.truncated_normal_initializer(-0.1, 0.1, seed=2))
            cell_fw = tf.contrib.rnn.DropoutWrapper(cell_fw, input_keep_prob = keep_prob)

            cell_bw = tf.contrib.rnn.LSTMCell(rnn_size, initializer=tf.truncated_normal_initializer(-0.1, 0.1, seed=2))
            cell_bw = tf.contrib.rnn.DropoutWrapper(cell_bw, input_keep_prob = keep_prob)

            outputs, states = tf.nn.bidirectional_dynamic_rnn(cell_fw, 
                                                              cell_bw, 
                                                              output,
                                                              sequence_length,
                                                              dtype=tf.float32)
            output = tf.concat(outputs,2)
            state = tf.concat(states,2)

    return output, state
betelgeuse
  • 1,136
  • 3
  • 13
  • 25
  • indeed this works . I tried something similar yesterday and it worked fine. but this returns result similar to my first function the one which uses MultiRNNCell. Any Idea if there is a different between using MultiRNNCell and connecting multiple bidirectional_dynamic_rnns together. if you think that this should be asked in a separate stack overflow question please do not hesitate to say so . – mousa alsulaimi Aug 20 '18 at 18:06
  • That's alright @mousaalsulaimi I believe [this](https://stackoverflow.com/questions/49242266/difference-between-multirnncell-and-stack-bidirectional-dynamic-rnn-in-tensorflo) post should clear all your doubts. It's explained beautifully there. – betelgeuse Aug 21 '18 at 05:59