Tensorflow и Keras: LSTM плохо справляется с проблемой seq2seq с четким решением - PullRequest
1 голос
/ 01 августа 2020

Я изучаю задачи tensorflow и seq2seq для машинного перевода. Для этого я дал мне следующую задачу:

Я создал Excel, содержащий случайные даты разных типов, например:

  1. 05.09.2192
  2. martes, 07 de mayo de 2329
  3. Пятница, 30 декабря 2129 г.

В моем наборе данных каждый тип встречается 1000 раз. Это моя стоимость поезда (X). Мои целевые (Y) значения всегда находятся в одной половине этого типа:

  • 05.09.2192
  • 07.03.2329
  • 30.12.2129

А в другой половине этого типа:

  • Samstag, 12 июня 2669
  • Donnerstag, 1. апрель 2990
  • Freitag, 10. ноябрь 2124

Чтобы модель могла различать эти два значения Y, другая контекстная информация (C) дается в виде текста:

  1. Ausgeschrieben (выписано)
  2. Дата (дата)

Итак, некоторые строки выглядят так:

Итак, моя цель - создать модель, которая способна «переводить» любой тип даты в немецкий тип даты, например, 05.09.2192.

Набор данных содержит 34000 пар.

Чтобы решить эту проблему, я использую токенизатор на основе символов для преобразования текста в целые числа:

tokenizer = keras.preprocessing.text.Tokenizer(filters='', char_level=True, oov_token="|")

Я использую модель кодировщика-декодера LSTM, и я ожидаю, что она достигнет идеальная точность, поскольку зависимость между X и Y может быть решена идеально.

Однако я достигаю максимальной точности 72%. Хуже того, точность достигает только этого, потому что заполнение создается хорошо. Например, большинство значений Y довольно короткие и поэтому дополнены. Таким образом, 12.02.2001 становится, например, ||||||||||||||||||||12.02.2001. Таким образом, модель хорошо учится генерировать маркер заполнения, но не ожидаемое значение.

Это структура модели, которую я использовал в своем последнем тесте:

from tensorflow.keras.layers import Concatenate

encoder_inputs = keras.layers.Input(batch_input_shape=[32,None], dtype=np.int32)
decoder_inputs = keras.layers.Input(batch_input_shape=[32,None], dtype=np.int32)
embeddings = keras.layers.Embedding(vocab_size, 1)
encoder_embeddings = embeddings(encoder_inputs)
decoder_embeddings = embeddings(decoder_inputs)

encoder_0 = keras.layers.Dense(128)(encoder_embeddings)
encoder_0d = keras.layers.Dropout(0.4)(encoder_0)
encoder_0_1 = keras.layers.Dense(256)(encoder_0d)
encoder_0_1d = keras.layers.Dropout(0.2)(encoder_0_1)
encoder_0_2 = keras.layers.Dense(128)(encoder_0_1d)
encoder_0_2d = keras.layers.Dropout(0.05)(encoder_0_2)
encoder_0_3 = keras.layers.Dense(64)(encoder_0_2d)

encoder_1 = keras.layers.LSTM(64, return_state=True, return_sequences=True, recurrent_dropout=0.2)
encoder_lstm_bidirectional = keras.layers.Bidirectional(encoder_1)
encoder_output, state_h1, state_c1, state_h2, state_c2 = encoder_lstm_bidirectional(encoder_0_3)
encoder_state = [Concatenate()([state_h1, state_h2]), Concatenate()([state_c1, state_c2])]

sampler = tfa.seq2seq.sampler.TrainingSampler()
decoder_cell = keras.layers.LSTMCell(64*2)

output_layer = keras.layers.Dense(vocab_size)

decoder = tfa.seq2seq.basic_decoder.BasicDecoder(decoder_cell, sampler, output_layer=output_layer)

final_outputs, final_state, final_sequence_lengths = decoder(decoder_embeddings, initial_state=encoder_state,
                                                             sequence_length=[sequence_length], training=True)
y_proba = tf.nn.softmax(final_outputs.rnn_output)

model = keras.Model(inputs=[encoder_inputs, decoder_inputs], outputs=[y_proba])

При необходимости я могу развернуть весь блокнот в github, но может есть простое решение, просто пока не видел. Спасибо за помощь!

1 Ответ

0 голосов
/ 06 августа 2020

Итак, на случай, если это поможет кому-то в будущем: модель сделала именно то, что я просил.

НО

Вы должны быть осторожны, чтобы предварительная обработка ваших данных не приводят к двусмысленности. Таким образом, вы должны предотвратить что-то вроде:

a -> b and also a -> c

При улучшении одного уравнения проиграет другое. Это была моя проблема. См. Этот пример:

eq1: 26.04.1994 -> 26.04.1994
eq2: 26.04.1994 -> Tuesday, 26.04.1994

С одной стороны, модели увеличивают точность для eq1. С другой стороны, это уменьшает потери для уравнения 2. Таким образом, 74% - это своего рода компромисс, как показала модель.

Чтобы решить эту проблему, мне пришлось добавить еще один фактор, который описывает данные более конкретно. Поэтому я добавил дополнительное условие, описывающее, записывается ли y или просто как тип даты. Итак, теперь у меня есть такая структура данных, и моя точность выросла до 98%:

eq1: 26.04.1994, dateformat -> 26.04.1994
eq2: 26.04.1994, written_out -> Tuesday, 26.04.1994
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...