Вы когда-нибудь задумывались, почему все гайды по обучению LLM заканчиваются на этапе "возьмите 256 H100 и подождите месяц"? Я тоже. И однажды решил пойти другим путём: обучить 7B модель с нуля, используя архитектуру DeepSeek, на двух обычных GPU (NVIDIA RTX 6000 Ada с 48 ГБ каждая). Спойлер: это сработало, но пришлось изрядно попотеть. Если вы хотите повторить этот путь — добро пожаловать под кат. Здесь нет волшебных таблеток, только кровь, пот и несколько терабайт логов.
Но сначала отвечу на вопрос, который вы, скорее всего, задаёте: "Зачем обучать LLM с нуля, если есть LLaMA, Mistral, Qwen?". Ответ прост: контроль. Контроль над архитектурой, данными, процессом обучения и, главное, над пониманием. Когда вы сами собрали модель, вы точно знаете, какие у неё слабые места и как их чинить. Это не про "запустить инференс", а про глубокое погружение. Если вам нужно просто запустить готовую модель — почитайте наш гайд по локальному запуску LLM. Но если вы готовы к настоящему инженерному приключению — поехали.
Почему DeepSeek, а не LLaMA?
Архитектура DeepSeek (особенно DeepSeekMoE) — это не просто очередной трансформер. Это MoE (Mixture of Experts) с 64 экспертами и top-2 routing. То есть каждый токен активирует только 2 эксперта из 64. На практике это означает, что при 7B параметров всего (сумма всех экспертов + shared layers), во время инференса и обучения используется лишь ~10-15% параметров. Это даёт колоссальную экономию VRAM и FLOPs. По сравнению с плотной моделью LLaMA-7B, DeepSeekMoE-7B может обучаться в 2-3 раза быстрее при том же бюджете памяти.
Мы выбрали DeepSeekMoE с 64 экспертами, размерностью d_model=2048, hidden_dim=5632, num_layers=24. Каждый эксперт — это FFN с активацией SwiGLU. Это классика, но с одним нюансом: мы использовали shared experts (общие эксперты) и routed experts. Shared expert обрабатывает все токены, routed — только часть. Это позволяет модели сохранять общие знания, а routed специализируются на подзадачах.
💡 Почему 64 эксперта, а не 8 или 16? Эмпирически DeepSeek показал, что большее количество мелких экспертов улучшает качество при том же количестве активных параметров. Но увеличивает overhead на routing. Мы остановились на 64 — золотая середина.
Железо: две карты и ни одного дата-центра
Мы использовали две NVIDIA RTX 6000 Ada (48 ГБ каждая, 96 ГБ суммарно). Это не H100, но зато они помещаются в обычный ПК. Вопрос: как обучить 7B модель (веса в bf16 занимают ~14 ГБ, но с экспертами и оптимизатором память растёт) на 96 ГБ? Ответ: агрессивная оптимизация VRAM.
Если вы собираете станцию специально для таких задач — взгляните на наш гайд по сборке станции за $15 000. Там много полезного про выбор карт, NVLink и охлаждение. Мы же работали на двух картах без NVLink (PCIe 4.0 x16), что добавляло latency, но для pretrain это не критично.
Pretrain: как не умереть в первый же день
1 Датасет и токенизация
Мы собрали корпус из 150B токенов: смесь The Pile (английский), русскоязычных датасетов (Saiga, cleaned web), и синтетических данных для кода. Токенизатор использовали собственный на основе Byte-Pair Encoding с размером словаря 50 258. Почему не использовать готовый, например, от LLaMA? Потому что мы хотели контролировать coverage русского языка. Стандартный токенизатор LLaMA плохо справляется с кириллицей, что приводит к лишним токенам и падению скорости.
Совет: потратьте время на токенизатор. Плохой токенизатор — это убитая эффективность. Мы обучили свой на 10B токенов из нашего корпуса, используя byte-level-bpe с пост-регуляризацией. Результат — среднее количество токенов на слово уменьшилось на 20% по сравнению с LLaMA tokenizer.
2 Архитектура и подготовка кода
Мы написали модель на PyTorch 2.5 с использованием torch.compile и FlashAttention-3. Для распределённого обучения — DeepSpeed ZeRO-3 с offloading optimizer states на CPU. Это стандарт, но с MoE есть нюансы: нужно правильно настроить routing и load balancing. DeepSpeed поддерживает MoE (Mixture of Experts), но мы использовали собственную реализацию на tutel от Microsoft — она быстрее и гибче.
Ключевая конфигурация DeepSpeed для MoE:
{
"zero_optimization": {
"stage": 3,
"offload_optimizer": {
"device": "cpu",
"pin_memory": true
},
"overlap_comm": true,
"contiguous_gradients": true
},
"moe": {
"enabled": true,
"num_experts": 64,
"topk": 2,
"capacity_factor": 1.5,
"min_capacity": 4
}
}
Capacity factor 1.5 — это небольшой overbooking, чтобы не терять токены при дисбалансе экспертов. Без него часть токенов просто дропается, и качество страдает.
3 Оптимизатор: muon вместо AdamW
Традиционный AdamW требует памяти на momentum и variance (2 дополнительных буфера на параметр). Для 7B это ~14 ГБ дополнительно. Muon-оптимизатор, предложенный в 2024 году, использует разложение по Ньютону-Шульцу и требует только одного буфера. Экономия памяти — до 30% на оптимизаторе. Но главное — muon даёт лучшее качество сходимости на разреженных моделях (MoE). Мы взяли реализацию из авторского репозитория и адаптировали под bf16.
Muon требует настройки learning rate и weight decay. Мы использовали cosine schedule с lr=3e-4, warmup 2000 шагов, batch size 256K токенов (micro batch 4K на GPU, gradient accumulation 32).
⚠️ Осторожно: Muon чувствителен к нормализации градиентов. При первом запуске мы получили NaN через 50 шагов из-за неправильной инициализации. Пришлось добавить gradient clipping (max_norm=1.0) и использовать специальную версию muon с стабилизацией (GUM — Gradient Update Method). GUM просто масштабирует обновление в зависимости от нормы градиента, предотвращая взрывы.
4 Оптимизация VRAM: выжимаем каждый гигабайт
Даже с ZeRO-3 и offloading, 7B MoE модель не влезала в 96 ГБ при batch size больше 2. Вот что мы сделали:
- Activation checkpointing: сохраняем активации не для всех слоёв, а для каждого второго. Экономит ~40% памяти, замедление всего 15%.
- Sequence parallelism: разбиваем длинные последовательности (2048 токенов) на чанки по 512, обрабатываем их на разных GPU с последующей синхронизацией. Это позволило увеличить эффективный batch без роста пиковой памяти.
- Mixed precision bf16/fp32: все веса и активации в bf16, master weights в fp32 (только для оптимизатора). Muon работает стабильно в bf16.
- Offloading экспертов: неиспользуемые эксперты (те, что не выбраны top-2) выгружаются на CPU. Поскольку каждый эксперт — это отдельный FFN, их можно перемещать независимо. DeepSpeed MoE изначально это поддерживает.
После всех ухищрений мы смогли уместить micro batch 4K токенов на карту. Градиентный аккумулятор 32 шага давал эффективный batch 256K токенов. Pretrain длился 2.5 недели (480K шагов).
RLHF: от pretrain к полезному ассистенту
После pretrain модель умеет генерировать текст, но не умеет отвечать на вопросы. Нужно fine-tune с RL (Reinforcement Learning from Human Feedback). Мы использовали комбинацию PPO и GRPO (Group Relative Policy Optimization), которую DeepSeek применил в DeepSeek-Math. GRPO не требует critic model, что экономит ещё одну модель. Но мы всё равно обучили reward model на основе нашего DeepSeekMoE (6 экспертов, shared layers frozen).
Конвейер RLHF:
- SFT (Supervised Fine-Tuning) на 50K диалогов (чат-формат).
- Обучение reward model на парных сравнениях (20K ответов).
- PPO/GRPO: генерация ответов, вычисление reward, обновление policy.
Из-за ограничений VRAM мы использовали off-policy PPO с реплеем размера 512. Каждый шаг PPO генерировал 4 ответа на промпт, мы брали средний reward. GRPO оказался стабильнее: он усредняет reward по группе ответов и не требует отдельного value head.
Важный нюанс: при RLHF с MoE routing начинает схлопываться — все эксперты предпочитают отвечать одинаково, и нагрузка на эксперты становится неравномерной. Мы добавили дополнительный auxiliary loss на load balancing (как в Switch Transformer). Коэффициент 0.01. Без этого loss модель деградировала до плотной.
Результат RLHF: модель научилась отвечать связно, хотя и не дотягивает до LLaMA-7B-chat. Но мы потратили $2000 на аренду GPU (облако) против $60K за обучение LLaMA. Абсолютное качество хуже на 15% по GSM8K и MMLU, но для кастомных задач (например, русскоязычный support-бот) этого достаточно.
Ошибки, которые мы совершили (чтобы вы их не повторяли)
- Неверный capacity factor. Начали с 1.0 — теряли 40% токенов. Пришлось повысить до 1.5, затем до 2.0. Слишком большой capacity увеличивает FLOPs, но без потерь.
- Экономия на валидации. Мы не отслеживали PPL на валидационном сете первые 50K шагов — в результате модель заучила шум. Пришлось перезапускать.
- Игнорирование квантования во время инференса. На этапе RLHF мы генерировали ответы в fp16. Ускорили бы генерацию в 2 раза, если бы использовали 4-битное квантование для reward модели.
- Забыли про gradient checkpointing для reward модели. Reward модель висела в памяти и мешала. Пришлось выгружать её на CPU между шагами.
Что дальше?
Сейчас мы дообучаем модель на синтетических данных с помощью метода дублирования слоёв (о котором писали в статье про улучшение LLM без изменения весов). Это выглядит как хардкод, но даёт прирост на 2-3% на Open LLM Leaderboard без переобучения.
И самое главное — мы поняли, что обучение LLM с нуля на двух GPU это реально. Да, это не H100, но с правильными оптимизациями (MoE, muon, offloading) можно получить рабочую модель за адекватные деньги. Если у вас есть 2 GPU по 48 ГБ или даже одна 80 ГБ (A100) — вы можете повторить. А если бюджет меньше, обратите внимание на MaximusLLM для одного T4.
Удачного обучения! И помните: если ваш эксперимент сгорел на второй день — это нормально. У нас он горел трижды.
FAQ по созданию LLM с нуля
Сколько времени занимает pretrain 7B MoE модели?
При использовании двух RTX 6000 Ada (96 ГБ) и batch size 256K токенов — около 2.5 недель на 150B токенов. С одной картой (48 ГБ) — примерно 6 недель, если уменьшить batch. С H100 (80 ГБ) — около 4 дней.
Какой оптимизатор лучше: muon или AdamW?
Muon экономит память и часто даёт лучшее качество на MoE, но требует осторожной настройки (clipping, GUM). AdamW надёжнее, но ест больше VRAM. Мы советуем muon, если объём памяти критичен.
Можно ли обучать модель с архитектурой DeepSeek на одной видеокарте?
Да, но с меньшим batch size и агрессивным offloading. Для 7B MoE на одной 24 ГБ карте это практически невозможно. Нужно хотя бы 48 ГБ. Альтернатива — использовать квантование во время обучения (например, QLoRA), но это уже не будет обучением с нуля.
RLHF с GRPO требует меньше памяти, чем PPO?
Да, GRPO не использует critic model, что уменьшает пиковую память на 20-30%. Кроме того, GRPO стабильнее при малом batch size. Мы рекомендуем GRPO для ограниченных ресурсов.