Перейти к основному содержимому

Устройство трансформеров — теория и практика с нуля

Разработчику Инженеру

Play ITЗагрузка интерактивного демо…

Промышленные модели (GPT, BERT) содержат миллиарды параметров и оптимизации (FlashAttention, fused kernels). Для понимания достаточно собрать один encoder block на PyTorch — scaled dot-product attention, multi-head обёртка, FFN, residual и LayerNorm.

Предполагается базовое знакомство с PyTorch и нейроном. Теория attention — предыдущая статья.


Каркас учебной модели

Упростим задачу:

  • фиксированная длина последовательности seq_len;
  • словарь размером vocab_size;
  • один encoder layer (без полного стека и без decoder);
  • обучаемые positional embeddings.

Полный Transformer из статьи 2017 года — стек из $N$ таких блоков + выходная проекция.


Scaled dot-product attention

Код ITЗагрузка примера кода…

Mask с shape (batch, 1, seq_len, seq_len) обнуляет запрещённые позиции. Для encoder на классификации mask часто не нужен. Для decoder (GPT) — нижний треугольник (causal mask).


Multi-head attention

Код ITЗагрузка примера кода…


Position-wise FFN

Два линейных слоя с расширением (обычно d_ff = 4 * d_model):

class PositionwiseFFN(nn.Module):
def __init__(self, d_model, d_ff, dropout=0.1):
super().__init__()
self.net = nn.Sequential(
nn.Linear(d_model, d_ff),
nn.GELU(),
nn.Dropout(dropout),
nn.Linear(d_ff, d_model),
)

def forward(self, x):
return self.net(x)

Encoder block

Post-LN (как в оригинальной статье) — нормализация после residual:

Код ITЗагрузка примера кода…

Современные модели (GPT-2, некоторые LLM) часто используют Pre-LN (нормализация перед подблоком) — стабильнее при большой глубине.


Мини-модель для классификации

Код ITЗагрузка примера кода…

Для обучения нужны input_ids, метки классов, CrossEntropyLoss и AdamW. На CPU учебная модель на сотнях примеров сходится за минуты — удобно для эксперимента с attention weights.


Causal mask для decoder

GPT-стиль — нижний треугольник единиц:

def causal_mask(seq_len, device):
return torch.tril(torch.ones(seq_len, seq_len, device=device)).unsqueeze(0).unsqueeze(0)

Применяют в self-attention декодера, чтобы позиция $i$ видела только $0..i$.


Что добавляют "боевые" реализации

КомпонентЗачем
KV cacheПри генерации не пересчитывать K/V для старых токенов
FlashAttentionМеньше памяти и быстрее attention на GPU
RoPE / ALiBiПозиционная информация для длинного контекста
Gradient checkpointingЭкономия VRAM при обучении
Mixed precision (fp16/bf16)Скорость и объём модели

Готовые стеки — Hugging Face transformers, Keras. С нуля имеет смысл один раз для обучения; в проде — проверенная библиотека.

Упражнение

Обучите TinyTransformerClassifier на бинарной классификации (например, RuSentiment с урезанным словарём). Сравните с TF-IDF + LogisticRegression из Scikit-learn — разница в F1 покажет выигрыш контекстуальных эмбеддингов.


Дальше