Кодировщик трансформера
Кодировщик модели трансформера (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), в котором по эмбеддингу каждого токена генерируется
-
-мерный запрос
-
-мерный ключ
-
-мерное значение
В статье [1] , поскольку самовнимание впоследствии повторялось 8 раз.
Объединяя для каждого токена последовательности вектора-строки их запросов, ключей и значений, получим
-
матрицу запросов ,
-
матрицу ключей ,
-
матрицу значений .
Тогда выходной эмбеддинг вычисляется агрегацией значений (values) для всех токенов последовательности:
Агрегация производится суммированием значений с весами, пропорциональным похожести ключа соответствующему запросу, которое вычисляется методом scaled dot-product attention.
Матричная запись
Для ускорения вычислений, они производятся для всех токенов одновременно, используя матричную запись:
Генерируются матрицы
– запросов (queries):
– ключей (keys):
– значений (values):
что графически показано ниже [2]:
Результат самовнимания для всех токенов запишется как
что графически можно изобразить как [2]:
Объединяя все операции, одна головка самовнимания (self-attention head) работает следующим образом: