# Иллюзия разума: математика и архитектура современных LLM

Источник: https://www.youtube.com/watch?v=biveB0gOlak
Канал: freeCodeCamp.org
Опубликовано: 24.04.2025

---

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

## 🚀 Введение в архитектуру и принципы работы LLM

[[JUMP:00:00]]

Большие языковые модели (LLM) — это интеллектуальные системы, главная задача которых заключается в генерации текста на основе анализа входящих данных. Фундаментальный принцип работы любой современной LLM, включая Llama 4, Quen, Deepseek, GPT, Gemma, Gemini и Claude, сводится к предсказанию следующего логичного элемента в последовательности.

Важно понимать, что «из коробки» языковая модель не обладает осознанием того, что такое чат или диалог. Это математическая структура, которая принимает на вход текст, анализирует его структуру и вычисляет вероятности для всех возможных продолжений. Модель оперирует не просто словами, а токенами — элементарными единицами данных, которыми могут быть как части слов, так и целые фразы, символы или эмодзи. В процессе генерации модель присваивает каждому потенциальному токену из своего словаря вероятность того, что именно он должен следовать за текущим контекстом. Сумма всех вероятностей для всех токенов в словаре всегда равна 100%, что позволяет модели делать обоснованный выбор.

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

### 🎛 Методы семплирования: от предсказуемости к креативности

[[JUMP:07:57]]

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

*   **Greedy Sampling (Жадный поиск):** Модель всегда выбирает токен с максимальной вероятностью. Этот подход идеален для задач, где существует единственный правильный ответ (например, математические вычисления или написание программного кода), но он делает модель чрезмерно цикличной и предсказуемой в творческих задачах.
*   **Random Sampling (Случайное семплирование):** Токены выбираются пропорционально их вероятностям. Это добавляет тексту вариативности, которую часто ошибочно принимают за «креативность». В действительности это лишь статистическая случайность, полезная для написания эссе или художественных текстов.
*   **Top-K Sampling:** Модель ограничивает выборку только $K$ наиболее вероятными токенами. Это позволяет исключить совсем маловероятные варианты, сохраняя при этом элемент случайности внутри заданного «окна» перспективных слов.

В реальных приложениях часто комбинируют несколько методов семплирования для достижения баланса между точностью и разнообразием текста.

### 🌡 Роль температуры в генерации текста

[[JUMP:11:04]]

Температура — это ключевой гиперпараметр, который управляет «остротой» распределения вероятностей токенов. Фактически, формула температуры модифицирует вероятности перед окончательным выбором:

*   **Низкая температура (ближе к 0):** Распределение вероятностей становится «острее». Наиболее вероятные токены получают еще больший вес, а маловероятные — практически обнуляются. Это делает модель более детерминированной, что критично для задач программирования и решения логических задач.
*   **Высокая температура:** Вероятности «сглаживаются», становясь ближе друг к другу. Это приводит к тому, что модель чаще выбирает менее очевидные токены, повышая непредсказуемость и разнообразие ответа.

Хотя API-интерфейсы часто ограничивают диапазон температуры (например, от 0 до 2), теоретически она может принимать любые значения. Важно помнить, что температура не меняет саму «интеллектуальность» модели, а лишь регулирует степень её консервативности при выборе следующего токена.

-

## 🧩 Искусство токенизации: от букв к подсловам

[[JUMP:25:24]]

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

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

### Преимущества стратегии subword-токенизации

[[JUMP:28:28]]

Золотой серединой в современной инженерии данных стала subword-токенизация (токенизация на уровне подслов). Этот подход позволяет достичь баланса между компактным размером словаря и вычислительной эффективностью, избегая крайностей «посимвольного» или «пословного» подходов.

Основная идея заключается в том, что вместо жесткого разбиения на полные слова (например, «running», «playing») мы выделяем общие морфемы или популярные сочетания букв, такие как «run», «play» и «in». Это дает ряд ключевых преимуществ:

*   **Оптимизация словаря:** Количество уникальных токенов сокращается с десятков миллионов (при использовании всех возможных слов) до сотен тысяч (обычно около 150 000 в современных моделях вроде Qwen).
*   **Гибкость:** Модель получает способность конструировать новые слова из существующих фрагментов, даже если само слово не встречалось в обучении в исходном виде.
*   **Устойчивость:** Данный метод значительно лучше справляется с опечатками, так как даже поврежденное слово может быть разбито на узнаваемые фрагменты.
*   **Вычислительная эффективность:** В отличие от посимвольной обработки, группы букв позволяют передавать больше семантической информации за один шаг, снижая общую нагрузку на вычислительные мощности.

Хотя исследования в области NLP развиваются крайне стремительно, и теоретически возможны новые прорывы, делающие пословную или попредложенческую токенизацию более предпочтительной, на данный момент именно подходы на базе subword-токенизации показывают наилучшую производительность в работе LLM.

## 🧩 Векторные эмбеддинги и их роль в представлении данных

[[JUMP:50:34]]

В процессе обучения LLM фундаментально важно понимать, как модель интерпретирует информацию. Поскольку компьютеры не «понимают» человеческий язык в привычном смысле, они работают с числами. Векторные эмбеддинги — это способ математического представления слов, символов или токенов в виде многомерных векторов чисел. Эти векторы позволяют передавать смысловые характеристики данных: слова, которые часто встречаются в схожих контекстах или имеют близкое значение, в векторном пространстве располагаются ближе друг к другу.

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

### Как формируются смысловые единицы
[[JUMP:51:32]]

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

*   **Уменьшение вычислений:** Замена двух токенов одним снижает нагрузку при обработке текста в два раза.
*   **Улучшение контекста:** Объединение часто встречающихся пар позволяет модели лучше улавливать устойчивые словосочетания или части слов, что делает обучение более целенаправленным.
*   **Иерархичность:** Новые токены, созданные путем слияния, сами могут участвовать в дальнейших операциях, создавая цепочки смысловых единиц.

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

### Программирование процесса слияния
[[JUMP:57:26]]

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

Процесс обучения алгоритма (например, BPE) включает в себя циклический поиск пар:

1.  **Статистика пар:** Функция `get_pair_stats` сканирует словарь, подсчитывая частоту появления каждой пары символов. Здесь важно избегать «кросс-словных» токенов, чтобы объединения происходили строго внутри границ слов.
2.  **Слияние:** Функция `merge_pair` заменяет наиболее частые пары на новый токен, обновляя структуру данных.
3.  **Итерации:** Этот цикл повторяется заданное количество раз (например, 15 итераций), постепенно формируя словарь, который максимально эффективно покрывает обучающий корпус.

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

## ⚙️ Реализация алгоритма Byte Pair Encoding (BPE)
[[JUMP:1:15:46]]

Основой создания эффективного словаря для языковой модели является алгоритм Byte Pair Encoding (BPE). Процесс начинается с формирования начального словаря, состоящего из всех отдельных символов текста. В ходе итеративного процесса алгоритм находит наиболее часто встречающуюся пару токенов в текущем представлении слов и объединяет их в новый, составной токен.

### Механика итеративного объединения
[[JUMP:1:19:46]]

Процесс обучения токенизатора строится на выполнении серии итераций (в примере их 15):

*   **Анализ частотности:** На каждом шаге функция `get_pair_stats` подсчитывает частоту появления всех пар символов или уже сформированных токенов в текущем наборе слов.
*   **Выбор лучшей пары:** Алгоритм идентифицирует пару с максимальной частотой (`best_pair`), которая станет кандидатом на объединение.
*   **Обновление словаря и правил:** Выбранная пара объединяется в новый токен, который добавляется в словарь. Правило этого слияния сохраняется в специальный словарь `merges`, что позволяет впоследствии «развернуть» токенизацию обратно до исходных символов.

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

### Вычислительная эффективность и структура данных
[[JUMP:1:16:54]]

Использование BPE дает существенное преимущество в вычислительной эффективности. Добавление нового токена в словарь технически увеличивает объем вычислений при расчете вероятностного распределения на выходе модели (так как размер выходного слоя растет). Однако, за счет того, что модель начинает оперировать более длинными токенами, общее количество токенов, которые необходимо обработать для представления одного и того же объема текста, значительно сокращается.

В реальных LLM вместо строк используются целочисленные индексы (ID) токенов. Это позволяет:

*   Ускорить поиск и обработку данных.
*   Оптимизировать использование оперативной памяти, так как хранение целых чисел требует меньше ресурсов, чем хранение строк.

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

---
CHAPTER-META---
{"summary": "Глава описывает пошаговую реализацию алгоритма BPE для токенизации, объясняя переход от символьного представления к более эффективным составным токенам на основе частотного анализа.", "quotes": [{"text":"The more frequent the pair the better because we will then reduce computation.","speaker":"Instructor","time":"1:16:54"}], "key_facts": ["Алгоритм BPE итеративно объединяет наиболее частые пары токенов в новые элементы словаря.", "Правила слияний сохраняются в словаре для возможности обратного преобразования.", "Использование целочисленных индексов вместо строк повышает вычислительную эффективность и экономит память."], "covered_topics": ["Алгоритм Byte Pair Encoding (BPE)", "Методика итеративного обучения токенизатора", "Вычислительные преимущества использования subword-токенов"]}

## 🧠 Анатомия контекста: как рождаются Ключи и Запросы
[[JUMP:1:40:53]]

### Эффективность обучения: параллельное насыщение контекстом
[[JUMP:1:41:20]]
Процесс работы большой языковой модели кардинально отличается в зависимости от того, обучается она или уже запущена на устройствах пользователей. В режиме инференса (генерации) алгоритм берет готовую последовательность токенов и предсказывает исключительно одно следующее слово. Однако если бы процесс обучения строился точно так же, это было бы крайне неэффективно.

Во время обучения перед создателями стоит задача оптимизировать параметры модели как можно быстрее. Возьмем для примера предложение «the dog ran quickly around the». Модель не просто пытается угадать финальное слово; она обучается предсказывать *каждое* последующее слово на основе предыдущих. На первом шаге ей подается токен «the», и она пытается спрогнозировать слово «dog». Затем ей дают фразу «the dog», чтобы она угадала «ran», и так далее по всей цепочке. 

В ходе этого процесса модель на каждом этапе видит так называемую «истинную реальность» (ground truth) — реальный следующий токен из обучающего текста. Сверяясь с ним, она корректирует все свои внутренние параметры: веса и смещения. Проходя через миллиарды итераций и перерабатывая тексты со всего интернета, языковая модель постепенно усваивает, какие комбинации слов вероятны, а какие лишены смысла. Таким образом, во время обучения искусственно симулируется ситуация, где каждый токен принудительно насыщается контекстом всех предшествующих элементов. Это подготавливает архитектуру к тому, чтобы на этапе инференса безошибочно рассчитывать контекст для финального предсказания.

### Поиск релевантности: концепция Ключей (Keys) и Запросов (Queries)
[[JUMP:1:45:28]]
Когда перед моделью стоит задача объединить информацию из прошлых слов, стандартные математические подходы вроде простого сложения векторов не работают. Очевидно, что в предложении «the dog ran quickly» значение слова «quickly» («быстро») гораздо сильнее зависит от глагола «ran» («бежал») или существительного «dog» («собака»), чем от служебного артикля «the». Более того, в длинном тексте гораздо раньше могло упоминаться слово «cat» («кошка»), но модель должна четко понимать, что характеристика «быстро» относится именно к собаке. Архитектура должна сама научиться определять, какой контекст важен, а какой нет.

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

* **Ключ (Key):** вектор, который кодирует и описывает, какую именно информацию данный токен может предложить остальным участникам последовательности. Он рассчитывается один раз и остается неизменным для конкретного токена во всей фразе.
* **Запрос (Query):** вектор, который определяет, какого рода контекст необходим текущему слову для уточнения его собственного смысла.

Суть этого разделения можно сформулировать одной емкой цитатой: «Запрос говорит: какой контекст я ищу? Ключ говорит: какой контекст у меня есть». Когда токен «quickly» пытается определить свою смысловую связь с окружением, он отправляет свой Запрос и сопоставляет его с Ключами всех предыдущих слов, полностью игнорируя их базовые семантические эмбеддинги. Если связь сильна — например, между «собакой» и действием «быстро» — модель получает высокий балл. Если же Ключ принадлежит нерелевантной «кошке», оценка будет близка к нулю.

### Математика сходства: скалярное произведение и матрицы внимания
[[JUMP:1:56:35]]
В реальных нейросетевых архитектурах векторы Ключей и Запросов обычно значительно компактнее исходных эмбеддингов: если базовый вектор слова может содержать тысячи чисел, то его Ключи и Запросы чаще всего состоят из сотен элементов. Чтобы превратить сопоставление этих векторов в конкретную оценку связи (число от нуля до единицы), применяется базовая математическая операция — скалярное произведение (dot product).

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



[Image of vector dot product projection]


Чем ближе направления векторов Запроса и Ключа, тем выше их финальное сходство. Любопытный математический факт: если векторы Запроса и Ключа оказываются строго перпендикулярны друг другу (угол равен 90 градусам), их скалярное произведение становится равным нулю.

Чтобы модель учитывала не только смысл, но и физическое расстояние между словами, в Ключи и Запросы напрямую подмешивается позиционная информация, детальная логика которой будет разобрана в следующих главах. Благодаря этому упоминание абстрактной «кошки», оставшееся на сто токенов позади, автоматически получит низкий приоритет при расчете сходства просто из-за своей удаленности. 

Итоговые результаты таких вычислений формируют упорядоченную структуру оценок. В качестве классического примера можно рассмотреть фразу «life is short eat dessert first». При анализе слова «short» его вектор Запроса поочередно умножается на Ключи предшествующих слов. На выходе получается точное числовое распределение: например, связь «short» со словом «life» оценивается в 0.19. Эти числовые коэффициенты в дальнейшем определяют, в какой пропорции контекст каждого отдельного слова будет добавлен для обогащения финального значения токена.

## 🧠 Механизм Self-Attention: Как модель понимает контекст

[[JUMP:2:06:04]]

Фундаментальный принцип работы современной языковой модели заключается в том, чтобы каждый токен «обогащался» смыслом окружающих его слов, не теряя при этом своей индивидуальности. В процессе self-attention (самовнимания) модель формирует контекстуализированные векторы, где итоговое представление токена — это «заряженная» контекстом версия исходного эмбеддинга. 

Чтобы сбалансировать значимость, модель учится определять пропорции: какая часть смысла должна остаться от самого слова, а какая — привнесена из предыдущих токенов. Обычно «родной» контекст токена составляет около 50–60% итогового значения, что предотвращает «размывание» смысла исходного слова избыточным влиянием соседей.

### Три вектора: Query, Key и Value

[[JUMP:2:11:21]]

Механизм self-attention опирается на взаимодействие трех векторов, которые вычисляются для каждого токена через обучаемые матрицы весов:

*   **Query (Запрос):** определяет, какую информацию токен «ищет» в других словах.
*   **Key (Ключ):** описывает, какой контекст данный токен может предложить другим.
*   **Value (Значение):** содержит саму «информацию», которая будет добавлена в итоговый вектор токена.

Когда мы вычисляем скалярное произведение (dot product) между Query текущего слова и Key другого слова, мы получаем коэффициент аффинности — оценку того, насколько первый токен должен «прислушаться» к контексту второго. Использование отдельных матриц для этих векторов позволяет модели эффективно разделять семантическое значение слова и его «контекстуальную значимость».

### Матрица внимания и маскирование будущего

[[JUMP:2:08:32]]

В архитектуре декодера важно, чтобы модель, предсказывая следующий токен, не «подглядывала» в будущее. Для этого используется треугольная маска в матрице внимания. Все ячейки, соответствующие будущим токенам, заполняются нулями (или минус бесконечностью перед применением softmax), что гарантирует: текущий токен может взаимодействовать только с самим собой и предыдущими элементами последовательности.

После вычисления сырых оценок (scores) применяется функция **softmax**. Она масштабирует значения так, чтобы сумма вероятностей для каждого токена равнялась единице. Это превращает оценки в весовые коэффициенты, которые определяют, какую долю значения (Value) каждого предыдущего токена нужно добавить к текущему вектору.

### Многоголовое внимание (Multi-Head Attention)

[[JUMP:2:29:34]]

Для более глубокого понимания связей реальные модели не обрабатывают весь вектор целиком, а разделяют его на несколько «голов» (heads). Каждая голова выполняет механизм внимания независимо от остальных. Логика такого разделения в том, что каждая голова может специализироваться на извлечении разных типов контекста: например, одна фокусируется на грамматических связях, другая — на семантике объектов или временных признаках.

---
*Ранее в разговоре упоминались методы нейронных сетей прямого распространения (Feed Forward Networks), которые применяются после этапа внимания для дополнительной нелинейной обработки контекста.*

## 🛠️ Сборка механизма внимания: от логики к коду
[[JUMP:2:30:54]]

Процесс обработки информации в Llama 4 строится на максимальной изоляции контекстов внутри отдельных «голов» внимания. Каждая голова фокусируется на своих аспектах данных, которые на начальных этапах могут быть переплетены и хаотичны. Однако после раздельной обработки векторов запросов (query), ключей (key) и значений (value), система переходит к этапу интеграции.

### Восстановление размерности: роль выходной матрицы проекции
[[JUMP:2:31:34]]

После того как каждая голова сформировала свой вектор значений (value head), они объединяются методом конкатенации в один массивный вектор. На этом этапе возникает техническая сложность: полученный «склеенный» вектор значительно меньше исходного эмбеддинга токена, с которого начинался процесс. Чтобы вернуть данные к исходному формату и позволить модели работать дальше, используется выходная матрица конверсии (output conversion matrix).

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

* Система проходит по всей строке вектора и каждому столбцу матрицы.
* Формируется первый признак (feature) нового эмбеддинга, затем второй и так далее.
* В итоге получается вектор токена (например, слова «dog»), который теперь «напитан» (juiced up) информацией обо всех окружающих его словах.



### Конфигурация параметров и управление памятью
[[JUMP:2:33:14]]

Переходя от теории к программному воплощению на PyTorch, важно определить ключевые гиперпараметры архитектуры. Одним из центральных понятий является `hidden_size` — размерность вектора эмбеддинга токена, которая сопровождает его на протяжении всей обработки. В учебной реализации Llama 4 количество голов внимания может составлять 16, что означает деление ключевых векторов на 16 независимых потоков.

Ранее в разговоре упоминались методы Grouped Query Attention (GQA), и здесь они находят свое практическое применение для оптимизации ресурсов. Вместо того чтобы вычислять уникальные ключи и значения для каждой из 16 голов, модель объединяет их в группы.

* **Разделение ресурсов:** На 16 запросов (queries) может приходиться всего 4 ключа и значения. 
* **Экономия памяти:** Группа из четырех голов использует общие Key и Value, что снижает требования к оперативной памяти в четыре раза. 
* **Производительность:** Такой подход практически не снижает точность модели, но критически важен при работе с контекстными окнами в миллионы токенов.

### Математическая интерпретация дистанции между токенами
[[JUMP:2:37:17]]

Для того чтобы модель понимала порядок слов и расстояние между ними, используется механизм поворота векторов. Это позволяет ИИ осознавать, что «собака» (dog) в предложении «собака бежит» находится рядом с действием, а не относится к «кошке», упомянутой тысячу токенов назад. 

Суть метода заключается в простом математическом трюке: векторы в пространстве поворачиваются на определенный угол в зависимости от их позиции в тексте. Чем дальше токены друг от друга, тем сильнее они «разворачиваются» относительно друг друга, что автоматически снижает их скалярное произведение (dot product) и, как следствие, уровень внимания между ними. 



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

1.  **Низкие размерности (первые пары):** Вращаются очень медленно. Даже при большом удалении токенов угол изменится незначительно. Это помогает модели улавливать глобальные, дальние связи.
2.  **Высокие размерности (последние пары):** Вращаются очень быстро, совершая полные круги даже при небольшом сдвиге позиции. Это обеспечивает высокую чувствительность к локальному контексту и порядку соседних слов.

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

### Техническая подготовка тензоров и масок
[[JUMP:2:50:08]]

Практическая инициализация модели требует создания специфических структур данных. В Llama 4 не используется смещение (bias) в проекционных матрицах и не применяется dropout, чтобы избежать избыточности. Вместо этого внедряется QK-нормализация (L2-нормализация для запросов и ключей) перед расчетом внимания.

Для тестирования архитектуры задаются базовые параметры: размер батча (batch size) равный 2, что означает одновременную обработку двух независимых текстовых последовательностей. Для каждого токена создаются идентификаторы позиций (position IDs) — одномерный тензор со значениями от 0 до длины последовательности минус один.

Особое внимание уделяется маске внимания (attention mask). Она представляет собой квадратную матрицу, где верхний правый треугольник заполнен нулями. Это гарантирует, что при расчете модель не сможет «подсматривать» в будущее: запросы текущего токена физически не могут обратиться к ключам токенов, которые стоят в тексте позже него. Эта маска одинакова для всех голов внимания, что упрощает вычисления.

## 🧭 Оптимизация архитектуры: Глубокое погружение в RoPE и Grouped Query Attention
[[JUMP:2:58:21]]

### Эффективность масштабирования: Механизм Grouped Query Attention (GQA)
[[JUMP:2:58:21]]

Механизм внимания в современных больших языковых моделях требует колоссальных вычислительных ресурсов и памяти. Ранее в разговоре уже подробно разбирался классический алгоритм self-attention, однако для оптимизации работы Llama использует более продвинутый подход — Grouped Query Attention (GQA). В рассматриваемой реализации вместо создания индивидуальных пар ключей и значений для каждого запроса применяется техника группировки: в коде создается 16 головок запросов (queries) и всего 4 головки ключей (keys) и значений (values). Таким образом, ровно четыре головки запросов разделяют между собой одну общую головку ключей и значений ради повышения вычислительной эффективности.

Для реализации этого процесса исходные матрицы трансформируются и меняют свою форму, разделяя вычисления по независимым головкам. Перестановка размерностей позволяет обрабатывать каждую головку так, будто это изолированное контекстное окно. В коде вычисляется специальный параметр `num_key_value_groups`, отражающий количество головок запросов, приходящихся на одну KV-головку. В данном случае 16 головок делятся на 4, что дает ровно 4 группы запросов на каждую пару ключ-значение.

С технической стороны, при финальном расчете скоров внимания применяется функция повторения `repeat_kv`. Она принимает скрытые состояния и количество необходимых повторений, фактически расширяя размерность более компактных KV-тензоров до полного соответствия числу головок запросов перед выполнением матричного умножения.

### Вращение в комплексном пространстве: Теория и математика RoPE
[[JUMP:3:02:09]]

Вторым важнейшим столпом оптимизации архитектуры Llama являются поворотные позиционные эмбеддинги (Rotary Positional Embeddings, или RoPE). В отличие от абсолютных позиционных эмбеддингов, применявшихся в трансформерах первого поколения, RoPE внедряет информацию о взаимном расположении слов непосредственно в векторы запросов и ключей перед вычислением их скалярного произведения. Этот метод радикально улучшает способность модели обрабатывать длинные контекстные последовательности.

Основная математическая идея RoPE заключается в представлении эмбеддингов в пространстве комплексных чисел и их повороте на угол, пропорциональный позиции токена в тексте. Для демонстрации расчета инверсных частот приводится пример с вектором небольшой размерности (равной 8) и базовым значением частоты 10 000.

Процесс вычисления выглядит следующим образом:

* Генерируется диапазон значений от 0 до 8 с шагом 2, получая массив значений.

* Значения нормализуются путем деления на общую размерность для приведения к диапазону от 0 до 1.

* Базовое число 10 000 возводится в степень полученных коэффициентов, после чего берутся обратные величины.

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

### Практическая реализация RoPE в коде
[[JUMP:3:10:14]]

Перенос математической логики RoPE в программный код происходит в функции `apply_rotary_embedding_torch`. В качестве входных параметров она принимает тензоры запросов и ключей, имеющие стандартные размерности: батч, количество головок, длина последовательности и размерность головки.

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

Чтобы применить вращение, векторы временно трансформируются. Кодирование позиций должно применяться одинаково ко всем головкам внимания для конкретной позиции токена, для чего добавляется дополнительная ось для бродкастинга. Пары чисел внутри размерности головки интерпретируются как комплексные числа через метод `view_as_complex`. После завершения операции поворота векторы переводятся обратно в исходный тип данных (например, Float16) и возвращаются для дальнейших расчетов.

В конечном счете вся эта логика упаковывается в единый модуль `Simplified Llama 4 Attention`, где последовательно выполняются линейные слои, применение RoPE к векторам Q и K, дублирование головок через GQA и финальная проекция тензоров.

## 🧠 Финальный аккорд: Feed Forward Networks и стабильность обучения
[[JUMP:321:04]]

Завершающий этап архитектуры Llama 4, как и большинства современных больших языковых моделей, строится на фундаменте блоков **Feed Forward Network (FFN)**. После того как механизм внимания (ранее в разговоре мы подробно разобрали Grouped Query Attention и RoPE) определил контекстные связи между токенами, управление передается слоям полносвязной сети. Если внимание — это «коммуникация» между словами, то FFN — это «индивидуальная обработка» каждого слова, позволяющая модели извлекать глубокие иерархические признаки.

### Архитектура FFN: Магия расширения и сжатия
[[JUMP:321:43]]

Сеть прямого распространения (FFN) применяется независимо к каждой позиции токена после того, как он прошел через механизмы внимания и остаточные связи. Основная задача этого блока — внести нелинейность, которая позволяет модели решать более сложные задачи, чем простое взвешивание векторов. Пока данные проходят только через слои внимания, они подвергаются в основном линейным преобразованиям; FFN же, благодаря функциям активации, «усиливает важные признаки и подавляет менее значимый контекст».

Структура FFN в Llama следует принципу расширения и последующего сжатия:

* **Входной слой:** Принимает токен размерности `hidden_size`.
* **Промежуточный слой (Intermediate):** Расширяет размерность вектора. Обычно используется коэффициент расширения **8/3** (примерно 2.67), что является стандартом для архитектур типа Llama.
* **Выравнивание:** Для оптимизации вычислений промежуточный размер часто корректируется так, чтобы он был кратен 32.
* **Выходной слой:** Сжимает данные обратно до исходного `hidden_size`.

Именно внутри этого расширенного пространства происходит основная «магия» обработки признаков.

### Gated Linear Units и нелинейная обработка
[[JUMP:325:22]]

В современных LLM стандартные полносвязные слои заменены на более эффективные механизмы, такие как **Gated Linear Units (GLU)**. В реализации Llama 4 это выглядит как сложная структура из трех проекций:

1.  **Gated Projection:** Линейный слой, создающий «ворота» для информации.
2.  **Up Projection:** Слой, расширяющий размерность данных.
3.  **Down Projection:** Слой, возвращающий данные к исходной размерности.

Ключевым моментом здесь является использование функции активации (чаще всего **SiLU/SwiGLU**). Модель применяет активацию к одной из проекций, а затем выполняет поэлементное умножение (element-wise multiplication). Этот метод позволяет сети гибко управлять потоком информации: «ворота» буквально решают, какие компоненты вектора должны пройти дальше, а какие — быть обнулены. Итоговый результат затем «схлопывается» обратно вниз через Down Projection.



### RMS-нормализация и остаточные связи
[[JUMP:324:14]]

Для того чтобы обучение такой глубокой сети оставалось стабильным и не приводило к «взрыву» или затуханию градиентов, Llama использует **RMS-нормализацию (Root Mean Square Layer Normalization)**. В отличие от стандартных трансформеров, где нормализация часто ставилась *после* блоков внимания или FFN, в Llama применяется подход **Pre-Normalization**.

> «Нормализация применяется перед подачей состояния в FFN. Это то, что сейчас делают практически все современные LLM — нормализация перед вниманием и перед FFN», — подчеркивает автор курса.

Этот подход позволяет сигналу проходить через сеть более чисто. Важным дополнением являются **остаточные связи (Residual Connections)**. После обработки в FFN результат суммируется с исходным входным вектором токена, который был получен еще до нормализации. Это гарантирует, что нейросеть сохраняет необходимую информацию из оригинального токена и обучается только «добавлять» новые полезные признаки, а не переписывать их с нуля.

### Путь к миллиардам параметров
[[JUMP:327:23]]

Разбор блока FFN завершает проектирование упрощенной версии Llama 4. Хотя некоторые аспекты реализации остаются крайне сложными, понимание этих базовых принципов — нормализации, проекций и нелинейной активации — дает ключ к созданию 90% современных языковых моделей.

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