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

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

Трансформаторы просты, модель кодировщика-декодера. Кодировщик принимает входные данные большой размерности, преобразует их и извлекает функции для создания скрытого представления. Затем он передается декодеру, который делает обратное. Кодирование осуществляется путем передачи данных через полносвязные (плотные) слои или сверточные слои. О слоях самовнимания с несколькими головами мы поговорим позже.

Давайте сначала обсудим левую часть трансформатора на рисунке 1. Это кодировщик. Кодировщик принимает входные данные, которые представлены текстом под красной кнопкой слева. Трансформаторы часто, но не исключительно, используются для задач обработки естественного языка (NLP). В компьютерном зрении эти Трансформаторы называются Трансформаторами Видения (ViT). Для нашего примера давайте просто предположим, что мы используем Transformer для задач NLP. Таким образом, входными данными будут предложения или текстовый корпус. Следовательно, вывод также будет текстовым. Одним из примеров может быть языковое моделирование, при котором вы хотите предсказать следующее слово в предложении.

Вход в наш кодировщик - это вложение слова. Чтобы создать это вложение, мы могли бы начать с модели Word2Vec. Поскольку семантическое сходство слов и понятий можно количественно оценить по тому, насколько они близки друг к другу в виде точек в векторных пространствах, наша модель Word2Vec представляет каждое отдельное слово с определенным списком чисел, называемым вектором, или когда мы складываем их все вместе в конечномерное пространство мы получаем векторное вложение. Таким образом, каждое слово имеет свой собственный вектор, встроенный в модель. На рисунке 2 ниже показано вложение патча 16x16. Во время обучения модели параметры в каждом из этих вложенных подпространств обучаются отдельно как часть определенного механизма самовнимания.

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

pos_embed (pos, 2i) = sin (pos / 10000 ^ (2i / dmodel))
pos_embed (pos, 2i + 1) = cos (pos / 10000 ^ (2i / dmodel))

Как видите, четные позиции используют функцию синуса (sin) и функцию косинуса нечетной позиции (cos) для создания вектора позиционного кодирования. Добавляя эти вычисления к исходным векторам слов, мы получаем позиционное встраивание, что показано на рисунке 3.

Полезно помнить, что функции sin и cos обладают линейным свойством. Вот как позиционное кодирование выглядит на практике:

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

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

Векторы запроса (q) и ключа (k) преобразуются с помощью скалярного произведения для формирования скоринговой матрицы, как показано на рисунке ниже. Если бы мы думали об изображениях, мы могли бы сказать, что это относительная связь патча с другими патчами во входном изображении. Оценки в матрице уменьшаются на квадратный корень из размерностей вектора K. Этот процесс гарантирует, что мы избежим взрывного градиента. Результирующая матрица называется масштабированной матрицей.

Масштабированная матрица передается через функцию Softmax для генерации весов вероятности, которая теперь называется матрицей оценки внимания (самовнимание представлено красной матрицей ниже). Поскольку он был запущен через Softmax, значения в матрице будут находиться в диапазоне от 0 до 1. Затем матрица оценки внимания умножается на векторы V, которые были пропущены через линейный слой в начале, что приводит к выходному вектору, который является затем обрабатывается линейным слоем.

Векторы Q, K и V генерируются для каждого элемента во входной последовательности путем передачи представления этого элемента (вектора) через обучаемый плотный слой. Важно отметить, что мы передаем не весь вектор, а часть вектора (по измерению вложения). Мы делаем это, чтобы включить несколько головок внимания!

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

Все еще не понимаете? Посмотрите на это фантастическое изображение:

Теперь мы используем остаточные соединения, уровень прямой связи и уровень нормализации. Вектор позиционного вложения, который мы создали на первом шаге, может распространяться глубже в модели. Мы нормализуем значение созданных представлений, затем слой активации линейного блока выпрямителя (ReLU), затем к линейному слою и, наконец, снова нормализуем. Это дает нам окончательный результат слоя кодировщика. Кодировщик можно складывать столько раз, сколько необходимо, чтобы придать смысл и богатое представление любого ввода. Базовая модель BERT, новое состояние модели NLP использует 12 кодировщиков, установленных друг на друга. BERT large использует 24 кодера, сложенных вместе!

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

По умолчанию механизм самовнимания может свободно смотреть в любую позицию во входной последовательности. Другими словами, весь вектор значений V полностью виден механизму внимания. Нам это не нужно, если, например, мы угадываем следующее слово в последовательности. Таким образом, мы «маскируем» вывод некоторых позиций. Мы делаем это, делая это число крайне отрицательным. Фактически эти позиции получат незначительно малый вес после операции Softmax. Поскольку оценка внимания этих будущих токенов будет равна 0, это говорит сети не сосредотачиваться на будущих словах, которые никогда не присутствовали в данный момент времени.

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

Один из приемов заключается в том, что декодер также может использоваться N раз, как кодировщик. Это улучшает вывод декодера.

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

Не все из них практичны для повседневного использования, если у вас нет ресурсов Microsoft или Google, но многие из них находятся в пределах досягаемости. В Delvify мы используем модель BERT в коммерческих целях и надеемся, что вы сможете найти идеальный трансформатор для себя.

Ссылки:
1. Внимание - это все, что вам нужно
2. Блог Джала Аммара
3. Блог Джагеша (Кувшинов)