"Начиная"

Внимание - это все, что вам нужно: открытие бумаги Transformer

Подробная реализация модели Transformer в Tensorflow

В этом посте мы опишем и демистифицируем соответствующие артефакты в статье Внимание - это все, что вам нужно »(Vaswani, Ashish & Shazeer, Noam & Parmar, Niki & Uszkoreit, Jakob & Jones, Llion & Gomez, Aidan И Кайзер, Лукаш и Полосухин, Илья. (2017)) [1]. Эта статья была большим достижением в использовании механизма внимания, являясь основным усовершенствованием модели под названием Transformer. Самые известные современные модели, возникающие в задачах НЛП, состоят из десятков трансформаторов или некоторых их вариантов, например, GPT-2 или BERT.

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

Зачем нужен Трансформер

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

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

Но этот подход по-прежнему имеет важное ограничение: каждая последовательность должна обрабатываться по одному элементу за раз. И кодировщик, и декодер должны дождаться завершения t-1 шагов для обработки шагаt-th. Таким образом, при работе с огромным корпусом это очень трудоемко и неэффективно с точки зрения вычислений.

Что такое Трансформер?

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

Бумага «Внимание - это все, что вам нужно» [1]

Модель Transformer извлекает признаки для каждого слова, используя механизм самовнимания, чтобы выяснить, насколько важны все другие слова в предложении w.r.t. к вышеупомянутому слову. И никакие повторяющиеся единицы не используются для получения этих функций, они просто взвешенные суммы и активации, поэтому они могут быть очень распараллеливаемыми и эффективными.

Но мы углубимся в его архитектуру (следующий рисунок), чтобы понять, что делают все эти части [1].

Мы можем видеть, что модель кодировщика находится слева, а декодер - справа. Оба содержат базовый блок «сети внимания и прямой связи», повторенный N раз. Но сначала нам нужно глубоко изучить основную концепцию: механизм самовнимания.

Самовнимание: основная операция

Самовнимание - это операция от последовательности к последовательности: последовательность векторов входит, а последовательность векторов выходит. Назовем входные векторы x1, x2,…, xt и соответствующие выходные векторы y1, y2,…, yt. Все векторы имеют размерность k. Чтобы создать выходной вектор yi, операция самовнимания просто берет средневзвешенное значение по всем входным векторам, самый простой вариант - это скалярное произведение.

Трансформеры с нуля Питера Блума [2]

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

Запрос, значение и ключ

Каждый входной вектор используется в механизме самовнимания тремя разными способами: запрос, ключ и значение. В каждой роли он сравнивается с другими векторами для получения собственного вывода yi (Запрос), для получения j-го вывода yj (Ключ) и для вычисления каждого вектора вывода после того, как веса были установлены (Значение).

Чтобы получить эти роли, нам нужны три весовые матрицы размеров k x k и вычислить три линейных преобразования для каждого xi:

Эти три матрицы обычно известны как K, Q и V, три обучаемых весовых уровня, которые применяются к одному и тому же закодированному входу . Следовательно, поскольку каждая из этих трех матриц поступает из одного и того же входа, мы можем применить механизм внимания входного вектора к самому себе, «самовнимание».

Масштабируемое внимание к скалярному произведению

Входные данные состоят из запросов и ключей измерения dk и значений измерения dv. Мы вычисляем скалярное произведение запроса со всеми ключами, делим каждый на квадратный корень из dk и применяем функцию softmax для получения весов значений.

Бумага «Внимание - это все, что вам нужно» [1]

Затем мы используем матрицы Q, K и V для вычисления оценок внимания. Баллы измеряют, насколько много внимания следует уделять другим местам или словам входной последовательности относительно слова в определенной позиции. То есть скалярное произведение вектора запроса на ключевой вектор соответствующего слова, которое мы оцениваем. Итак, для позиции 1 мы вычисляем скалярное произведение (.) q1 и k1, затем q1. k2, q1. k3 и так далее,…

Затем мы применяем «масштабированный» коэффициент, чтобы получить более стабильные градиенты. Функция softmax не может работать должным образом с большими значениями, что приводит к исчезновению градиентов и замедлению обучения [2]. После «softmaxing» мы умножаемся на матрицу значений, чтобы сохранить значения слов, на которых мы хотим сосредоточиться, и минимизируем или удаляем значения для нерелевантных слов (их значение в матрице V должно быть очень маленьким).

Формула для этих операций:

Многоголовое внимание

В предыдущем описании оценки внимания сосредоточены на всем предложении одновременно, это даст одинаковые результаты, даже если два предложения содержат одни и те же слова в разном порядке. Вместо этого мы хотели бы обратить внимание на разные части слов. Мы можем придать самовниманию большую способность различать, объединив несколько голов самовнимания, разделив векторы слов на фиксированное количество (h, количество головок) частей, а затем сам -внимание прилагается к соответствующим фрагментам, используя подматрицы Q, K и V. , [2] Питер Блум, «Трансформаторы с нуля ». Это дает h различных выходных матриц оценок.

Но следующий уровень (слой с прямой связью) ожидает только одну матрицу, вектор для каждого слова, поэтому «после вычисления скалярного произведения каждого заголовка мы объединяем выходные матрицы и умножаем их на дополнительную матрицу весов. Wo, [3]. Эта итоговая матрица собирает информацию от всех головок внимания.

Позиционное кодирование

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

С этой целью мы добавляем «позиционные кодировки» к входным вложениям в нижней части стеков кодировщика и декодера. Позиционные кодировки имеют тот же размер, что и вложения, поэтому их можно суммировать. Есть много вариантов позиционных кодировок.

Бумага «Внимание - это все, что вам нужно»

Итак, мы применяем функцию для сопоставления позиции в предложении с вещественным вектором. Сеть научится использовать эту информацию. Другой подход - использовать встраивание позиции, подобное встраиванию слов, кодируя каждую известную позицию вектором. «Это потребует предложения всех принятых позиций во время цикла обучения, но позиционное кодирование позволяет модели экстраполировать на длины последовательностей, превышающие те, которые встречаются во время обучения», [2].

В статье применяется синусоидальная функция:

Кодировщик

Теперь, когда были описаны все основные части модели, мы можем представить компоненты кодировщика [4]:

  • Позиционное кодирование: добавьте кодировку положения к встраиваемым входным данным (наши входные слова преобразуются в встраиваемые векторы). «Одна и та же весовая матрица совместно используется двумя уровнями внедрения (кодировщиком и декодером) и линейным преобразованием pre-softmax. В слоях внедрения мы умножаем эти веса на квадратный корень из измерения модели » [1].
  • N=6 идентичных слоя, содержащих два подуровня: механизм самовнимания с несколькими головками и полностью подключенную сеть прямого распространения ( два линейных преобразования с активацией ReLU). . Но он применяется ко входу по позициям, что означает, что одна и та же нейронная сеть применяется к каждому отдельному вектору «токена», принадлежащему последовательности предложений.

  • Вокруг каждого подуровня (внимание и сеть FC) существует остаточная связь, суммирующая вывод уровня с его вводом, за которым следует нормализация уровня.
  • Перед каждым остаточным соединением применяется регуляризация: «Мы применяем выпадение к выходным данным каждого подуровня, прежде чем он будет добавлен к входу подуровня и нормализован. Кроме того, мы применяем выпадение к суммам вложений и позиционного кодирования как в стеке кодировщика, так и в стеке декодера » [1] с коэффициентом выпадения 0,1.

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

Питер Блум, «Трансформеры с нуля» [2]

Сначала мы реализуем уровень кодировщика, каждый из шести блоков, содержащихся в кодировщике:

На следующем рисунке подробно показаны компоненты:

И код кодировщика:

Имейте в виду, что в декодер отправляется только вектор из последнего слоя (6-го).

Декодер

Декодер разделяет некоторые компоненты с кодировщиком, но они используются по-другому, чтобы учесть выходные данные кодировщика, [4]:

  • Позиционная кодировка: аналогична кодировке.
  • N=6 идентичных слоев, содержащих 3 три подслоя. Во-первых, замаскированное внимание с несколькими головами или замаскированное причинное внимание, чтобы не допустить перехода позиций к последующим позициям. «Эта маскировка в сочетании с тем фактом, что выходные вложения смещены на одну позицию, гарантирует, что прогнозы для позиции i могут зависеть только от известных выходных данных в позициях меньше, чем i» [1]. Реализована установка в −∞ значений, соответствующих запрещенным состояниям в слое softmax модулей внимания скалярных произведений. второй компонент или «внимание кодировщика-декодера» выполняет внимание с несколькими заголовками на выходе декодера, векторы ключа и значения поступают с выхода кодера, но запросы поступают из предыдущего уровня декодера. «Это позволяет каждой позиции в декодере обслуживать все позиции во входной последовательности» [1]. И, наконец, полностью подключенная сеть.
  • Остаточное соединение и нормализация уровня вокруг каждого подуровня, аналогично кодировщику.
  • И повторите то же остаточное выпадение, которое было выполнено в кодировщике.

Слой декодера:

В конце N составных декодеров, линейный уровень, полностью подключенная сеть, преобразует сложенные выходные данные в гораздо больший вектор, логиты. Затем слой softmax преобразует эти оценки (логиты) в вероятности (все положительные, все в сумме дают 1,0). Выбирается ячейка с наивысшей вероятностью, и слово, связанное с ней, создается в качестве выходных данных для этого временного шага , [3] Джей Аламмар, Иллюстрированный трансформатор .

Компонент декодера:

Соединяем все части: Трансформер

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

Стоит отметить, что мы создаем 3 маски, каждая из которых позволит нам:

  • Маска кодировщика: это маска заполнения для исключения маркеров контактных площадок из расчета внимания.
  • Маска декодера 1: эта маска представляет собой объединение маски заполнения и маски упреждающего просмотра, которая поможет причинному вниманию отбросить токены «в будущем». Мы берем максимальное значение между маской заполнения и прогнозируемой.
  • Маска декодера 2: это маска заполнения, которая применяется в слое внимания кодер-декодер.

Как видите, затем мы вызываем кодировщик, декодер и последний уровень linear-softmax, чтобы получить прогнозируемый результат нашей модели Transformer.

Обучение модели трансформатора

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

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

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

Мы используем оптимизатор Adam, описанный в документе, с beta1=0.9, beta2=0.98 и epsilon=10e-9. А затем мы создаем планировщик для изменения скорости обучения в процессе обучения в соответствии с:

Основная функция поезда

Функция поезда похожа на многие другие тренинги Tensorflow, обычный цикл обучения для задач от последовательности к последовательности:

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

И все, у нас есть все необходимые элементы для обучения нашей модели, нам просто нужно их создать и вызвать функцию train:

Делать предсказания

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

Вот шаги в этом процессе:

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

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

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

Код доступен в моем репозитории на github Transformer-NMT. Код частично взят из отличного курса команды SuperDataScience под названием Обработка современного естественного языка в Python на Udemy. Я очень рекомендую это.

Вот некоторые примеры переводов:

#Show some translations
sentence = "you should pay for it."
print("Input sentence: {}".format(sentence))
predicted_sentence = translate(sentence)
print("Output sentence: {}".format(predicted_sentence))
Input sentence: you should pay for it. 
Output sentence: Deberías pagar por ello.
#Show some translations
sentence = "we have no extra money."
print("Input sentence: {}".format(sentence))
predicted_sentence = translate(sentence)
print("Output sentence: {}".format(predicted_sentence))
Input sentence: we have no extra money. 
Output sentence: No tenemos dinero extra.
#Show some translations
sentence = "This is a problem to deal with."
print("Input sentence: {}".format(sentence))
predicted_sentence = translate(sentence)
print("Output sentence: {}".format(predicted_sentence))
Input sentence: This is a problem to deal with. 
Output sentence: Este problema es un problema con eso.

Надеюсь, вам понравится экспериментировать с моделью Transformer. В следующем посте мы займемся другими задачами НЛП.

использованная литература

[1] Васвани, Ашиш и Шазир, Ноам и Пармар, Ники и Ушкорейт, Якоб и Джонс, Ллион и Гомес, Эйдан и Кайзер, Лукаш и Полосухин, Илья, Внимание - это все, что вам нужно, 2017.

[2] Питер Блум, Сообщение в блоге« Трансформеры с нуля », 2019 г.

[3] Джей Аламмар, Проиллюстрированный трансформер, запись в блоге, 2018 г.

[4] Лилиан Вэн, Внимание? Внимание !! » запись в блоге, 2018.

[5] Рикардо Фаундес-Карраско, запись в блоге Внимание - это все, что вам нужно », 2017 г.

[6] Александр Раш, Аннотированный трансформатор, 2018, Гарвардская группа НЛП.