MicroGPT: Минималистичная реализация GPT для глубокого понимания трансформеров — Блог
$ cat learn/blogopost/microgpt-analysis.md

MicroGPT: Минималистичная реализация GPT для глубокого понимания трансформеров

Что такое microgpt.py?

В репозитории обнаружен единственный файл microgpt.py — это компактная, но полная реализация Generative Pre-trained Transformer (GPT) на чистом Python, без внешних зависимостей. Авторство, судя по комментарию @karpathy, принадлежит Андрею Карпати, известному исследователю в области глубокого обучения и создателю популярных образовательных материалов.

Код представляет собой «наиболее атомарный способ обучения и выполнения вывода для GPT», как сказано в заголовке. Это не «секретный алгоритм», а образовательный инструмент, который показывает, как работают современные языковые модели, начиная с токенизации и заканчивая обновлением параметров через Adam.

Зачем это нужно?

Реализация GPT в промышленных масштабах (например, в OpenAI GPT‑3/4) состоит из миллионов строк кода, оптимизированных под распределённые вычисления, кеширование внимания и множество эвристик. MicroGPT же удаляет все слои абстракции и оставляет только суть:

  • Автоград (автоматическое дифференцирование) реализован в классе Value (строки 30–73).
  • Токенизация на уровне символов (строки 24–27).
  • Архитектура трансформера с одним слоем, многоголовым вниманием и MLP‑блоком (строки 108–144).
  • Оптимизатор Adam с линейным затуханием скорости обучения (строки 146–182).
  • Цикл обучения на датасете имён (строки 151–185) и инференс с температурой (строки 186–200).

Изучив этот код, можно понять, как именно GPT «думает» — как эмбеддинги токенов и позиций складываются, как внимание взвешивает контекст, как MLP преобразует признаки и как градиенты распространяются назад для обновления весов.

Ключевые компоненты

1. Автоград (Value)

Класс Value — это сердце микрофреймворка. Он хранит скалярное значение (data), градиент (grad), ссылки на дочерние узлы и локальные производные. Переопределение операторов (+, *, **, log, exp, relu) позволяет строить вычислительный граф, а метод backward() выполняет обратное распространение ошибки по цепному правилу.

class Value:
    __slots__ = ('data', 'grad', '_children', '_local_grads')
    ...
    def backward(self):
        # топологическая сортировка и накопление градиентов

2. Токенизация

Датасет — список имён (загружается из names.txt). Уникальные символы образуют словарь, к которому добавляется специальный токен BOS (Beginning of Sequence). Таким образом, каждый символ (например, 'a', 'b') получает целочисленный id, а BOS используется для обозначения начала/конца последовательности.

3. Параметры модели

Веса инициализируются маленькими случайными значениями (гауссово распределение со стандартным отклонением 0.08). Структура параметров повторяет архитектуру GPT‑2:

  • wte — матрица токенных эмбеддингов (размер vocab_size × n_embd)
  • wpe — матрица позиционных эмбеддингов (block_size × n_embd)
  • layer{i}.attn_wq, layer{i}.attn_wk, layer{i}.attn_wv, layer{i}.attn_wo — веса внимания
  • layer{i}.mlp_fc1, layer{i}.mlp_fc2 — веса MLP‑блока
  • lm_head — проекция на словарь для получения логитов

Всего в модели с n_layer=1, n_embd=16, block_size=16, n_head=4 получается несколько тысяч параметров — несравнимо мало по сравнению с промышленными моделями (миллиарды), но достаточно для обучения на коротких последовательностях.

4. Архитектура GPT (gpt)

Функция gpt выполняет прямой проход для одного токена на заданной позиции:

  1. Токенное и позиционное эмбеддинги складываются.
  2. RMSNorm (упрощённый аналог LayerNorm) применяется к эмбеддингам.
  3. Для каждого слоя:
    • Многоголовое внимание: запрос, ключ, значение вычисляются через линейные проекции; внимание считается как взвешенная сумма значений с весами, полученными после softmax от скалярных произведений запроса и ключа.
    • Остаточное соединение добавляет вход блока внимания к его выходу.
    • MLP‑блок: два линейных преобразования с активацией ReLU между ними, также с остаточным соединением.
  4. Логиты получаются проекцией выхода последнего слоя на размер словаря.

5. Обучение

Цикл обучения на каждом шаге:

  • Выбирает один документ (имя), токенизирует его, добавляет BOS в начало и конец.
  • Для каждого токена в контексте (длиной до block_size) вычисляет логиты, вероятности (softmax) и отрицательное логарифмическое правдоподобие (кросс‑энтропийный loss).
  • Усредняет loss по длине последовательности.
  • Вызывает loss.backward() для расчёта градиентов.
  • Обновляет все параметры с помощью Adam с линейным затуханием скорости обучения.

6. Генерация (инференс)

После обучения модель может генерировать новые имена:

  • Начинает с токена BOS.
  • На каждом шаге предсказывает логиты для текущего контекста, применяет температуру (temperature=0.5), преобразует в вероятности и семплирует следующий токен.
  • Генерация продолжается до достижения BOS или предела длины контекста.

Что это даёт для понимания deep‑learn GPT техник?

  1. Прозрачность — каждый этап описан в 200 строках кода, без «магии» фреймворков.
  2. Практическое понимание автограда — видно, как градиенты накапливаются и распространяются через вычислительный граф.
  3. Ясность архитектуры трансформера — внимание, остаточные связи, нормализация, MLP показаны в явном виде.
  4. Полный цикл «обучение–генерация» — от инициализации весов до синтеза новых последовательностей.
  5. Возможность экспериментировать — можно менять гиперпараметры (n_layer, n_embd, n_head), пробовать другие датасеты, регулировать температуру, добавлять регуляризацию и т.д.

Заключение

microgpt.py — не «секретный алгоритм», а образовательный шедевр, который демонстрирует суть GPT в минимальном, самодостаточном виде. Изучив его, вы не только поймёте, как работают современные языковые модели, но и получите инструмент для собственных экспериментов.

«Всё остальное — просто эффективность». — @karpathy

Ссылки:

Статья создана автоматически на основе анализа кода в репозитории.