Охота на электроовец. Большая книга искусственного интеллекта - Марков Сергей Николаевич
Как часто бывает, некоторые идеи, положенные в основу трансформера, можно найти в работах [2162], [2163], [2164], написанных в начале 1990-х годов Юргеном Шмидхубером [2165]. Тип внимания, положенный в основу трансформера, называется особенно страшно — «многоголовое внутреннее внимание» [multi-headed self-attention]. Разумеется, по-русски так его никто не называет, вместо этого отечественные специалисты просто используют термин в его английском варианте.

Одна из проблем рекуррентных сетей заключается в том, что при их вычислении трудно добиться эффективного параллелизма. Действительно, для того чтобы вычислить следующее состояние сети, необходимо получить результат вычисления предыдущего состояния — сама природа рекуррентной сети последовательна, поэтому максимум, что можно сделать, это вычислять параллельно результаты для разных последовательностей либо выполнять параллельные вычисления в пределах одного состояния рекуррентной сети, однако оба этих подхода обычно не позволяют в полной мере использовать вычислительный потенциал тензорных процессоров. Нельзя ли вообще отказаться от рекуррентной сети в пользу нерекуррентной архитектуры, сохранив при этом механизм внимания, показавший свою эффективность? Оказывается, можно (именно на это ненавязчиво указывает нам заголовок статьи исследователей из Google).
Рассмотрим для примера предложение: «Люди одиноки, потому что вместо мостов они строят стены». Кто такие в данном случае «они»? Человек, прочитавший это предложение, без особого труда понимает, что в данном случае слово «они» относится к слову «люди». Можно сказать, что у нас в голове возникает представление о наличии определённого отношения (в данном случае — тождества) между словами «они» и «люди». Другое отношение связывает слова «они» и «строят», а также «люди» и «строят» — это отношения вида «A выполняет действие B». И так далее — слова в высказывании связаны определёнными отношениями. Идея multi-headed self-attention заключается в том, чтобы для разных типов отношений (за каждый из них отвечает отдельная «голова» сети внимания, так же как в свёрточной сети за каждый выявляемый слоем свёртки признак отвечает отдельный набор весов для свёрточного ядра) рассчитать матрицу выравниваний, то есть для каждой пары слов в предложении выяснить, в какой мере выражено для неё данное отношение.
На рисунке для всех слов предложения показаны отношения со словом «они» у разных «голов внимания» (обозначенных синим, зелёным и оранжевым цветом), насыщенность цвета показывает выраженность отношения. Пример условный, для упрощения показаны только три «головы», а не восемь.

Для вычисления матрицы выравниваний в трансформере используется довольно красивая матричная операция, имитирующая извлечение значения из таблицы по ключу. Так же как и в случае «обычного» внимания, каждый из векторов эмбеддингов слов (которые являются в нашем случае аналогами состояний кодировщика) при помощи трёх проекций превращается в три новых вектора одинаковой размерности: вектор запроса Q (от query), вектор ключа K (от key) и вектор значения V (от value). После этого создаётся матрица, элементы которой будут показывать «отношения» между различными словами предложения (эту матрицу называют «матрицей внимания» [attention matrix]). Для этого элемент матрицы с индексами i и j вычисляется как скалярное произведение вектора запроса Qi и вектора ключа Kj. Далее каждый элемент этой матрицы делится на квадратный корень из размерности вектора ключа K, а затем результат построчно пропускается через softmax-слой (тем самым производится нормализация коэффициентов, чтобы для каждой строки матрицы они в сумме давали единицу).
Далее для каждого слова предложения все векторы значений V умножаются на коэффициенты соответствующей этому слову строки из матрицы выравниваний и складываются, тем самым формируя некий итоговый вектор значений V. Таким образом, в нём будут хорошо учтены слова, имеющие определённые «отношения» с рассматриваемым словом, а иные слова, напротив, будут учтены слабо. Это и будет выходом такой подсети для данного слова предложения.
Схема данных операций приводится ниже, для сложения векторов значений V используются двухслойные полносвязные подсети, вычисление которых может осуществляться параллельно.

На выходе подсетей возникает матрица той же размерности, что и на входе сети внимания. Однако такой выход у нас имеется для каждой из «голов внимания». Поэтому полученные матрицы мы склеиваем (конкатенируем) друг с другом, а затем превращаем в матрицу исходной размерности при помощи слоя проекции. Именно поэтому модель и называют трансформером — она трансформирует полученные на вход данные, не меняя их размерности. Благодаря этому свойству описанные нами блоки кодировщиков можно укладывать подобно стопке блинов — выходы одного блока становятся входами следующего. Для борьбы с исчезающими градиентами используются, как и в свёрточных сетях, перепрыгивающие связи.
Блок декодера в трансформерах устроен аналогичным образом за той лишь существенной разницей, что он имеет два входа: на один подаётся выход кодировщика, на второй — выход сети внимания, применённой к уже известной части выходной последовательности (этот тип внимания называется «многоголовым вниманием с маской» [masked multi-head attention], маска используется для исключения неизвестных на данный момент частей выходной последовательности).
Ещё одним интересным трюком, использованным в оригинальном трансформере, является применение так называемого позиционного кодирования. Дело в том, что сам по себе трансформер, подобно свёрточным сетям, теряет информацию о порядке следования слов, поэтому эту информацию следует добавлять к векторам эмбеддинга. Можно было бы добавить, например, порядковый номер слова в качестве ещё одной компоненты в эти векторы, но на практике лучше работают более хитрые способы. В оригинальной версии трансформера вычисляют так называемую матрицу позиционного кодирования [positional encoding] размером W × n, где W — размерность вектора эмбеддинга слова, а n — максимальное количество слов в обрабатываемом моделью тексте. В нечётные строки этой матрицы записываются значения, равные
<i>sin ( j/10000<sup>i /n</sup>)</i>
<i>cos ( j/10000<sup>(i – 1)/ n</sup>)</i>