wake-up-neo.com

Wie verwende ich mehrschichtiges bidirektionales LSTM in Tensorflow?

Ich möchte wissen, wie man mehrschichtiges bidirektionales LSTM in Tensorflow verwendet.

Ich habe den Inhalt von bidirektionalem LSTM bereits implementiert, möchte das Modell jedoch mit den hinzugefügten Multilayern vergleichen.

Wie soll ich in diesem Teil Code hinzufügen?

x = tf.unstack(tf.transpose(x, perm=[1, 0, 2]))
#print(x[0].get_shape())

# Define lstm cells with tensorflow
# Forward direction cell
lstm_fw_cell = rnn.BasicLSTMCell(n_hidden, forget_bias=1.0)
# Backward direction cell
lstm_bw_cell = rnn.BasicLSTMCell(n_hidden, forget_bias=1.0)

# Get lstm cell output
try:
    outputs, _, _ = rnn.static_bidirectional_rnn(lstm_fw_cell, lstm_bw_cell, x,
                                          dtype=tf.float32)
except Exception: # Old TensorFlow version only returns outputs not states
    outputs = rnn.static_bidirectional_rnn(lstm_fw_cell, lstm_bw_cell, x,
                                    dtype=tf.float32)

# Linear activation, using rnn inner loop last output
outputs = tf.stack(outputs, axis=1)
outputs = tf.reshape(outputs, (batch_size*n_steps, n_hidden*2))
outputs = tf.matmul(outputs, weights['out']) + biases['out']
outputs = tf.reshape(outputs, (batch_size, n_steps, n_classes))
7
Gi Yeon Shin

Sie können zwei verschiedene Ansätze verwenden, um ein mehrschichtiges Bilstm-Modell anzuwenden:

1) Verwenden Sie die vorherige Bilstm-Schicht als Eingabe für die nächste Bilstm. Am Anfang sollten Sie die Arrays mit Vorwärts- und Rückwärtszellen der Länge num_layers erstellen. Und 

for n in range(num_layers):
        cell_fw = cell_forw[n]
        cell_bw = cell_back[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), last_state = tf.nn.bidirectional_dynamic_rnn(cell_fw, cell_bw, output,
                                                                             initial_state_fw=state_fw,
                                                                             initial_state_bw=state_bw,
                                                                             scope='BLSTM_'+ str(n),
                                                                             dtype=tf.float32)

        output = tf.concat([output_fw, output_bw], axis=2)

2) Sehenswert auch einen anderen Ansatz stacked bilstm .

4
Taras Khakhulin

Dies ist im Wesentlichen dasselbe wie bei der ersten Antwort, jedoch mit ein wenig Variation der Verwendung des Bereichsnamens und mit zusätzlichen Dropout-Wrappern.

def bidirectional_lstm(input_data, num_layers, rnn_size, 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,
                                                              dtype=tf.float32)
            output = tf.concat(outputs,2)

    return output

Problem mit diesem Code ist jedoch, dass es nicht funktioniert, wenn num_layerstensor ist.

3
mnis

Wie @Taras hervorhob, können Sie Folgendes verwenden:

(1) tf.nn.bidirectional_dynamic_rnn()

(2) tf.contrib.rnn.stack_bidirectional_dynamic_rnn().

Alle vorherigen Antworten erfassen nur (1), daher gebe ich einige Details zu (2) an, insbesondere, da es normalerweise besser ist als (1). Für eine Vorstellung über die verschiedenen Konnektivitäten siehe hier .

Angenommen, Sie möchten einen Stapel von 3 BLSTM-Layern mit jeweils 64 Knoten erstellen:

num_layers = 3
num_nodes = 64


# Define LSTM cells
enc_fw_cells = [LSTMCell(num_nodes)for layer in range(num_layers)]
enc_bw_cells = [LSTMCell(num_nodes) for layer in range(num_layers)]

# Connect LSTM cells bidirectionally and stack
(all_states, fw_state, bw_state) = tf.contrib.rnn.stack_bidirectional_dynamic_rnn(
        cells_fw=enc_fw_cells, cells_bw=enc_bw_cells, inputs=input_embed, dtype=tf.float32)

# Concatenate results
for k in range(num_layers):
    if k == 0:
        con_c = tf.concat((fw_state[k].c, bw_state[k].c), 1)
        con_h = tf.concat((fw_state[k].h, bw_state[k].h), 1)
    else:
        con_c = tf.concat((con_c, fw_state[k].c, bw_state[k].c), 1)
        con_h = tf.concat((con_h, fw_state[k].h, bw_state[k].h), 1)

output = tf.contrib.rnn.LSTMStateTuple(c=con_c, h=con_h)

In diesem Fall verwende ich zu jedem Zeitpunkt die Endzustände des gestapelten biRNN und nicht die Zustände (gespeichert in all_states), da ich ein Codierungsdecodierungsschema verwendete, bei dem der obige Code nur der Codierer war.

1
dopexxx

Oben auf Taras Antwort. Hier ist ein weiteres Beispiel, bei dem nur zweilagiges bidirektionales RNN mit GRU-Zellen verwendet wird 

    embedding_weights = tf.Variable(tf.random_uniform([vocabulary_size, state_size], -1.0, 1.0))
    embedding_vectors = tf.nn.embedding_lookup(embedding_weights, tokens)

    #First BLSTM
    cell = tf.nn.rnn_cell.GRUCell(state_size)
    cell = tf.nn.rnn_cell.DropoutWrapper(cell, output_keep_prob=1-dropout)
    (forward_output, backward_output), _ = \
        tf.nn.bidirectional_dynamic_rnn(cell, cell, inputs=embedding_vectors,
                                        sequence_length=lengths, dtype=tf.float32,scope='BLSTM_1')
    outputs = tf.concat([forward_output, backward_output], axis=2)

    #Second BLSTM using the output of previous layer as an input.
    cell2 = tf.nn.rnn_cell.GRUCell(state_size)
    cell2 = tf.nn.rnn_cell.DropoutWrapper(cell2, output_keep_prob=1-dropout)
    (forward_output, backward_output), _ = \
        tf.nn.bidirectional_dynamic_rnn(cell2, cell2, inputs=outputs,
                                        sequence_length=lengths, dtype=tf.float32,scope='BLSTM_2')
    outputs = tf.concat([forward_output, backward_output], axis=2)

Übrigens, vergessen Sie nicht, einen anderen Bereichsnamen hinzuzufügen. Ich hoffe das hilft.