Чтобы закодировать слово с учётом его соседей, мы используем идею query, key, value. Эмбединг слова умножается на матрицу Q и превращается в вектор query, эмбединги всех слов превращаются умножением на матрицу K в вектор key, и умножением на матрицу V в вектор value. Далее мы перемножаем query данного слова на каждый key всех слов в предложении, и с этим весом (query*key) усредняем value каждого слова в предложении - это и получится представлением исходного слова с учётом контекста окружающих слов. Это Attention. В реальности, чтобы учитывать позицию, на вход подаётся не просто эмбединг слова, но ещё и добавляется кодирование последовательности. У Attention'а есть ограничение на максимальную длину фразы, и это будет размерность всех сумм векторов, которые идут дальше в сети.
Матрицу Q, K, V - обучаются. Мы можем параллельно обучать набор матриц, и получать не одно представление слова, а набор векторов -- это будет Multi Head Attention
Encoder представляет собой Multi Head Attention блок, выход которого идёт на полносвязанную нейронную сеть, с проложенными слоями skip слоями: Add&Norm и повторяющаяся несколько раз (может быть в 5-6 повторов).
Decoder получает на вход сгенерированную им же самим фразу - в один multihead attention, который выдаёт вектор q, идущий на вход второго multihead attention, которому на вход в качестве k и v подаются выходы из Encoder'а. Выход второго Multi Head Attention'а идёт в многосвязаную сеть опять же с Add&Norm слоями и на выходе ставим линейный слой и softmax, который выдаёт нам токен.