Кодировщик трансформера
Кодировщик модели Transformer (transformer) [1] принимает на вход эмбеддингов элементов входной последовательности и выдаёт уточнённых эмбеддингов для каждого элемента с учётом его контекста (других элементов последовательности).
Кодировщик состоит из последовательных применений блоков кодировщика, каждый раз - со своими параметрами. В оригинальной статье [1] бралось .
Блок кодировщика
Схема одного блока кодировщика представлена ниже [2] для перевода входного предложения "Thinking machines":
Первый блок кодировщика принимает -мерные эмбеддинги каждого токена входной последовательности, прибавляет к ним эмбеддинги позиционного кодирования, после чего выдаёт такое же количество -мерных выходных эмбеддингов, но которые в результате некоторых преобразований уже учитывают контекст всей входной последовательности (всего переводимого предложения). В статье берётся .
Поскольку в трансформере предлагается наслаивать такие блоки раз, каждый из блоков будет всё больше уточнять эмбеддинги по контексту, пока последний блок не выдаст итоговые эмбеддинги, с которыми впоследствии будет работать декодировщик модели, состоящий из отдельных блоков декодировщика.
Считается, что сети достаточно передать информацию о позициях токенов в последовательности только один раз, поэтому позиционные эмбеддинги прибавляются к эмбеддингам входных токенов только для первого блока декодировщика. Последующие блоки работают только с выходными эмбеддингами предшествующих блоков в неизменном виде.
Каждый блок кодировщика имеет свои параметры, но функционально устроен единообразно:
-
каждый входной эмбеддинг преобразуется через блок самовнимания (self-attention) в выходной эмбеддинг;
-
входной и выходной эмбеддинги суммируются, как показано пунктиром на схеме;
-
суммарный эмбеддинг пропускается через послойную нормализацию (LayerNorm);
-
результирующий эмбеддинг преобразуется двухслойным персептроном (Feed Forward) в выходной;
-
затем опять входной и выходной эмбеддинги (в контексте предыдущего шага) суммируются, как показано пунктиром на схеме;
-
суммарный эмбеддинг снова пропускается через послойную нормализацию (LayerNorm).
Для каждого из блоков декодировщика этапы 1-6 применяются к каждому эмбеддингу входной последовательности независимо с одинаковыми весами. При этом веса внутри каждого блока свои. Рассмотрим подробнее каждый этап.
Сумма входного и выходного эмбеддингов
Суммирование входа с выходом, как и в модели ResNet, мотивировано тем, что:
-
градиент при обучении проще доходит от функции потерь к более ранним слоям, что упрощает настройку этих слоёв и ускоряет обучение всей сети;
-
в глубоких сетях целесообразно наслаивать слои, оставляя возможность модели оставить всё "как есть" (что обеспечивает тождественная связь), а при необходимости вносить лишь небольшие уточнения (с помощью нелинейного блока, веса которого инициализируются малыми числами).
Feed Forward
Feed Forward преобразование представляет собой двухслойный персептрон с активацией ReLU:
где
-
- входной эмбеддинг токена,
-
- е го нелинейно преобразованная версия той же размерности,
-
- обучаемые матрицы,
-
- обучаемые вектора смещений.
Этот блок позволяет модели настраивать сложные зависимости и строить более богатые признаковые представления.
Self-attention
Блок самовнимания (self-attention) призван обогатить эмбеддинг каждого токена информацией о других токенах последовательности. Поскольку каждый токен при этом использует информацию со всех других токенов, то схематично это можно представить в виде:
Рассмотрим детально, как работает блок самовнимания. Для большей ясности изложения будем писать сбоку внизу размерности векторов и матриц.
Пусть мы обрабатываем последовательность длины и каждый токен этой последовательности представляется -мерным эмбеддингом. Тогда входную последовательность можно представить в виде матрицы .
Используется механизм внимания (attention mechanism), в котором по эмбеддингу каждого токена генерируются:
-
-мерный запрос (query) ;
-
-мерный ключ (key) ;
-
-мерное значение (value) .
В статье [1] использовались , поскольку самовнимание впоследствии повторялось 8 раз.
Объединяя для каждого токена последовательности вектора их запросов, ключей и значений, получим:
-
матрицу запросов ;
-
матрицу ключей ;
-
матрицу значений .
Тогда выходной эмбеддинг вычисляется агрегацией значений для всех токенов последовательности:
Агрегация производится суммированием значений с весами, равными соответствиям соответствующих ключей запросу. Соответствия вычисляются методом scaled dot-product attention.
Матричная запись
Для повышения производительности вычисления производятся для всех токенов одновременно, используя матричную запись.
Генерируются матрицы:
– запросов: ;
– ключей: ;
– значений: .
Вычисления над полученными матрицами проиллюстрированы графически ниже [2]:
Результат самовнимания для всех токенов запишется как
Это можно графически можно изобразить как [2]:
Объединяя все операции, одна головка самовнимания (self-attention head) работает следующим образом: