Scaling Laws и токенизация
Chinchilla, overtraining, BPE, vocab size trade-offs, LR schedules.
Scaling Laws и токенизация: сколько данных нужно модели?
Два вечных вопроса LLM-инженера: насколько жирной делать модель и сколько данных ей скормить? Scaling laws дают математический ответ — чтобы ты не гадал на кофейной гуще. А токенизация определяет, как модель "видит" текст — и это влияет буквально на всё.
Бюджет вычислений: C ≈ 6·N·D
Вычислительный бюджет обучения LLM — удивительно простая штука. FLOPs ≈ 6 × параметры × токены. Шестёрка — это эмпирика: forward pass + backward pass ≈ 6 операций на параметр на токен. Вот и вся магия.
C — FLOPs (вычисления), N — параметры модели, D — число токенов обучения
Chinchilla Scaling Laws
До 2022 года все были одержимы размером модели. "Больше параметров = умнее", думали они. GPT-3 (175B параметров) обучали на жалких 300B токенов. Потом пришёл Chinchilla (DeepMind, 2022) и всех отрезвил: данные так же важны, как параметры. По Chinchilla, GPT-3 нужно было 3.7 триллиона токенов — в 12 раз больше! OpenAI, по сути, недокормили свою модель.
📊 Chinchilla rule
Overtraining: почему лабы нарушают scaling laws
Но вот фишка: современные лабы сознательно забивают на Chinchilla и перетренируют модели далеко за оптимум. Почему? Потому что маленькая модель, обученная дольше, стоит копейки при инференсе. SmolLM3 (3B параметров) обучен на 11T токенов — в 18 раз больше рекомендации Chinchilla. Kimi K2 (1T) — на 15.5T. Qwen 3 — на 36T. Overtraining — это не ошибка, это стратегия.
- GPT-3: 175B params, 300B tokens — сильно undertrained по современным стандартам
- SmolLM3: 3B params, 11T tokens — overtraining ×18 для дешёвого инференса
- Kimi K2: 1T params (MoE), 15.5T tokens
- Qwen 3: 36T tokens — рекорд по объёму данных
# Прикинем compute для обучения модели
def estimate_flops(n_params: float, n_tokens: float) -> float:
"""C ≈ 6 * N * D — грубая оценка FLOPs для обучения."""
return 6 * n_params * n_tokens
# GPT-3: 175B params × 300B tokens (undertrained!)
gpt3_flops = estimate_flops(175e9, 300e9) # ~3.15e23 FLOPs
# Chinchilla optimal для того же compute: N ≈ D
# sqrt(C/6) ≈ 7.2e11 → ~72B params, ~720B tokens
chinchilla_n = (gpt3_flops / 6) ** 0.5 # ~72B params
chinchilla_d = chinchilla_n # ~72B tokens — столько же
# SmolLM3: 3B params, 11T tokens — overtraining ×18
smol_flops = estimate_flops(3e9, 11e12) # ~1.98e23 FLOPs
chinchilla_optimal_tokens = 3e9 # по Chinchilla надо было 3B × 20 = 60B
overtraining_ratio = 11e12 / (3e9 * 20) # ×18 — осознанный выбор
# Сколько GPU-часов? A100 = 312 TFLOPS (bfloat16 с utilization ~50%)
gpu_hours = smol_flops / (312e12 * 0.5) / 3600
print(f"SmolLM3: ~{gpu_hours/1000:.0f}K A100-часов")Batch size и learning rate
Увеличил batch size в k раз? Learning rate масштабируй как √k. Интуиция простая: больший batch = более стабильные градиенты (меньше шума), значит можно делать шаги покрупнее. Ещё нюанс: critical batch size растёт по ходу тренировки — в начале модель учится быстро и шумно, потом успокаивается.
При увеличении batch size B в k раз, learning rate η масштабируется как √k для сохранения variance обновлений
Learning Rate Schedules
Learning rate живёт по расписанию: сначала warmup (1-5% шагов) — мягко разгоняемся, потом decay — плавно тормозим. Три популярных варианта:
- Cosine annealing — классика, плавный спад. Минус: нужно заранее знать число шагов
- WSD (Warmup-Stable-Decay) — warmup → плато → линейный спад в конце (10-20%). Гибче: можно менять длину обучения. SmolLM3 и Kimi K2 используют WSD
- Multi-step — warmup → плато → дискретные дропы (80/10/10 или 70/15/15). DeepSeek-v3 использует вариант с cosine между дропами
💡 На практике
Токенизация: vocab size и fertility
Алгоритм BPE (Byte-Pair Encoding) мы подробно разобрали в ноде «Seq2Seq и Attention» — начинаем с байтов, итеративно склеиваем самые частые пары. Тут фокус на другом: какой размер словаря выбрать и как это влияет на качество и скорость.
- Vocab size: 50K для English-only, 100K+ для multilingual. GPT-4: o200k, Llama 3: cl_100k
- Больше vocab → меньше токенов → быстрее инференс + меньше KV cache. Но больше embedding матрица
- Fertility — среднее число токенов на слово. Меньше = эффективнее. Русский текст: GPT-2 ~2.5 tok/word, Llama 3 ~1.8
- Для математики: single-digit splitting (каждая цифра = токен). Llama 3: числа 1-999 как отдельные токены
from transformers import AutoTokenizer
# Сравним токенизацию разных моделей
tokenizers = {
"GPT-4 (o200k)": AutoTokenizer.from_pretrained("openai-community/gpt2"),
"Llama 3 (128k)": AutoTokenizer.from_pretrained("meta-llama/Meta-Llama-3-8B"),
}
text = "Рекомендательная система предсказывает P(click|user, item)"
for name, tok in tokenizers.items():
tokens = tok.encode(text)
print(f"{name}: {len(tokens)} токенов")
print(f" Токены: {[tok.decode([t]) for t in tokens[:8]]}...")
# Fertility (токенов на слово) — ключевая метрика для multilingual
# Русский текст: GPT-2 ~2.5 токена/слово, Llama 3 ~1.8
words = text.split()
for name, tok in tokenizers.items():
fertility = len(tok.encode(text)) / len(words)
print(f"{name}: fertility = {fertility:.2f}")⚖️ Vocab size tradeoff
Ключевые выводы
- C ≈ 6·N·D — простая формула бюджета вычислений
- Chinchilla: данные так же важны, как параметры. Но лабы осознанно перетренируют ради дешёвого инференса
- LR масштабируется как √batch_size. WSD — гибкий schedule для продакшена
- BPE — стандарт токенизации. Vocab size зависит от модели и языков
- Scaling laws — ориентир, а не закон. Реальные решения учитывают inference cost, доступные данные и целевые задачи