[Перевод] Объясняем простым языком, что такое трансформеры

e71e8c4c3d0ff4ca43af5139e64a22cf.jpg

Облако предлагает много возможностей для развития ИИ. С помощью облачных вычислений проще масштабировать ML-модели, повышать точность обучения и предоставлять данные удаленно пользователям. Однако масштабное развертывание ML-моделей требует понимания архитектуры нейронных сетей. 

Один из важнейших инструментов машинного обучения — трансформеры. Популярность трансформеров взлетела до небес в связи с появлением больших языковых моделей вроде ChatGPT, GPT-4 и LLama. Эти модели созданы на основе трансформерной архитектуры и демонстрируют отличную производительность в понимании и синтезе естественных языков. 

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

Что такое трансформер?

Это такой вид нейросетевой архитектуры, который хорошо подходит для обработки последовательностей данных. Пожалуй, самый популярный пример таких данных это предложение, которое можно считать упорядоченным набором слов. 

Трансформеры создают цифровое представление каждого элемента последовательности, инкапсулируют важную информацию о нём и окружающем его контексте. Получившиеся представления затем можно передать в другие нейросети, которые воспользуются этой информацией для решения разных задач, в том числе для синтеза и классификации. Создавая такие информативные представления, трансформеры помогают последующим нейросетям лучше понять скрытые паттерны и взаимосвязи во входных данных. И поэтому они лучше синтезируют последовательные и взаимосвязанные результаты.

Главное преимущество трансформеров заключается в их способности обрабатывать длительные зависимости в последовательностях. Кроме того, они очень производительны, могут обрабатывать последовательности параллельно. Это особенно полезно в задачах вроде машинного перевода, анализа настроений и синтеза текста.

Что поступает в трансформер?

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

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

4d934a8df750e4115381a49dd5e9e181.png

Но это примитивный способ кодирования текста, потому что слова вроде cat и cats будут кодироваться разными токенами, хотя это единственное и множественное число одного животного. Поэтому придумали разные способы токенизации (вроде кодирования парами байтов), при которых слова перед индексированием разбиваются на фрагменты. Кроме того, часто бывает полезно добавлять специальные токены для обозначения характеристик вроде начала и конца предложения, чтобы дать модели больше контекста.

Рассмотрим токенизацию на примере такого предложения:

«Hello there, isn«t the weather nice today in Drosval?»

Drosval — это название сгенерировано GPT-4 по промпту: «Можешь создать название выдуманного места, которое звучит так, словно оно из мира Drenai Дэвида Геммеля?» (Can you create a fictional place name that sounds like it could belong to David Gemmell«s Drenai universe? ), и выбран вариант, которого нет в словарях каких-либо обученных моделей.

С помощью токенизатора bert-base-uncased из библиотеки transformers library превратим предложение в последовательность токенов:

85b261c00dac09bbe8f7292438b165c1.png

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

818fdb7acf1697d07acb9f67a0a93a7a.png

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

Хотя в качестве примера мы использовали предложение, трансформеры обрабатывают не только текст. Эта архитектура показала хорошие результаты и в визуальных задачах. Прежде чем передать изображение в модель, авторы ViT превратили её в последовательность: разрезали картинку на не пересекающиеся фрагменты размером 16 на 16 пикселей и конкатенировали их в длинный вектор. Если бы мы использовали в рекомендательной системе трансформер, то на вход модели можно было бы подать идентификаторы последних N объектов, которые посмотрел пользователь. Если для нашей тематической области можно создать осмысленное представление входных токенов, то их можно скормить трансформеру.

Эмбеддинг токенов

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

В зависимости от задачи, при превращении токенов в эмбеддинги нам может потребоваться сохранить порядок токенов. Это особенно важно в обработке естественных языков, иначе мы придём к методу «мешка слов». Чтобы этого не допустить, мы применяем к эмбеддингам позиционное кодирование. Есть разные способы это сделать, но основная идея в том, что у нас есть ещё один набор эмбеддингов, представляющих положение каждого токена во входной последовательности. Этот второй набор комбинируется с эмбеддингами токенов.

3157a1964b640b2df8bc69190951e1ac.png

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

It«s dark, who turned off the light?

Wow, this parcel is really light!

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

По сути, что такое внимание?

Пожалуй, самый важный механизм в трансформенной архитектуре — это внимание. Он позволяет нейросети понять, какая часть входной последовательности наиболее релевантна задаче. Механизм внимания определяет для каждого токена последовательности, какие другие токены необходимы для его понимания в данном контексте. Прежде чем мы перейдем тому, как это реализовано в трансформере, давайте сначала разберемся, чего пытается добиться механизм внимания.

Этот механизм можно представить как метод, который заменяет каждый эмбеддинг токена на эмбеддинг, содержащий информацию о соседних токенах, вместо использования одинакового эмбеддинга для каждого токена вне зависимости от контекста. Если бы мы знали, какие токены релевантны текущему, то узнать его контекст можно с помощью средневзвешенного — или, в общем случае, линейной комбинации — этих эмбеддингов.

e45a146d14805fdc5c7b888e951416b8.png

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

5609636dbb10bca8a596e955421d372f.png

Здесь наши веса — это матрица тождественностей. А применив механизм внимания, мы хотим узнать матрицу весов, которая позволит нам подобным образом выразить эмбеддинг для слова light:

6b7c996d09ad6a44c307a999eefecf1b.png

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

Мы поверхностно рассмотрели, что пытается добиться механизм внимания. Давайте теперь разберемся, как именно это реализовано.

Как вычисляется внимание?

Есть разные варианты этого механизма, и главное различие между ними заключается в способе вычисления весов для линейной комбинации. Здесь мы рассмотрим scaled dot-product attention (механизм на основе скалярного произведения), поскольку сегодня это самый популярный способ. Будем считать, что все наши эмбеддинги позиционно закодированы.

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

9905243423653b5b5027da2b1c7a5af7.png

Поскольку для каждого токена нужно вычислить его взаимосвязь с каждым другим токеном последовательности, мы можем обобщить задачу до матричного умножения и получим матрицу весов, которую часто называют attention scores (оценка внимания). Чтобы убедиться, что сумма весов равна единице, мы также применим многопеременную логистическую функцию (МЛФ). Но поскольку матричное умножение может давать произвольные большие числа, МЛФ будет возвращать очень маленькие градиенты для больших оценок внимания. А это может привести к проблеме исчезающего градиента во время обучения. Для борьбы с этим умножим оценки внимания на поправочный коэффициент перед применением МЛФ.

34f40ac50d3de1f69d51c2262d817953.png

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

Упрощенное вычисление внимания. Предполагается, что эмбеддинги позиционно закодированы.

Упрощенное вычисление внимания. Предполагается, что эмбеддинги позиционно закодированы.

Хотя модель может выучить достаточно сложные эмбеддинги для синтеза оценки внимания и контекстуальных эмбеддингов, мы пытаемся уместить в них слишком много информации. Поэтому для облегчения обучения модели вместо прямого использования матрицы эмбеддингов давайте передавать её через три независимых линейных слоя (матричных умножений). Это позволит модели «сосредоточиться» на разных частях эмбеддингов:

Масштабированное вычисление внимания (self-attention) на основе скалярного произведения. Предполагается, что эмбеддинги позиционно закодированы.

Масштабированное вычисление внимания (self-attention) на основе скалярного произведения. Предполагается, что эмбеддинги позиционно закодированы.

На линейные проекции помечены как Q, K и V. В исходной научной работе они названы Query, Key и Value, вероятно, авторы вдохновлялись процессом извлечения информации. Лично мне такая аналогия никогда не помогала, так что не буду на этом останавливаться. Я сохранил терминологию ради согласованности с литературными источниками, и чтобы подчеркнуть раздельность этих линейных слоев.

Мы разобрались в работе процесса, и теперь вычисление внимания можно представить как блок с тремя входами, которые подаются в Q, K и V.

6ec81ee1bc04b51f31d842fd57c73b40.png

Когда мы подаем одну матрицу в Q, K и V, это называется self-attention — выявление закономерностей только между входными данными.

Что такое multi-head attention?

На практике мы часто параллельно запускаем несколько блоков self-attention, чтобы трансформер одновременно обрабатывал разные части входной последовательности — это называют multi-head attention. Идея проста: выходы нескольких независимых блоков self-attention конкатенируются и передаются через линейный слой. Он позволяет модели комбинировать контекстуальную информацию из каждого блока внимания. 

На практике скрытый размер измерения в каждом блоке self-attention обычно выбирается как размер исходного эмбеддинга, делённый на количество блоков внимания, чтобы сохранить структуру матрицы эмбеддингов. 

602280884893899cf60e6c8c70baabed.png

Что ещё входит в состав трансформера?

Хотя научная работа, в которой впервые был описан трансформер, печально известна как »Вам нужно лишь внимание» (Attention is all you need), это вводит в заблуждение, потому что в трансформере есть много других компонентов:

  • Нейросеть с прямой связью (Feedforward Neural Network, FFN): двухслойная нейросеть, которая применяется независимо к каждому эмбеддингу токена в пакете и последовательности. Её задача — внести в трансформер дополнительные изучаемые параметры, позволяющие убедиться, что контекстуальные эмбеддинги разделены и распределены. В исходной научной работе использована функция активации GeLU, но компоненты FFN могут меняться в зависимости от архитектуры.

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

  • Связи с пропускам (Skip connections): как и в архитектуре ResNet, для борьбы с проблемой исчезающего градиента и повышения стабильности обучения используются остаточные подключения.

Хотя архитектура трансформеров мало изменилась с момента первой публикации, размещение блоков нормализации слоев может меняться в зависимости от версии архитектуры. Вот так выглядит первоначальная версия, которая известна как post-layer norm:

c943d4ed547d80d6976e02ae72e9e961.png

Сегодня чаще всего блоки нормализации размещаются до self-attention и FFN, внутри связи с пропусками — это называется pre-layer norm:

e899d7eb1a8ba6c278af047b103e1f7b.png

Какие бывают трансформеры?

Существует много разных трансформерных архитектур, и большинство можно разделить на три типа.

Энкодеры

Модели-энкодеры синтезируют контекстуальные эмбеддинги, которые можно использовать в последующих задачах вроде классификации или распознавания именованных сущностей, поскольку механизм внимания может обрабатывать всю входящую последовательность. Именно этот тип архитектуры мы рассмотрели в этой статье. Самое популярное семейство чистых трансформеров-энкодеров — это BERT и его разновидности.

Передав данные через один или несколько блоков-трансформеров, мы получаем сложную матрицу контекстуализированных эмбеддингов, которая содержит по эмбеддингу на каждый токен последовательности. Но чтобы использовать эти данные для последующих задач вроде классификации нужно сделать одно предсказание. Обычно берут первый токен и передают через классификатор, в котором есть слои Dropout и Linear. Результат работы этих слоев можно пропустить через МЛФ для превращения в вероятности классов. Например, так:

60c7a4eaf4e6dab4ef3cede3864f4b78.png

Декодеры

Этот тип архитектур почти идентичен предыдущему, главное отличие в том, что декодеры используют маски̒рованный (или причинный) слой self-attention, поэтому механизм внимания может принимать только текущий и предыдущие элементы входной последовательности. То есть контекстуальные эмбеддинги учитывают только предыдущий контекст. К популярным моделям-декодерам относится семейство GPT.

0d9bb757b6186288e71ff9888aca9c0a.png

Обычно этого добиваются с помощью маскирования оценок внимания с помощью двоичной нижнетреугольной матрицы и замены немаскированных элементов отрицательной бесконечностью (потом при прогоне через МЛФ получают для этих позиций оценки внимания равные нулю). Давайте обновим нашу схему с self-attention с учетом сказанного:

Маскированное вычисление self-attention. Предполагается, что эмбеддинги позиционно закодированы.

Маскированное вычисление self-attention. Предполагается, что эмбеддинги позиционно закодированы.

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

e8279b15f352ad34dd0fbbfae1a74e1c.png

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

Кроме того, после применения МЛФ к логитам без фильтрации мы получим распределение вероятностей по каждому токену в словаре модели. Объем данных может быть огромным! И зачастую хочется уменьшить количество возможных вариантов с помощью разных фильтров:

  • Регулировка температуры: температура — это параметр, применяемый в операции МЛФ. Он влияет на случайность генерируемого текста, и с помощью изменения распределения вероятностей выходных слов определяет, насколько творческим будет результат работы модели. Повышение температуры сглаживает распределение и увеличивает разнообразие текста.

  • Выборка топ-P: количество потенциальных кандидатов для следующего токена фильтруется на основе заданного порога вероятности и меняет распределение вероятностей в зависимости от кандидатов, превысивших порог.

  • Выборка топ-K: количество потенциальных кандидатов ограничивается количеством наиболее вероятных токенов К на основе их логитов или значения вероятности (в зависимости от реализации).

Подробнее об этих методах можно почитать здесь.

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

Энкодеры-декодеры

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

Главное отличие архитектур типа энкодер-декодер заключается в том, что декодер использует энкодер-декодерное внимание: при вычислении внимания используется результат энкодера (K и V) и входные данные декодера (Q). Сравните с self-attention, когда для всех входных данных используется одна и та же входная матрица эмбеддингов. При этом общий процесс синтеза очень похож на процесс в архитектурах декодеров.

Ниже — схема архитектуры энкодера-декодера. Для её упрощения я показал вариант post-layer norm из исходной научной статьи, в котором слой нормализации расположен после блоков внимания.

0c7e4f472f35163aba31301e2326baf7.png

Ссылки

●              [1706.03762] Attention Is All You Need (arxiv.org)

●              Recent Advances in Google Translate — Google Research Blog

●              How GitHub Copilot is getting better at understanding your code — The GitHub Blog

●              Introducing ChatGPT (openai.com)

●              gpt-4.pdf (openai.com)

●              Introducing LLaMA: A foundational, 65-billion-parameter language model (meta.com)

●              The Illustrated Transformer — Jay Alammar — Visualizing machine learning one concept at a time. (jalammar.github.io)

●              Byte-Pair Encoding tokenization — Hugging Face NLP Course

●              Drenai series | David Gemmell Wiki | Fandom

●              bert-base-uncased · Hugging Face

●              Transformers (huggingface.co)

●              [2010.11929v2] An Image is Worth 16×16 Words: Transformers for Image Recognition at Scale (arxiv.org)

●              Getting Started With Embeddings (huggingface.co)

●              A Gentle Introduction to the Bag-of-Words Model — MachineLearningMastery.com

●              [2104.09864] RoFormer: Enhanced Transformer with Rotary Position Embedding (arxiv.org)

●              Scaled Dot-Product Attention Explained | Papers With Code

●              Softmax function — Wikipedia

●              [1607.06450] Layer Normalization (arxiv.org)

●              Vanishing gradient problem — Wikipedia

●              [1512.03385] Deep Residual Learning for Image Recognition (arxiv.org)

●              [1810.04805] BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding (arxiv.org)

●              [2005.14165] Language Models are Few-Shot Learners (arxiv.org)

●              Token selection strategies: Top-K, Top-P, and Temperature (peterchng.com)

●              Multinomial distribution — Wikipedia

●              [1910.10683] Exploring the Limits of Transfer Learning with a Unified Text-to-Text Transformer (arxiv.org)

© Habrahabr.ru