В этом посте мы будем строить модель Seq2Seq на основе LSTM с архитектурой Encoder-Decoder для машинного перевода без механизма внимания.

Содержание:

  1. Введение
  2. Подготовка и обработка данных
  3. Долгосрочная краткосрочная память (LSTM) - Под капотом
  4. Архитектура модели кодировщика (Seq2Seq)
  5. Реализация кода кодировщика (Seq2Seq)
  6. Архитектура модели декодера (Seq2Seq)
  7. Реализация кода декодера (Seq2Seq)
  8. Интерфейс Seq2Seq (кодировщик + декодер)
  9. Реализация кода Seq2Seq (кодировщик + декодер)
  10. Обучение модели Seq2Seq
  11. Вывод модели Seq2Seq
  12. Ресурсы и ссылки

1. Введение

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

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

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

Таким образом, модель Sequence to Sequence (seq2seq) в этом посте использует архитектуру кодировщика-декодера, которая использует тип RNN, называемый LSTM (Long Short Term Memory), где нейронная сеть кодировщика кодирует последовательность входного языка в один вектор, также называется вектором контекста.

Считается, что этот C вектор онтекста содержит абстрактное представление последовательности входного языка.

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

Здесь я делаю нейронный машинный перевод с немецкого на английский. Но ту же концепцию можно распространить на другие проблемы, такие как распознавание именованных сущностей (NER), суммирование текста, даже другие языковые модели и т. Д.

2. Подготовка и предварительная обработка данных

Чтобы получить данные наилучшим образом, я использую библиотеки SpaCy (создание словаря), TorchText (предварительная обработка текста) и набор данных multi30k, который содержит последовательности перевода для английского, немецкого и французского языков.

Torch text - мощная библиотека для подготовки текстовых данных к различным задачам НЛП. В нем есть все инструменты для предварительной обработки текстовых данных.

Давайте посмотрим, какие процессы он может выполнять,

1. Разделение для обучения / допустимости / тестирования: разделите данные на определенный набор для обучения / допустимости / тестирования.

2. Загрузка файла: загрузите корпус текста в различных форматах (.txt, .json, .csv).

3. Токенизация: разбиение предложений на список слов.

4. Словарь: создайте список словаря из корпуса текстов.

5. Преобразование слов в целые числа: преобразование слов в целые числа для всего корпуса и наоборот.

6. Вектор слова: преобразование слова из более высокого измерения в более низкое (Встраивание слова).

7. Пакетирование. Создайте партии образца.

Итак, как только мы поймем, что можно сделать в текстовом модуле torch, давайте поговорим о том, как это можно реализовать в текстовом модуле torch. Здесь мы собираемся использовать 3 класса под текстом факела.

1. Поля:

  • Это класс под текстом факела, где мы указываем, как должна выполняться предварительная обработка нашего корпуса данных.

2. TabularDataset:

  • Используя этот класс, мы можем фактически определить набор данных столбцов, хранящихся в формате CSV, TSV или JSON, а также преобразовать их в целые числа.

3. BucketIterator:

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

Здесь наш исходный язык (SRC - ввод) - немецкий, а целевой язык (TRG - вывод) - английский. Мы также добавляем 2 дополнительных токена «начало последовательности» ‹sos› и «конец последовательности» ‹EOS› для эффективного обучения модели.

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

Создание пакетов - это сложный процесс, и, к счастью, мы можем использовать библиотеку итераторов TorchText.

Здесь мы используем BucketIterator для эффективного заполнения исходного и целевого предложений. Мы можем получить доступ к исходному (немецкому) пакету данных с помощью атрибута .src, а соответствующий (английский) пакет данных - с помощью атрибута .trg. Кроме того, мы можем видеть данные до их токенизации.

Я просто экспериментировал с размером партии 32, и образец партии показан ниже. Предложения токенизируются в список слов и индексируются в соответствии с словарным запасом. Маркер «pad» получает индекс 1.

Каждый столбец соответствует предложению, пронумерованному числами, и у нас есть 32 таких предложения в одном целевом пакете, а количество строк соответствует максимальной длине этого предложения. Короткие предложения дополняются единицами, чтобы компенсировать длину.

В приведенной ниже таблице (Idx.csv) содержатся числовые индексы пакета, которые позже вводятся во встраивание слов и преобразуются в плотное представление для обработки Seq2Seq.

Таблица ниже (Words.csv) содержит соответствующие слова, сопоставленные с числовыми индексами пакета.

3. Долговременная краткосрочная память (LSTM)

На приведенном выше рисунке показаны единицы, присутствующие в одной ячейке LSTM. Я добавлю несколько ссылок, чтобы узнать больше о LSTM в прошлом и почему он хорошо работает для длинных последовательностей.

Но, проще говоря, Vanilla RNN, Gated Recurrent Unit (GRU) не может улавливать долгосрочные зависимости из-за своей конструкции и сильно страдает от проблемы исчезающего градиента, которая делает скорость изменения весов и значений смещения незначительной. , что приводит к плохому обобщению.

Внутри ячейки LSTM у нас есть несколько мини-нейронных сетей с сигмоидной активацией и активацией TanH на последнем уровне и несколько векторных сумматоров, Concat, операций умножения.

Сигмоидальный NN → сжимает значения от 0 до 1. Скажите, что значение, близкое к 0, означает забыть, а значение, близкое к 1, означает запомнить.

Встраивание NN → Преобразует индексы входных слов в встраивание слов.

TanH NN → сжимает значения от -1 до 1. Помогает регулировать векторные значения от увеличения до максимума или сжатия до минимума.

Ворота:

Но в LSTM есть несколько специальных модулей, называемых воротами («Запомнить (добавить) ворота», «Забыть ворота», «Обновить ворота»), которые помогают преодолеть указанные выше проблемы.

  1. Забыть ворота → Имеет сигмовидную активацию и диапазон значений между (0–1), и он умножается на состояние ячейки, чтобы забыть некоторые элементы. («Вектор» * 0 = 0)
  2. Добавить ворота → Имеет активацию TanH и диапазон значений от
    (от -1 до +1), и он добавлен поверх состояние ячейки для запоминания некоторых элементов. («Вектор» * 1 = «Вектор»)
  3. Обновить скрытое → Обновляет скрытое состояние на основе состояния ячейки.

Скрытое состояние и состояние ячейки упоминаются здесь как вектор контекста, которые являются выходными данными ячейки LSTM. Входными данными являются числовые индексы предложения, введенные во встраиваемую NN.

4. Архитектура модели кодировщика (Seq2Seq)

Перед тем, как перейти к построению модели seq2seq, нам нужно создать кодировщик, декодер и создать интерфейс между ними в модели seq2seq.

Давайте передадим немецкую последовательность ввода «Ich Liebe Tief Lernen», которая переводится как «Я люблю глубокое обучение» в Английский.

Для более легкой заметки давайте объясним процесс, происходящий на изображении выше. Кодировщик модели Seq2Seq принимает по одному входу за раз. Наша входная последовательность немецких слов - «ich Liebe Tief Lernen».

Кроме того, мы добавляем токены начала последовательности «SOS» и конца предложения «EOS» в начало и конец входного предложения.

Поэтому в

  1. На временном шаге 0 отправляется маркер «SOS»,
  2. На временном шаге-1 отправляется токен «ich»,
  3. На временном шаге 2 отправляется токен «Liebe»,
  4. На временном шаге 3 отправляется жетон «Тиф»,
  5. На временном шаге 4 отправляется жетон «Lernen»,
  6. На временном шаге 4 отправляется токен «EOS».

И первый блок в архитектуре кодировщика - это слой встраивания слов [показан зеленым блоком], который преобразует входное индексированное слово в плотное векторное представление, называемое встраиванием слов (размеры - 100/200/300).

Затем наш вектор встраивания слов отправляется в ячейку LSTM, где он объединяется со скрытым состоянием (hs) и состоянием ячейки (cs) предыдущего временного шага, а блок кодера выводит новый hs и cs, который передается. в следующую ячейку LSTM. Понятно, что до сих пор hs и cs захватили некоторое векторное представление предложения.

На временном шаге 0 скрытое состояние и состояние ячейки либо полностью инициализируются нулями, либо случайными числами.

Затем после того, как мы отправили pass всю нашу входную последовательность немецких слов, наконец получается вектор контекста [показанный желтым блоком] (hs, cs), который является плотным представлением последовательность слов и может быть отправлена ​​в первый LSTM декодера (hs, cs) для соответствующего перевода на английский язык.

На приведенном выше рисунке мы используем двухуровневую архитектуру LSTM, где мы подключаем первый LSTM ко второму LSTM, а затем получаем 2 вектора контекста, сложенных сверху, в качестве финального выход. Это чисто экспериментально, вы можете манипулировать этим.

Мы обязательно должны разработать идентичные блоки кодера и декодера в модели seq2seq.

Приведенная выше визуализация применима к одному предложению из партии.

Допустим, у нас есть пакет размером 5 (экспериментальный), затем мы передаем кодировщику 5 предложений по одному слову за раз, что выглядит как на рисунке ниже.

5. Реализация кода кодировщика (Seq2Seq)

6. Архитектура модели декодера (Seq2Seq)

Декодер также выполняет один шаг за раз.

Вектор контекста из блока кодировщика предоставляется как скрытое состояние (hs) и состояние ячейки (cs) для первого блока LSTM декодера.

Токен начала предложения «SOS» передается внедряющей сети, затем передается в первую ячейку LSTM декодера и, наконец, проходит через линейный уровень. [Показано розовым цветом], который обеспечивает выходные вероятности предсказания английских токенов (4556 Вероятности) [4556 - как в общем словарном запасе английского языка], скрытое состояние (hs), состояние ячейки (cs ).

Выбирается выходное слово с наибольшей вероятностью из 4556 значений, скрытое состояние (hs) и состояние ячейки (cs) передаются в качестве входных данных в следующую ячейку LSTM, и этот процесс выполняется до тех пор, пока не достигнет значения конец предложения «EOS».

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

Обучайте коэффициенту силы:

В дополнение к другим блокам вы также увидите блок, показанный ниже, в декодере архитектуры Seq2Seq.

Во время обучения модели мы отправляем входные данные (последовательность на немецком языке) и цели (последовательность на английском языке). После того, как вектор контекста получен из кодировщика, мы отправляем им вектор и цель в декодер для перевода.

Но во время вывода модели цель генерируется из декодера на основе обобщения обучающих данных. Таким образом, выходные предсказанные слова отправляются в качестве следующего входного слова в декодер до тех пор, пока не будет получен токен ‹EOS›.

Таким образом, в самом обучении модели мы можем использовать коэффициент обучающей силы (tfr), где мы можем фактически контролировать поток входных слов в декодер.

  1. Мы можем отправлять фактические целевые слова в часть декодера во время обучения (показаны зеленым цветом).
  2. Мы также можем отправить предсказанное целевое слово в качестве входных данных для декодера (показано красным цветом).

Отправку любого слова (фактического целевого слова или прогнозируемого целевого слова) можно регулировать с вероятностью 50%, поэтому на любом временном шаге одно из них будет передано во время обучения.

Этот метод действует как регуляризация. Чтобы модель тренировалась эффективно и быстро в процессе.

Приведенная выше визуализация применима к одному предложению из партии. Допустим, у нас есть пакет размером 4 (экспериментальный), затем мы передаем 4 предложения за раз в кодировщик, который предоставляет 4 набора векторов контекста, и все они передаются в декодер, как показано на рисунке ниже.

7. Реализация кода декодера (Seq2Seq)

8. Интерфейс Seq2Seq (кодировщик + декодер)

Окончательная реализация seq2seq для одного входного предложения выглядит как на рисунке ниже.

  1. Предоставьте предложения как для ввода (немецкий), так и для вывода (на английском языке).
  2. Передайте входную последовательность кодировщику и извлеките векторы контекста.
  3. Передайте выходную последовательность декодеру, контекстные векторы из кодировщика, чтобы создать предсказанную выходную последовательность.

Приведенная выше визуализация применима к одному предложению из партии. Скажем, у нас есть пакет размером 4 (экспериментальный), затем мы передаем 4 предложения за раз в кодировщик, которые предоставляют 4 набора векторов контекста, и все они переданы в декодер, как показано на рисунке ниже.

9. Реализация кода Seq2Seq (кодировщик + декодер).

10. Обучение модели Seq2Seq

Прогресс обучения для примерного предложения:

Потеря тренировки:

11. Вывод модели Seq2Seq

Теперь давайте сравним нашу обученную модель с моделью SOTA Google Translate.

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

12. Ресурсы и ссылки

Надеюсь, мне удалось дать некоторое визуальное представление о том, как модель Seq2Seq обрабатывает данные, дайте мне знать ваши мысли в разделе комментариев.

Ознакомьтесь с Блокнотами, которые содержат полную реализацию кода, и не стесняйтесь ломать его.

Полная реализация кода доступна по адресу,

@ GitHub



@ Колаб



@ Kaggle



Для любопытных: визуализации в этой статье стали возможны с помощью Figma и Google Drawing.

Полные файлы визуализации, созданные на Figma (.fig) [LSTM, ENCODER + DECODER, SEQ2SEQ], доступны @ Github.



Ссылки: LSTM, WORD_EMBEDDING, DEEP_LEARNING_MODEL_DEPLOYMENT_ON_AWS

А пока увидимся в следующий раз.

Автор статьи:

БАЛАКРИШНАКУМАР V