Устройство трансформеров — теория и практика с нуля
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 покажет выигрыш контекстуальных эмбеддингов.