Анализ роли параметров Return_state и Return_seq в моделях последовательности на основе LSTM

Введение:

RNN - это основные строительные блоки рекуррентных нейронных сетей. RNN имеет два входа и два выхода. Из двух входов один - это вход из набора данных, а другой вход - из выхода скрытого состояния предыдущего блока RNN. Из двух выходов один - это выход, который предсказывает цель для RNN, а другой выход - это выход скрытого состояния, который переходит в следующий блок RNN как вход скрытого состояния.

Я знаю, что предыдущий абзац был потрясающим, если вы впервые видите RNN. Чтобы упростить жизнь, посмотрите на Рис.1.

Различные приложения моделей последовательности принимают эти входы и выходы по-разному. Два аргумента, которые сильно помогают в манипулировании выходными данными единиц RNN, - это return_state и r eturn_sequence в Keras framework Deep Learning . В этой статье мы увидим, как эти два аргумента используются в разных приложениях.

Информация, представленная в документации Keras:

Состояние возврата и последовательность возврата - два очень важных параметра на уровне RNN Keras. Существует много путаницы относительно того, как работают эти два параметра. Во многом это связано с отсутствием хорошего объяснения в документации Keras. Они не предоставили никаких примеров для понимания этих параметров.

Поскольку LSTM - наиболее используемая модель последовательности, мы будем использовать LSTM для нашего объяснения.

keras.layers.LSTM(units, activation=’tanh’, recurrent_activation=’hard_sigmoid’, use_bias=True, kernel_initializer=’glorot_uniform’, recurrent_initializer=’orthogonal’, bias_initializer=’zeros’, unit_forget_bias=True, kernel_regularizer=None, recurrent_regularizer=None, bias_regularizer=None, activity_regularizer=None, kernel_constraint=None, recurrent_constraint=None, bias_constraint=None, dropout=0.0, recurrent_dropout=0.0, implementation=1, return_sequences=False, return_state=False, go_backwards=False, stateful=False, unroll=False)

Выше код - это слой LSTM от Keras. Мы видим, как указывается так много аргументов.

return_sequences: логическое. Следует ли возвращать последний вывод. в выходной последовательности или в полной последовательности.

return_state: логическое. Следует ли возвращать последнее состояние в дополнение к выходным данным.

В этой статье мы сосредоточимся в основном на return_sequences и return_state. Мы также видим, что по умолчанию для них установлено значение False. Это означает, что если мы не указываем их в слое LSTM, для них установлено значение False, чтобы сделать их True, мы должны явно указать. Это параметры логического типа.

Что такое return_state и return_sequences:

На уровне LSTM return_state может иметь значение true или false. Речь идет о рассмотрении вывода скрытого состояния последнего временного шага или его игнорирования. Если установлено значение False, которое является параметром по умолчанию, мы не используем и не берем вывод скрытого состояния последнего временного шага. Если это True, мы берем вывод скрытого состояния последнего временного шага и используем его в другом месте, где он нам нужен.

Каков последний временной шаг в слое LSTM?

Этот вопрос очень важен для понимания того, что зависит от конкретного приложения. LSTM - это повторяющийся блок, который повторяется снова и снова в заданном окне. В языковой модели (рис. 2) мы передаем выходные данные каждого временного шага в качестве входных данных для следующего временного шага. В этом случае каждый временной шаг считается последним временным шагом. В случае классификации (рис. 3) с использованием архитектуры «многие к одному» временной шаг конечного выходного блока считается последним временным шагом.

В случае моделей seq2seq (рис. 4), кодировщик рассматривается как блок длины входного предложения. LSTM, соответствующий последнему слову в предложении, считается последним временным шагом. В то время как в декодере он работает как языковая модель, где выходные данные каждого временного шага предоставляются в качестве входных данных для следующего временного шага. Таким образом, в декодере каждый блок LSTM считается последним временным шагом.

Разобравшись в return_State, теперь попробуем разобраться в return_sequence. return_sequences заботится о выводе на каждом временном шаге, тогда как return_state относился к скрытому выводу (состояние ячейки и скрытое состояние в LSTM) последнего временного шага. Например, если мы классифицируем предложение из 10 слов, мы должны учитывать повторяющуюся единицу из 10 единичных временных шагов, которая работает как установка многие-к-одному. В этом приложении из 10 выходов, то есть временных шагов, мы берем только последний выход временного шага, игнорируя другие выходы. В таких случаях для return_sequences установлено значение False, а для return_state установлено значение False.

В таких приложениях, как seq2seq, Language model и Text summarization, где нам нужна настройка "многие ко многим", мы устанавливаем для return_sequences значение true. Фактически, общее заявление, которое мы сделали только что, вводит в заблуждение. Поскольку разные архитектуры для одного и того же приложения имеют разные варианты наборов return_sequences и return_state.

Большая путаница возникает из-за того, что стандартные приложения, такие как классификация текста, языковая модель и seq2seq, имеют разные варианты реализации, которые используют идею выполнения последнего временного шага с использованием состояния возврата по-разному. Чтобы не попасть в подобную ловушку, нужно хорошо разбираться в этих параметрах. Ниже мы объясним rerturn_sequence и return_state, используя различные варианты нейронных машинных переводов и языковых моделей, и мы не будем вдаваться в детали различных архитектур.

Нейронный машинный перевод:

Пример-1:

Это вариант кода нейронного машинного перевода, который не использует дуэт кодировщик-декодер. Модель выглядит как многослойная модель LSTM. В этом случае входными данными является предложение исходного языка, а выходными данными - предложение целевого языка.

Первый слой LSTM относится к типу многие к одному, где входными данными является предложение, а выходными данными является только последний временной шаг уровня LSTM. Для этого нам нужно сделать как return_seq, так и return_state равным False, поскольку нам также не нужно, чтобы вывод скрытого состояния последнего временного шага LSTM передавался куда-либо.

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

Второй уровень LSTM имеет единицы, равные максимальной длине целевого предложения, которая также равна количеству выходных данных, реплицированных RepeatVector. Этот слой LSTM относится к типу «многие ко многим». Здесь нам нужно зафиксировать все временные шаги для пословного предсказания выходного предложения, для которых мы установили для return_sequence значение True. Нам не нужно никуда извлекать скрытое состояние, установив для return_state значение False.

# define NMT model
def define_model(src_vocab, tar_vocab, src_timesteps, tar_timesteps, n_units):
 model = Sequential()
 model.add(Embedding(src_vocab, n_units, input_length=src_timesteps, mask_zero=True))
 model.add(LSTM(n_units))
 model.add(RepeatVector(tar_timesteps))
 model.add(LSTM(n_units, return_sequences=True))
 model.add(TimeDistributed(Dense(tar_vocab, activation=’softmax’)))
 return model

* ПРИМЕЧАНИЕ. Существует заблуждение, что все модели нейронного машинного перевода являются вариантами seq2seq Encoder-Decoder, что неверно. мы можем представить себе любую модель нейронной сети, которая может переводить один язык на другой. При этом модель seq2seq чрезвычайно популярна для нейронного машинного перевода в той мере, в какой люди не хотят рассматривать другие варианты. Ниже мы увидим одну из таких моделей seq2seq.

Пример-2:

В приведенном ниже коде кодер и декодер (seq2seq) определены отдельно.

Кодировщик LSTM имеет return_state = True, а для return_sequence установлено значение False, что является параметром по умолчанию. В этом коде кодер должен передать выходы своего последнего скрытого состояния (ячейка и скрытое состояние) декодеру, выходы на каждом временном шаге не используются.

Декодер LSTM имеет return_state = True и return_sequence = True. Это так, потому что мы используем весь каждый временной шаг LSTM, чтобы предсказать следующее слово в выходном предложении, для которого нам нужно установить return_sequence в True. Скрытое состояние каждого временного шага также передается на вход скрытого состояния следующего временного шага, обрабатывая каждый временной шаг или единицу LSTM индивидуально. Это можно сделать, установив return_state в True. Это представлено на рис. 4 выше.

# Define an input sequence and process it.
encoder_inputs = Input(shape=(None, num_encoder_tokens))
encoder = LSTM(latent_dim, return_state=True)
encoder_outputs, state_h, state_c = encoder(encoder_inputs)
encoder_states = [state_h, state_c]
# Set up the decoder, using `encoder_states` as initial state.
decoder_inputs = Input(shape=(None, num_decoder_tokens))
decoder_lstm = LSTM(latent_dim, return_sequences=True, return_state=True)
decoder_outputs, _, _ = decoder_lstm(decoder_inputs,
 initial_state=encoder_states)
decoder_dense = Dense(num_decoder_tokens, activation=’softmax’)
decoder_outputs = decoder_dense(decoder_outputs)

Пример-3:

Здесь мы объясняем еще один вариант нейронного перевода с механизмом внимания.

В случае нейронного машинного перевода seq2seq без внимания, как объяснено в примере 2, return_sequence для кодировщика становится ложным. Потому что мы используем только последнее скрытое состояние LSTM для представления всего входного предложения в векторе, который будет передан декодеру в качестве входных данных для скрытого состояния if. В декодере уровень LSTM подобен языковой модели, поэтому нам нужно установить для возвращаемой последовательности значение true.

В этом случае, когда мы используем внимание, мы ожидаем взять все выходные данные временных шагов кодировщика, чтобы правильно сопоставить соответствующие входные слова для соответствующего прогнозируемого выходного слова. Для этого нам нужно установить для return_sequence значение True в кодировщике.

Следующий фрагмент кода предназначен для модели seq2seq с декодером и кодировщиком с вниманием. Здесь мы видим, что кодировщик LSTM имеет return_state и return_sequenc, для которых установлено значение True. Это необходимо для того, чтобы обеспечить внимание за счет выполнения всех временных шагов выходного сигнала кодировщика. Часть кода декодера очень похожа на то, что мы видели раньше.

encoder_inputs = Input(shape=(None, num_encoder_tokens))
encoder = LSTM(latent_dim, return_sequences=True, return_state=True)
encoder_outputs, state_h, state_c = encoder(encoder_inputs)
# We discard `encoder_outputs` and only keep the states.
encoder_states = [state_h, state_c]
# Set up the decoder, using `encoder_states` as initial state.
decoder_inputs = Input(shape=(None, num_decoder_tokens))
# We set up our decoder to return full output sequences,
# and to return internal states as well. We don’t use the 
# return states in the training model, but we will use them in inference.
decoder_lstm = LSTM(latent_dim, return_sequences=True, return_state=True)
decoder_outputs, _, _ = decoder_lstm(decoder_inputs,
 initial_state=encoder_states)
decoder_dense = Dense(num_decoder_tokens, activation=’softmax’)
decoder_outputs = decoder_dense(decoder_outputs)
# Define the model that will turn
# `encoder_input_data` & `decoder_input_data` into `decoder_target_data`
model = Model([encoder_inputs, decoder_inputs], decoder_outputs)

Языковая модель:

Пример-1:

В этом примере языковой модели мы берем окно из смежных слов в предложении и предсказываем следующее слово. Для одной такой операции мы берем окно слов в качестве входных и прогнозируем следующее слово в качестве выходных. Мы используем время «многие к одному» LSTM на основе модели. Установив для return_sequence значение False, мы получаем вывод только последнего временного шага. Это окно перемещается по одному слову за раз, используя то же количество слов для предсказания следующего слова. Это может сгенерировать предложение после обучения на корпусе текстовых данных.

Поскольку нам не нужно извлекать скрытое состояние, return_state также имеет значение False. Это представлено на рис.

# define model
model = Sequential()
model.add(Embedding(vocab_size, 10, input_length=max_length-1))
model.add(LSTM(50))
model.add(Dense(vocab_size, activation=’softmax’))
print(model.summary())

Пример 2: (глубокий LSTM)

Ниже приведен код классического примера языковой модели, в которой многоуровневый LSTM. используется. У нас есть слой LSTM с именем переменной «decoder_lstm» с return_sequence, установленным на True. Следует понимать, что для всех скрытых слоев LSTM return_sequence будет иметь значение True. Потому что они должны передавать вывод каждого временного шага на следующий уровень LSTM.

Слой LSTM в цикле for выполняет итерацию для создания дополнительных слоев LSTM. У последнего слоя LSTM также будет значение return_sequences, равное True, для передачи выходных данных каждого временного шага в качестве входных данных для следующего временного шага. Это представлено на рис. 6.

## Define model
input = Input(shape=(None, ))
decoder_lstm = LSTM(options.lstm_capacity, return_sequences=True)
h = decoder_lstm(embedded)
if options.extra is not None:
 for _ in range(options.extra):
 h = LSTM(options.lstm_capacity, return_sequences=True)(h)
out = TimeDistributed(fromhidden)(h)
fromhidden = Dense(numwords, activation=’linear’)

Заключение

Из приведенных выше примеров языковых моделей и переводов нейронных машин видно, что return_state и return_sequence использовались на основе выбора архитектуры.