Содержание:

1. Введение

Архитектура с двумя кодировщиками

Архитектура 3-декодера

4-Стадия вывода

5-Проблема

6-Что такое внимание?

7-Внедрение различных типов механизмов внимания

8-Недостаток внимания

9-Ссылки

1. Введение:

Последовательное обучение (Seq2Seq) - это все о моделях, которые принимают последовательность на входе и также выводят последовательность. Есть много примеров и применений этого, но сегодня я сосредоточусь на одном конкретном приложении, которое представляет собой машинный перевод. Например, с английского на хинди.

Есть много подходов, которым вы можете следовать для решения этой конкретной задачи, но самой современной техникой является подход кодировщика-декодера (подробнее об этом позже).

Технически Encoder - это блок RNN, который принимает последовательность в качестве входных данных и кодирует ее как вектор состояния, который затем передается в декодер с некоторым входом для прогнозирования желаемого выхода.

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

На заметку: обычно это RNN-единица LSTM или GRU.

Итак, наша окончательная архитектура выглядит так.

Вместо того, чтобы здесь все описывать, давайте сделаем это шаг за шагом:

2. Архитектура кодировщика:

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

Просто для контекста, модуль LSTM принимает три входа и возвращает три выхода.

Здесь X, h0 и c0 - входы, Y, ht и ct - выходы. Этот рисунок выше представляет собой свернутую версию модуля LSTM. Обычно он принимает одно слово / символ за раз и со временем разворачивается. Рисунок ниже проясняет это.

Первый вход - это последовательность, которую мы хотим перевести, а два других входа - это два вектора, состояние ячейки и скрытое состояние.

Например, возьмем эту последовательность. «Это хороший телефон». Эта последовательность содержит 5 слов, поэтому наш кодировщик lstm будет обрабатывать каждое слово за один временной интервал.

На приведенной выше диаграмме x1 - это входное слово, которое является 'This', h0, c0 - входные векторы состояния, которые инициализируются случайным образом в начале. Оно выводит три вектора y1 (выходной вектор), h1 и c1 (векторы состояния). .

Интуитивно понятно, что h1 и c1 здесь содержат информацию слова This, которое мы ввели на временном шаге t0. Теперь LSTM на временном шаге t1 будет принимать h1 и c1 в качестве входных данных со следующим словом в последовательности, которое является ‘is’. Вектор h3, c3 содержит информацию до слова 3, которое является ‘a’. Итак, до последнего временного шага 5 мы получим h5 и c5, которые содержат информацию обо всей входной последовательности.

Итак, теперь наша входная последовательность «Это хороший телефон» преобразуется в векторы h5 и c5. Мы отбрасываем выходные векторы (от y1 до y5), потому что они нам здесь не нужны. Нам нужны только векторы состояния вывода, поскольку они будут содержать информацию о заданной входной последовательности.

Теперь мы инициализируем наш декодер этими конечными векторами состояния кодировщика, которые являются h5 и c5, а не случайным образом, как мы это делали с кодировщиком LSTM. Логически это также имеет смысл, потому что мы хотим, чтобы наш декодер не просто запускался случайным образом, но чтобы иметь представление о входной последовательности.

3. Архитектура декодера:

Декодер LSTM также будет иметь ту же архитектуру, что и кодировщик, но с другими входами и выходами. Теперь есть две вещи: фаза обучения и фаза вывода. Мы коснемся фазы вывода позже. Сначала завершите тренировочную фазу.

У нас есть векторы, закодированные нашим кодировщиком LSTM. H0 и c0 декодера инициализируются не случайными, а значениями h5 и c5, которые мы получили от кодировщика.

Также, чтобы все работало, мы добавляем символ _START_ в начало и символ _END_ в конце целевой последовательности. Теперь последняя последовательность выглядит как ‘_Start_ यह एक अच्छा फोन है _END_’

Здесь X1 = _Start_ и Y1 = यह с h0 = h5 энкодера и c0 = c5 экодера. Это возвращает векторы состояния h1, c1, которые вводятся в декодер на следующем временном шаге, и выходной сигнал Y1, который вводится как основная истина в декодер. Это продолжается до тех пор, пока модель не встретит символ _END_. На последнем временном шаге мы игнорируем векторы конечного состояния декодера (h6, c6), потому что это бесполезно для нас, нам нужен только вывод Y.

Эта техника также называется Принуждение учителя. Подробнее об этом здесь.

Вся архитектура обучения (кодировщик + декодер) может быть представлена ​​на диаграмме ниже:

Учитывая окончательную архитектуру, теперь мы можем прогнозировать выходные данные для каждого временного шага, а затем ошибки распространяются обратно во времени, чтобы обновить параметры всей сети и затем вычислить наши потери при обучении.

4. Стадия вывода:

Задача применения обученной модели для создания перевода называется логическим выводом или, чаще всего, декодированием последовательности в машинном переводе.

У нас есть обученная модель, теперь мы можем генерировать прогнозы на основе заданной входной последовательности. Этот шаг в основном известен как вывод. Вы можете назвать это этапом тестирования, в то время как вышеуказанные шаги были этапом обучения. На этом этапе у нас есть только изученные веса и входная последовательность, которые нужно декодировать.

Модель, определенная для обучения, получила веса для этой операции, но структура модели не предназначена для рекурсивного вызова для генерации одного слова за раз. Для этого нам нужно разработать новые модели для тестирования нашей обученной модели. Есть много способов выполнить декодирование.

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

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

Модель Decoder более сложная. Для этого требуются три входа, скрытые состояния и состояния ячеек от кодировщика в качестве начального состояния вновь определенной модели кодировщика и пока что закодированные выходные данные трансляции. Он будет вызываться для каждого слова, т.е. мы должны сделать это внутри цикла, и цикл завершится, как только он увидит символ _END_.

Мы будем использовать эту модель вывода, чтобы окончательно перевести последовательность с одного языка на другой.

5. Проблема:

«Внимание» - одна из последних тенденций в сообществе глубокого обучения. Илья Суцкевер, человек, стоящий за вышеупомянутой архитектурой seq2seq для машинного перевода, упомянул, что «механизмы внимания» - одно из самых захватывающих достижений в вышеупомянутом подходе кодер-декодер, и что они здесь, чтобы остаться. Но в чем проблема такого подхода и что решает внимание?

Чтобы понять, что для нас может сделать внимание, давайте рассмотрим ту же проблему с машинным переводом, что и выше. Мы хотели перевести предложение «Это хороший телефон» на «यह एक अच्छा फोन है». Помните, что мы использовали кодировщик LSTM для сопоставления английского предложения с векторами конечного состояния. Посмотрим на это визуально:

Мы видим, что векторы h5, c5 должны кодировать все, что нам нужно знать об исходном предложении. Он должен полностью отражать его смысл.

Но есть загвоздка.

По сути, он улавливает смысл всего предложения, но это когда предложение не длинное. Например, предложение, которое мы взяли, состоит всего из 5 слов, и нормальный кодировщик отнесется к нему должным образом, но когда предложение состоит из статей длиной 50 или 100 слов, этот единственный конечный вектор не сможет отобразить полностью всю последовательность. Посмотрите на это с другой стороны: если предложение состоит из 100 слов, первое слово исходного предложения, вероятно, сильно коррелирует с первым словом целевого предложения. Но это означает, что декодер должен учитывать информацию, полученную 100 шагов назад, и эту информацию нужно каким-то образом закодировать в векторе. У RNN есть старая проблема долгосрочных зависимостей. Теоретически такие архитектуры, как LSTM, должны уметь справляться с этим, но на практике долгосрочные зависимости все еще проблематичны. Есть несколько приемов, которые могут улучшить ситуацию, но это не принципиальные решения.

И вот здесь-то и появляется "Внимание".

6. Что такое внимание:

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

Например, на рис. 8 мы будем использовать все h и c вместо использования только h5, c5. Итак, теперь, если наш декодер хочет декодировать «This» в «», он может напрямую обращаться к первым векторам состояния h1, c1. Эта идея известна как уделение большего внимания текущему слову, отсюда и название «Внимание». Интуитивно вы можете подумать, что декодер обратится к первому английскому слову при создании первого слова на хинди и так далее.

Реализация пользовательского слоя Keras:

Для реализации собственного механизма внимания нам нужно написать кастомный слой Keras.

Чтобы реализовать это в Keras, нам нужно написать всего три простых метода.

  • build(input_shape): здесь вы определите свой вес. Этот метод должен установить self.built = True в конце, что можно сделать, вызвав super([Layer], self).build().
  • call(x): Здесь живет логика слоя.
  • compute_output_shape(input_shape): в случае, если ваш слой изменяет форму входных данных, вы должны указать здесь логику преобразования формы.

7. Внедрение различных типов механизмов внимания:

Приведенное выше объяснение представляет собой представление верхнего уровня. Нам нужно глубоко копнуть, чтобы полностью понять это. С 2015 года внимание стало довольно популярным понятием и инструментом для решения проблем НЛП. В последние годы произошло множество улучшений и модификаций простых механизмов внимания, что привело к созданию различных типов моделей. Хотя основные принципы внимания одинаковы для всех типов, их различия заключаются в основном в их архитектуре и вычислениях. Некоторые из популярных я расскажу ниже с реализацией в Keras. Мы можем использовать модуль GRU вместо LSTM просто для простоты, поскольку GRU состоит из одного скрытого состояния по сравнению с LSTM, которое поддерживает два скрытых состояния.

7.1- Внимание, предложенное Bahdanau:

Прямо сейчас у нас есть все закодированные векторы состояния от (h1) до (h5). Слой внимания примет эти закодированные векторы и внутреннее состояние декодера на предыдущем временном шаге в качестве входных данных. Для предсказания самого первого слова декодер не имеет текущего внутреннего состояния. По этой причине мы будем рассматривать последнее состояние кодировщика (т.е. h5) как предыдущее состояние декодера. С помощью этих векторов будет рассчитана оценка выравнивания, которая затем будет использоваться для расчета весов внимания. Это подробно обсуждается ниже:

Декодер обучен предсказывать выходные данные y на временном шаге t с учетом вектора контекста c и ранее предсказанных выходных данных.

Здесь y - ранее предсказанные выходные данные, а c - вектор контекста. Другими словами, можно сказать, что декодер пытается найти указанную выше условную вероятность. Часть условной вероятности можно смоделировать как:

где g - нелинейная, потенциально многослойная функция, которая выводит вероятность «yt», а «st» - скрытое состояние декодера GRU / LSTM, которое рассчитывается как:

Здесь вы можете видеть, что вероятность обусловлена ​​отдельным вектором c, который является вектором контекста для каждого целевого слова. Вектор контекста ci зависит от выходной последовательности кодировщика (h1, h2,… hTx), в которую кодировщик отображает входное предложение.

Вектор контекста ci затем вычисляется как взвешенная сумма этих векторов состояния.

Если мы развернем приведенную выше формулу для нашего примера из пяти слов, мы получим:

context_vector = ( α 1 * h1 + α 2 * h2 + α 3 * h3 + α 4 * h4 + α 5 * h5)

- это модель выравнивания, которая оценивает, насколько хорошо совпадают входные данные в позиции j и выходные данные в позиции i. Оценка основана на скрытом состоянии si-1 декодера GRU / LSTM и j-м выходе hj входного предложения. Здесь «а» - простая нейронная сеть с прямой связью, которая обучается совместно со всеми другими компонентами предлагаемой системы. Эти модели выравнивания eij также называются энергетическими баллами.

Для вычисления energy_score / allignment_score в бумаге вводятся три весовые матрицы W_combined, W_decoder, W_encoder. Приведенная ниже формула проясняет это.

Давайте определим эти веса в функции построения класса AttentionLayer.

У нас есть определенные веса, необходимые для вычисления alignment_score. Теперь давайте определим функцию вызова класса, в которой будут находиться фактические вычисления и логика кода.

Слой внимания, наконец, вернет allignment_score и веса внимания. Затем веса будут использоваться для вычисления окончательного вектора контекста.

context_vector = attention_wts * enc_output_seq

Наш последний класс уровня внимания определен ниже:

2 - Внимание, предложенное Луонгом:

Этот механизм был введен Тханг Луонгом в 2015 году после механизма Бахданау. Он был построен на основе предыдущего механизма и имеет некоторые отличия.

  1. Способ вычисления оценки выравнивания.
  2. Позиция, в которой механизм внимания вводится в декодер.

В Bahdnau Attention слой внимания принимает закодированные входные векторы и скрытый вектор декодера на предыдущем временном шаге в качестве входных данных. Затем он вычисляет вектор контекста, используя это. Использование этого вектора контекста прогнозируется. Но в Luong Attention вектор контекста используется только после того, как RNN / LSTM произвел вывод для этого временного шага. На уровне декодера предыдущее скрытое состояние декодера и выходные данные декодера проходят через RNN декодера для создания нового скрытого состояния для этого временного шага. Используя новое скрытое состояние декодера и скрытые состояния кодировщика, вычисляются оценки выравнивания.

Всего существует три способа расчета оценок выравнивания по сравнению с методом Bahdanau, который имеет только один тип. Вот эти типы:

Точка:

В этой функции нам нужно только скрытое состояние декодера и скрытое состояние кодировщика для вычисления оценки выравнивания.

Общий:

Это похоже на точечную функцию, за исключением того, что у нее есть весовая матрица после точечной функции.

Объединить:

Эта функция вычисляет балл следующим образом.

Здесь H_decoder - это новое скрытое состояние, которое генерируется путем передачи предыдущего скрытого состояния и вывода декодера.

Ниже представлена ​​реализация Luong Attention:

8. Недостаток внимания:

Как указано в предыдущем абзаце, он вычисляет context_vector для каждого слова, за которое приходится платить. Чем длиннее последовательности, тем больше потребуется времени на обучение. Также, если вы видите, что человеческое внимание - это то, что должно экономить вычислительные ресурсы. Сосредоточившись на одном, мы можем пренебречь многими другими вещами. Но это не совсем то, что мы делаем в приведенной выше модели. По сути, мы подробно изучаем все, прежде чем решить, на чем сосредоточить внимание. Интуитивно это эквивалентно выводу переведенного слова и последующему просмотру всей внутренней памяти текста, чтобы решить, какое слово создать следующим. Это кажется пустой тратой, и это совсем не то, что делают люди. На самом деле, это больше похоже на доступ к памяти, а не на внимание, что, на мой взгляд, неправильно. Тем не менее, это не помешало механизмам внимания стать довольно популярными и хорошо справляться со многими задачами.

9. Ссылки:

1- https://machinelearningmaster.com/define-encoder-decoder-sequence-sequence-model-neural-machine-translation-keras/

2- https://github.com/tensorflow/nmt

3- https://www.tensorflow.org/tutorials/text/nmt_with_attention

4- https://machinelearningmaster.com/encoder-decoder-recurrent-neural-network-models-neural-machine-translation/