Как объединить 2 слоя LSTM с tenorflow 2.0 в конфигурации Encoder / Decoder - PullRequest
0 голосов
/ 24 октября 2019

У меня есть проблема, которая может очень просто привести к специалистам с tenorflow 2.0

Я следую этому руководству -> https://machinetalk.org/2019/03/29/neural-machine-translation-with-attention-mechanism и все работает отлично, я не совсем понялпричина этой четко сформулированной структуры, а не простой функциональной API, но учитывая, что она имеет дело с текстом, я предположил, что для этого есть причина.

Итак, я попытался сложить еще один слой LSTM поверх существующего, сначала просто на стороне кодера, чтобы посмотреть, что произойдет, я не совсем понял использование «состояний» LSTM, поэтому я просто предположил, что этоработать, и я записал свою новую версию кодировщика, проблема в том, что я получаю странную ошибку, и я не знаю, как исправить свой код, учитывая, что каждое руководство говорит, как написать что-то, но они забывают сказать, почему они 'делаю это

Итак, я написал:

class Encoder2(tf.keras.Model):
    def __init__(self, vocab_size, embedding_size, lstm_size):
        super(Encoder2, self).__init__()
        self.lstm_size = lstm_size
        self.lstm_size2 = (int)(lstm_size)
        self.embedding = tf.keras.layers.Embedding(vocab_size, embedding_size)
        self.lstm = tf.keras.layers.LSTM(lstm_size, return_sequences=True, return_state=True)
        self.lstm2 = tf.keras.layers.LSTM(self.lstm_size2, return_sequences = True, return_state = True)

    def call(self, sequence, states1, states2):
        embed = self.embedding(sequence)
        output = self.lstm(embed, initial_state=states1)
        output, state_h, state_c = self.lstm2(output, initial_state=states2)

        return output, state_h, state_c

    def init_states(self, batch_size):
        return ([tf.zeros([batch_size, self.lstm_size]),
                tf.zeros([batch_size, self.lstm_size])],
                [tf.zeros([batch_size, self.lstm_size2]),
                tf.zeros([batch_size, self.lstm_size2])]) 

Мне не очень понятно использование «состояний» для слоев LSTM, возможно, я сделал несколько ошибок при построении двух слоев. Во всяком случае, я попробовал код только с одной итерацией набора данных, чтобы увидеть, что происходит, например:


encoder = Encoder2(in_vocab_size, EMBEDDING_SIZE, LSTM_SIZE)
decoder = Decoder(out_vocab_size, EMBEDDING_SIZE, LSTM_SIZE)  

en_initial_states = encoder.init_states(BATCH_SIZE)
for batch, (source_seq, target_seq_in, target_seq_out) in enumerate(training_set.take(-1)):
    if(len(source_seq)== BATCH_SIZE):
      train_step(source_seq, target_seq_in,
                          target_seq_out, en_initial_states)
      break
encoder.summary()
@tf.function
def train_step(source_seq, target_seq_in, target_seq_out, en_initial_states):
    loss = 0
    with tf.GradientTape() as tape:
        en_outputs = encoder(source_seq, en_initial_states[0], en_initial_states[1])
        #en_outputs = encoder(source_seq)
        en_states = en_outputs[1:]
        de_state_h, de_state_c = en_states

        # We need to create a loop to iterate through the target sequences
        for i in range(target_seq_out.shape[1]):
            # Input to the decoder must have shape of (batch_size, length)
            # so we need to expand one dimension
            decoder_in = tf.expand_dims(target_seq_in[:, i], 1)
            logit, de_state_h, de_state_c, _ = decoder(
                decoder_in, (de_state_h, de_state_c), en_outputs[0])

            # The loss is now accumulated through the whole batch
            loss += loss_func(target_seq_out[:, i], logit)

    variables = encoder.trainable_variables + decoder.trainable_variables
    gradients = tape.gradient(loss, variables)
    optimizer.apply_gradients(zip(gradients, variables))

    return loss / target_seq_out.shape[1]

, и я получаю эту ошибку:

AssertionError                            Traceback (most recent call last)
<ipython-input-84-8e6b52715d0e> in <module>()
     13     if(len(source_seq)== BATCH_SIZE):
     14       train_step(source_seq, target_seq_in,
---> 15                           target_seq_out, en_initial_states)
     16       break
     17 encoder.summary()

8 frames
/tensorflow-2.0.0/python3.6/tensorflow_core/python/framework/func_graph.py in wrapper(*args, **kwargs)
    903           except Exception as e:  # pylint:disable=broad-except
    904             if hasattr(e, "ag_error_metadata"):
--> 905               raise e.ag_error_metadata.to_exception(e)
    906             else:
    907               raise

AssertionError: in converted code:

    <ipython-input-67-5f4e7c851f23>:5 train_step  *
        en_outputs = encoder(source_seq, en_initial_states[0], en_initial_states[1])
    /tensorflow-2.0.0/python3.6/tensorflow_core/python/keras/engine/base_layer.py:847 __call__
        outputs = call_fn(cast_inputs, *args, **kwargs)
    <ipython-input-66-0a370f7cebcd>:13 call  *
        output, state_h, state_c = self.lstm2(output, initial_state=states2)
    /tensorflow-2.0.0/python3.6/tensorflow_core/python/keras/layers/recurrent.py:620 __call__
        self._num_constants)
    /tensorflow-2.0.0/python3.6/tensorflow_core/python/keras/layers/recurrent.py:2716 _standardize_args
        assert initial_state is None and constants is None

    AssertionError: 

Мои вопросыявляются:

1) Почему эта структура в руководстве? Разве не намного проще иметь одну модель с кодом кодера и декодера внутри нее?

2) Какое использование состояний в слоях LSTM?

3) Что не так смой код?

Большое вам спасибо за ваше время

...