Это четвёртая статья серии «AI без магии». В первой разобрали, откуда вообще взялись LLM. Во второй — как модель «думает» по одному токену и почему галлюцинирует. В третьей — как текст превращается в векторы. Теперь разберём механизм, который сделал трансформер тем, чем он стал: attention.
Зачем токенам вообще разговаривать
В прошлой статье мы остановились на статических эмбеддингах. Каждое слово получает свой вектор, и похожие по смыслу слова кучкуются в пространстве. Но есть проблема: вектор у слова один, а смыслов может быть много.
Классический пример из 3Blue1Brown: возьмите слово «mole». В фразе «American shrew mole» это вид крота. В «one mole of carbon dioxide» — единица количества вещества. В «take a biopsy of the mole» — родинка. Три совершенно разных смысла, а статический эмбеддинг — один.
Или пример попроще: слово «банк». «Сбербанк» — финансовая организация. «На банке реки» — берег. «Открыл стеклянную банку» — ёмкость. Эмбеддинг-слой, который мы построили в прошлой статье, выдаст один и тот же вектор во всех трёх случаях.
Чтобы понять, какое из значений сейчас в игре, токену нужно посмотреть на соседей. «Стеклянную» рядом — значит ёмкость. «Реки» — значит берег. «Сбер» — финансы.
Механизм, который позволяет токенам «смотреть друг на друга» и обновлять свои векторы с учётом контекста, называется attention. И в этой статье мы разберём, как он устроен.
Soft search: общая идея
В первой статье мы уже коротко упоминали attention — как «soft search». Идея пришла из машинного перевода в 2015 году: вместо того чтобы один токен жёстко выбирал один связанный с ним токен из контекста, давайте получать смесь всех с разными весами.
Это похоже на поиск в библиотечном каталоге, только мягкий. Вы приходите с запросом — например, «что-то про нейросети». Каталог не выдаёт вам одну книгу. Он выдаёт смесь: 60% — книга про машинное обучение, 30% — про оптимизацию, 10% — про статистику. Чем лучше книга совпадает с запросом, тем больше её доля в смеси.
В attention происходит ровно это. Каждый токен задаёт запрос. Все остальные токены показывают свои ключи. Мы считаем, насколько запрос совпадает с каждым ключом, нормализуем эти совпадения в проценты, и собираем взвешенную сумму значений этих токенов.
Query, Key, Value
Каждый токен в attention играет три роли:
— Query (запрос): «что я ищу в контексте?» — Key (ключ): «вот что я могу предложить, если меня спросят» — Value (значение): «вот что я передам, если со мной согласятся»
Все три — это просто разные проекции исходного эмбеддинга через три обучаемые матрицы Wq, Wk, Wv. Эти матрицы — те самые «параметры», которые модель учит во время тренировки. Ничего больше в attention нет.
Зачем вообще нужны три разные роли? Почему нельзя просто сравнивать векторы напрямую? Потому что одно и то же слово в разных контекстах хочет разного. Слово «который» как query ищет существительное-антецедент. Как key — оно ничем особо не интересно. А как value — передаёт «здесь начинается придаточное». Три проекции позволяют модели выучить, что искать, как себя показывать и что отдавать — независимо друг от друга.
Self-attention пошагово
Слово «self» в self-attention означает, что все query, key и value берутся из одной и той же последовательности — той, которую модель сейчас обрабатывает. Не как в машинном переводе, где запросы шли от декодера, а ключи от энкодера. В GPT-моделях query, key и value — это всё разные роли тех же входных токенов.
Возьмём конкретный пример из учебника Раски — фразу «Your journey starts with one step». Шесть токенов, считаем self-attention.
Шаг 1. Для каждого токена вычисляем три вектора: q, k, v (умножая эмбеддинг на Wq, Wk, Wv).
Шаг 2. Считаем матрицу совпадений 6×6: для каждой пары (i, j) берём скалярное произведение q_i · k_j. Это attention score — насколько вопрос i-го токена «совпадает» с предложением j-го.
Шаг 3. Делим всё на √d_k (где d_k — размерность ключей). Это нужно, чтобы scores не разбегались на больших размерностях и softmax не уходил в насыщение.
Шаг 4. К каждой строке применяем softmax. Получаем attention weights — нормализованные веса, сумма которых по строке равна 1.
Шаг 5. Для каждого токена i считаем взвешенную сумму всех значений: z_i = Σ w_ij · v_j. Это и есть контекстный вектор — обновлённый эмбеддинг, в котором уже учтён контекст.
Главное, что стоит понять: эта матрица полностью заполнена. Любой токен может «достать» информацию о любом другом за один проход. В RNN, чтобы передать сигнал от первого токена к десятому, нужно было пройти десять шагов рекурсии — на каждом из них сигнал затухал. В attention это происходит за одно умножение матриц.
Causal mask: почему GPT не видит будущее
В GPT-моделях есть тонкость. Когда модель учится предсказывать следующий токен, она не должна подсматривать в правильный ответ.
Представьте: мы скармливаем модели «Your journey starts with one», и она должна предсказать «step». Если бы при подсчёте attention для слова «one» модель могла видеть «step», то задача стала бы тривиальной: смотри на следующий токен и его же выдавай. Модель ничему не научится, потому что на инференсе следующего токена ещё нет — его как раз надо предсказать.
Решение — causal mask, причинная маска. Перед softmax все клетки в верхнем треугольнике матрицы attention scores заменяются на минус бесконечность. После softmax они становятся нулями: токен i может смотреть только на токены 1…i, но никогда на i+1, i+2 и так далее.
Маска применяется только в декодер-моделях (GPT, LLaMA, Claude). В энкодерах (BERT, classification-модели) её не нужно — там задача другая, и токены спокойно смотрят и вперёд, и назад. Но GPT — авторегрессивная модель, она генерирует слева направо, поэтому маска нужна.
Multi-head: почему head несколько
Одна head attention — это одна «точка зрения». Она учится связывать токены каким-то одним способом. Но в языке связей много: подлежащее ↔ сказуемое, прилагательное ↔ существительное, местоимение ↔ антецедент, артикль ↔ слово, к которому он относится.
Если бы у нас была только одна head, модель должна была бы запихнуть все эти типы связей в одну матрицу — что почти невозможно. Решение: запустить несколько head параллельно. У каждой свои Wq, Wk, Wv, и каждая учится своему типу связей.
Хороший пример из 3Blue1Brown: фраза «The glass ball fell on the steel table, and it shattered». Чтобы понять, к чему относится «it» и что значит «shattered», нужно несколько разных attention-связей одновременно: «ball» ↔ «glass» (свойство), «table» ↔ «steel» (свойство), «shattered» ↔ что-то хрупкое. Одна head не справится — нужно несколько, каждая со своим узором весов.
В оригинальной статье «Attention Is All You Need» 2017 года было 8 head. У GPT-2 — 12 в маленькой версии, 25 в самой большой. У GPT-3 — 96 head в каждом блоке. И блоков много: 12, 24, 96 в зависимости от размера модели. Каждая комбинация (блок × head) учится своему типу связей.
После того как все head посчитали свои контекстные векторы, результаты конкатенируются в один длинный вектор и пропускаются через ещё одну линейную проекцию. Это и есть multi-head attention. На выходе — обновлённый вектор для каждого токена, в котором сжата информация со всей последовательности, увиденная под несколькими углами одновременно.
Что мы теперь знаем
— Статические эмбеддинги дают слову один вектор. Но смысл слова зависит от контекста — нужно, чтобы токены «поговорили друг с другом».
— Attention — это soft search. Каждый токен задаёт запрос, все остальные показывают ключи, мы получаем взвешенную смесь значений.
— Q, K, V — три проекции исходного эмбеддинга через обучаемые матрицы Wq, Wk, Wv. В этом весь механизм — три матрицы, скалярное произведение, softmax.
— Causal mask запрещает токену смотреть в будущее. Без неё GPT не научилась бы предсказывать следующий токен.
— Multi-head — несколько head параллельно, каждая со своими Wq/Wk/Wv, каждая учится своему типу связей. У GPT-3 — 96 head в каждом блоке.
Attention превратил статические эмбеддинги в контекстные. Каждый токен теперь «знает» про окружение, и его вектор сдвинут в нужную сторону: «mole» в «shrew mole» теперь ближе к «крот», а в «one mole of CO2» — к «количество вещества».
Но attention — это только половина блока трансформера. После него идёт обычная feed-forward сеть, нормализация, residual connection. И таких блоков в стопке десятки или сотни. В следующей, последней статье серии, соберём всё вместе и посмотрим, как из этих кубиков получается работающая GPT.
- Attention Is All You Need Та самая статья, в которой transformer впервые появился — без RNN, только attention.
- Attention in transformers, step-by-step Лучшее визуальное объяснение, что делает одна head attention. Примеры с «mole» и «Eiffel tower».
- Causal attention, explained Короткий FAQ про то, почему GPT-моделям нужна маска и где именно она применяется.
- Query, Key, Value: The Foundation of Transformer Attention Аналогия с библиотечным каталогом, которая хорошо ложится на Q/K/V.