
Раскрученный проект nanochat обещает "за $100 обучите свой ChatGPT". В оригинале обучение на 8xH100 80Gb, но никто не мешает обучить его на домашнем и более слабом железе. Попробуем обучить LLM с нуля на статьях Хабра, чтобы посмотреть хватит ли там материала, чтобы модель хотя бы смогла связать пару слов.
Этапы обучения LLM с нуля
Классические этапы обучения LLM:
pretrain - это base модель. Дают неразмеченный сырой текст, модель учится продолжать.
SFT - это instruct модель. Дают качественный, размеченный датасет.
RL, DPO - выравнивание модели, датасет с парами хороший-плохой ответ.
Обучение с нуля начинается со случайных параметров, на вход необученной модели подается неразмеченный текст и модель шаг за шагом пытается предсказать следующие токены на основе предыдущего контекста. Вначале модель осваивает простые паттерны, такие как орфография и пунктуация, после начинается выявление более сложных связей, где происходит аппроксимация не только коротких связей, но и полных документов, например, идея которая озвучена в 1 главе получает развитие в 3 главе, и такие длинные связи тоже начинают выявляться.
Цель настроить параметры так, чтобы модель могла уверенно продолжать текст, где начало, середина и конец связаны друг с другом. Упрощенно можно на это посмотреть так, из случайного распределения параметров начинают проявляться структуры, эти структуры означают, что паттерны найдены и знание усвоено:

Анимация упрощенного процесса подбора параметров модели

Модель работает с токенами. Слова, перед тем как попадут в модель, разбиваются на токены, токены в свою очередь преобразуются в вектора, эти вектора можно назвать как "вектора сути". Такие вектора тоже обучаются, и после обучения начинают передавать смысл слова.
То, что имеет похожие смыслы или близкие сущности - они начинают располагаться всё ближе и ближе друг к другу в многомерном пространстве, формируя кластер семантической близости. Чем лучше обучена нейросеть, тем точнее будет их расположение в таком многомерном пространстве с огромной размерностью (размерность от 512 до 8192 и более). Это называют эмбеддингами.

Эмбеддинги несут суть слова в многомерном пространстве, а не само слово, и так как это вектора, то с ними можно проводить различные операции через геометрию пространства.
Например, есть Вектора "Король", "Мужчина", "Женщина". Каждый вектор содержит в себе какую-то определённую суть:
Вектор("Король") = [Мужчина] + [Монарх]Вектор("Мужчина") = [Мужчина] + [Человек]Вектор("Женщина") = [Женщина] + [Человек]
Если из Вектор("Король") вычесть Вектор("Мужчина"), получится чистый признак [Монарх]
Если пока нет готового понятия, его можно создавать:
Вектор("Король") - Вектор("Мужчина") + Вектор("Женщина") = Вектор("Королева")
По сути работа нейросети заключается в том, чтобы перемножать эмбеддинги с векторами положений слова, вычислять значимость слова в контексте, создавая новые вектора, новые вектора прогоняются дальше слой за слоем, всё усложняя признаки.
На выходе нейросети вычисленные вероятности для всех токенов нейросети, количество вероятностей равно vocab_size, обычно от 32к до 256к, но большинство их них будут иметь значение ниже 0.01 и только top-k токенов будут иметь какую-то значимость.
Нейросеть не выбирает какой токен из предложенных выбрать. Выбором занимается внешний от нейросети процесс - семплинг. Семплинг это не интеллектуальная сущность, тут нет накопленной статистики, нет обучения, и он предназначен чтобы добавить случайности и разнообразия в ответ, это делает модель более интересной, но выбор неудачного токена может увести даже большую модель в ошибочное направление.
Можно выделить основные параметры семплирования:
Greedy (Жадный поиск) - всегда берется самый вероятный токен, самый первый.
Top-K - отсекает хвосты, оставляя только N верхних по вероятности токенов.
Top-P - оставляет токены, пока их сумма вероятностей не достигает порога.
Temperature - масштабирует логиты до softmax, сглаживает или заостряет распределение.

Когда pretrain создан, он умеет только продолжать фразы и нужно научить его следовать инструкциям. Модели показывают как выглядят инструкции, шаблон, структуру, служебные токены для разделения user и assistant, чтобы модель могла правильно отделять свои ответы от запросов пользователя.
Всё это делается на основе множества размеченных примеров, из которых будут выявляться паттерны. Происходит процесс подбора параметров так, чтобы шаблон сходился.

После того как модель научилась следовать шаблону, можно её дополнительно настроить или выровнять, усилить сигнал хороших ответов и ослабить у плохих. Для этого нужен датасет где будет пара хороший-плохой ответы, и по ходу дообучения расхождение между этими парами должно усиливаться.

Nanochat, закон Шиншиллы, PLE, домашние GPU, win vs linux
Обучать будем на nanochat, это позволит создать современную LLM без погружения в конфигурации, настройки, подбор параметров обучения.
Nanochat от Andrej Karpathy построен по принципу "укажите 1 параметр, остальные будут подобраны автоматически" - нужно указать depth или количество слоев трансформера. Остальные параметры будут подобраны согласно закону Шиншиллы.
В nanochat свежие подходы к обучению, вместо AdamW используют гибрид с новым эффективным Muon, вместо GELU более качественный SwiGLU, пробуют различные новые архитектурные решения вроде PLE, обучение в fp8, компиляция torch.compile triton ядер для ускорения в 2 раза и т.д.
Возможно, вместо adamw+muon можно перейти на новый оптимизатор gefen, который заявляет, что можно сэкономить до x8 памяти: https://github.com/ndvbd/Gefen
Что такое PLE?
Размер модели d16 составляет 0.5B, но эффективных ~0.25B, остальное это PLE.
Архитектура PLE (Per-Layer Embeddings), это к каждому, или через один, слою добавляется слои эмбеддингов, которые по сути является ассоциативной памятью. Этот слой обучают вместе с моделью, но он почти не требует FLOPs ни на обучение, ни на инференс. Идея в чем-то похожа на MoE, только тут получается статичный слой PLE, который увеличивает емкость данных у модели в 2 раза, не тратя ресурсы на вычисления.
В Gemma4 есть 2 модели E2B и E4B, которые работают на этой архитектуре. В теории Gemma4 E4B обучается и запускается как 4B модель, но работает как "умная" 8B модель.
Что такое закон Шиншиллы?
Исследователи из DeepMind в 2022 году представили работу Chinchilla Scaling Laws (Закон Шиншиллы), в которой вывели эмпирические правила, что на 1 параметр модели нужно 20-25 токенов обучения. Так же они внесли корректировки в Warmup и пиковый LR.
В nanochat из этого scaling laws исключаются эмбеддинги, поэтому в nanochat, где эмбединги PLE занимают почти половину модели, Chinchilla ratio составляет 12. Другие параметры будут вычислены на основе этих факторов.
Например, вычисление общего размера батча:
Где B - оптимальный размер батча, а D - размер датасета. Степень 0.383 тоже выведена эмпирически DeepMind и OpenAI, отвечающая на вопрос как сильно надо увеличить размер батча, если увеличивается объем датасета, чтобы обучение шло оптимально.
Для d16 размер батча оптимален в 512к, для d24 будет 1кк. Вместить такой размер физически на GPU тяжело, чтобы это компенсировать используют Gradient accumulation.
На домашнем GPU физический размер батча будет где-то в диапазоне 4-16, но за счет накапливания через Gradient accumulation, итоговый батч будет иметь нужный размер. И математически это почти равнозначно физическому батчу.
5090 это урезанный Blackwell, поэтому поддержки fa3 нет
Nanochat рассчитан на работу с серверными картами уровня H100 и выше, потому что тут используется flash-attention 3, который ускоряет обучение и тратит меньше памяти. FA3 работает на архитектурах Blackwell и Hopper.
Я буду обучать на 5090, и это как раз архитектура Blackwell, но в ходе обучения возникла первая проблема, расход памяти был слишком большой, и снижалась скорость обучения, MFU показывал не эффективное использование карты.
Проблема в том, что в nanochat используется скользящее окно внимания SSSL (S - 1/4 от полного внимания, L - полное), это ускоряет обучение и экономит память. SSSL эффективно только в fa3, для этого паттерна нужно оптимально маскировать урезанное внимание, чтобы не тратить полную память и вычисления на операция с такими слоями.
Изучение вопроса как работает FA3 привело к тому, что тут нужны физические блоки тензорной памяти TMEM, если их нет, будет откат на старые регистры HMMA (уровень Volta/Ampere), которые не могут оптимально работать с SSSL и тратят лишнюю память и время на обработку, что приводит к тому, что скорость обучения падает. Оказалось, что TMEM физически присутствует только в корпоративном сегменте Blackwell, на картах типа B200, на домашних картах этих блоков нет. Подробнее про fa3 и отсутствие TMEM на 5090: https://gist.github.com/solatticus/aab6ec3a0436748b021cbbdd12e8c739
В итоге на домашних GPU придется откатиться на SDPA, где под капотом используется FA2 (в Linux, под Windows скорее всего придется установить fa2 вручную), который не может нормально работать с SSSL. FA2 это тоже быстро, но не так эффективно как FA3/FA4, и придётся переключиться на полный L.
Возможно, есть какой-то эффективный способ обучать со скользящим окном внимания на потребительских GPU, вроде FlexAttention. Ещё какая-то работа представлена тут: https://github.com/MaxLSB/flash-attn2
Обучение на Windows или на Linux
Под Windows нужно установить pip install triton-windows - это позволит запустить обучение и скомпилировать triton ядра, но вопрос скорости остается открытым.
Под Linux скорость обучения выше, чем под Windows. В чем именно проблема, не понятно. Возможно проблема моей сборки, возможно медленный fa2 под Windows, или из-за Win10, а на Win11 будет нормально.
Под Windows скорость 85к t/s:

Утилизация GPU 100%, что с учетом скорости, не эффективно:

Под Linux 132к t/s, на ~60% выше при той же утилизации 100%:

В обоих случаях nvidia-smi -i 0 -pl 450, чтобы GPU оставалась тихой во время работы, это снижает эффективность всего на ~7%, но шум вентиляторов тише в 2 раза.

Обучение. Токенизатор
Обучение начинается с обучения токенизатора. В качестве датасета IlyaGusev/habr.
Обучение токенизатора проходит на тех же статьях, он ищет зависимости языка, выявляет частые слоги, корни слов, различные сочетания символов, создает словарь, чтобы эффективно сжимать русский текст в токены.

После обучения токенизатора, можно подсчитать точное число токенов Хабра, получилось на 302к статей всего 508M токенов.

Комментарии это ещё +0.6B. Но их не будем учитывать, так как обучение на статьях, хотя комментарии могли бы внести живости в общение модели и расширить её знания.

Обучение pretrain. Параметры d16
Скрипт обучения рассчитан на 80Гб VRAM, по умолчанию batch-size равен 32, чтобы влезть в меньший объем VRAM, нужно его снизить. Если памяти совсем не хватает, можно включить Gradient checkpointing, который кардинально снижает расход памяти за счёт скорости.
Обучать будем в fp8, размер d16, для размера 0.5B нужен датасет в 6-10B, у нас есть только 508M. Вместо SSSL используем L, сохраняем чекпоинт каждые 500 шагов, размер физического батча 16 или меньше, чтобы влезало в VRAM.
python -m scripts.base_train --depth=16 --fp8 --window-pattern L --save-every=500 --device-batch-size 16
После запуска, скрипт произведет все необходимые расчёты по автоматическому выставлению параметров. Размер d16 составляет 0.5B (размер PLE указан как value_embeds и составляет 0.25B, размер матриц трансформера 0.19B и общий размер 0.5B), суммарный размер батча 512к, количество голов внимания 8.
С учетом Закона Шиншиллы и PLE скрипт рассчитал, что для d16 нужно 2.8B токенов, чтобы достигнуть это число обучение будет в несколько эпох, пока не будет пройдено заданное количество токенов. Из-за множества эпох возможно переобучение (overfitting).

Малый размер датасета и BOS-aligned best-fit packing
По умолчанию в nanochat максимальная длина последовательности 2048 токенов. Но я выставил её в 512, чтобы сэкономить память, и тут же столкнулся с первой проблемой обучения.
Обучение шло не плохо, loss уверенно снижался, но эпохи слишком быстро сменяли друг друга.
По расчётам должно было быть 5.5 эпох, но первые эпохи прошли слишком быстро, а потом пошли эпохи 6, 7, 8, чего быть не должно. Вернувшись к анализу кода, и внимательнее посмотрев на предупреждение в файле dataloader.py о том, что "Original Streams tokens" отключен, теперь вместо него BOS-aligned bestfit который "~35% tokens cropped at T=2048", стало понятно, что датасет кропается по какому-то алгоритму.
Старый способ создавал плоский буфер токенов из 100% датасета, который шли друг за другом, в таком режиме обрезки старой статьи попадали в новую, получалось много шумных данных. Вместо этого новый алгоритм ищет статьи которые влезают в заданную последовательность, если таких нет, берутся длинные и обрезаются, обрезки выбрасываются.
При bestfit модель видит более чистые данные, каждое начало это BOS токен и начало документа, структура и весь контекст статьи в одном месте. Но при размере контекста в 512 токенов, хвосты выбрасываются и это составляют львиную долю датасета.
В итоге в обучение попало только 170M вместо 508M при ctx 512.
Обучаем pretrain. 1 попытка. Контекст 2048
Вернемся к стандартному значению в 2048. При таком варианте из датасете берется 370M. Потери в районе обещанных 35%, поэтому попробуем обучить так.
Численным показателем хода обучения выступает функция потерь cross-entropy loss. Модель выдает распределение вероятностей по всему словарю, настоящий следующий токен известен из обучающих данных, и кросс-энтропия измеряет расстояние между тем, что выдает модель и тем, что должно быть. На первых шагах loss максимальный и вычисляется как натуральный логарифм от размера словаря, в нашем случае это 32к, все 32к токенов имеют равную вероятность.
Базовые паттерны будут очень быстро усваивается, поэтому дойти до loss 6 будет просто, в районе 3 будут усвоены все основные принципы языка, орфография, пунктуация, опуститься ниже 3 будет сложно, так как там будут выявляться уже какие-то конкретные факты, тонкости.
Размер d16, fp8, 5090, датасет 370M с BOS bestfit, целевое количество токенов 2.8B, ожидаемое время обучения 6 часов. Размер контекста в 2048, хвосты длинных статей обрезаются, 63% датасета. Обучение потребует ~9 эпох.

loss 10.39. Шаг 1. Loss совпадает с расчётным, все 32к токена равновероятны при выборе моделью. Посмотрим как это выглядит.
Токены просто хаотично слипаются, есть какие-то слова, но это либо случайность, либо целый токен слова, текст представляет собой неразборчивое месиво:

loss 6. Шаг 40. Происходит быстрое снижение с 10 до 6. Базовые паттерны языка выявляются, смысла в фразах нет, но теперь это уже не мешанина токенов:

loss 3.3. Шаг 500. Примерно 10% обучения, эпоха ещё не пройдена. До loss 3 добраться просто, нейросеть быстро аппроксимирует язык и PPL равняется 20, у модели есть 20 вариантов следующих токенов, которые она считает подходящими.

PPL 20 означает, что ответы уже начинают походить на настоящие, модель выучила частоту токенов, простые сочетания, базовую грамматику, в фразах начинает проявляться смысл:

loss 2.6. Шаг 3000. 55% обучения. 2 эпохи. Опуститься ниже loss 3 занимает много времени.
Тут можно заметить bpb 0.56, который я пока не учитываю.

loss ниже 3 изучает семантические связи, длинные зависимости, набор фактических знаний. PPL опустился до 13, текст становится более связным:

loss 1.8. Шаг 5376. bpb 0.7, 9 эпох. Пройдено 2.8B токенов, цель достигнута.

Проверка pretrain 1. Первая проблема обучения на fp8
Можно посмотреть какие паттерны удалось выявить.
В целом текст получается связным, ответ по промпту, орфография соблюдена. Модель пытается что-то выжать и придумать какой-то ответ, даже если ей не известно ничего:

Проверим, как модель усвоила тонкости языка. Если начать как мужской, то модель продолжает писать в мужском роде, если начать как женский, то модель следует этому:

Списки стандартный, буквенный, римский и ненумерованный. У модели не получилось аппроксимировать этот навык:

И это первое проявление проблемы fp8 против bf16. Точнее их было больше, но модель постепенно, но не идеально, выправляла их по ходу обучения.
Для сравнения fp8 vs bf16 пример старого чекпоинта d16, который обучался только на статьях Хабра, но обучался в bf16. Такой чекпоинт не только вывел как правильно составлять все варианты списков, но и усвоил последовательность планет до Марса:

Но в целом pretrain обучился и в fp8, и возможно ему просто не хватило токенов.
pretrain. 2 попытка. Попробуем контекст в 8192
Чтобы увеличить количество токенов, и прежде чем отказываться от BOS bestfit, попробуем обучить модель в 8192. Это увеличивает до 450M токенов, примерно 85%.
Обучать сразу в 8192 не рекомендуется, так как стабильность хуже, матрица внимания слишком большая на первых шагах из-за чего сходимость будет плохая.
Скорость обучения просела в 2 раза (и дополнительно от того, что под Win10):

На 500 шагах loss упал до 3.2, в целом работает:

Качество для loss 3 имеет слишком много зацикливаний и повторений:


Поэтому попробуем вариант поэтапного обучения. Можно взять предыдущий чекпоинт в контексте 2048, который прошел 5376 шагов и дообучить его как Continued Pre-Training (CPT). Если немного модифицировать код nanochat, можно продолжать обучение не с конкретного шага, а инициировать новое обучение, но не с нуля, а весами с другого шага.
python -m scripts.base_train --depth=16 --fp8 --window-pattern L --save-every=500 --device-batch-size 4 --max-seq-len 8192 --model-tag d16-8192 --load-weights-from 5376
Модель уже видела 370M токенов, поэтому сразу loss 3.1 и быстро падает до 2.3, адаптация к 8192 проходит на первых шагах нормально:

А дальше loss начал плавно расти до 2.7 и не собирался останавливаться. Модель обучается слишком большим шагом LR и вылетает из своего минимума.

Нужно снизить LR, увеличить warmup:
python -m scripts.base_train --depth=16 --fp8 --window-pattern L --save-every=500 --device-batch-size 4 --max-seq-len 8192 --model-tag d16-8192 --load-weights-from 500 --matrix-lr 0.005 --embedding-lr 0.075 --unembedding-lr 0.002 --scalar-lr 0.125 --warmup-steps 200
После этого loss снижается, в ходе адаптации плавает от 2.4 до 2.1. Итоговый loss стал ниже даже 1.7, у 2048 версии было 1.8. Но при этом val bpb остался тем же, стал 0.71, а был 0.70:

И это странно, если посмотреть лог, то минимальный bpb составлял 0.55, но в конце обучения он вырос до 0.7, хотя loss упал:

Всё это указывает на переобучение. Для CPT надо было задать меньше эпох, так как в обучение добавилось только 80M дополнительных токенов, но чекпоинт на 2048 имел аналогичные показатели, минимальный был 0.55, а итоговый 0.70. Так что проблема была и с первым чекпоинтом.
Не сохранилась 0.55 версия, но можно сравнить bpb 0.65 vs 0.71:

Версия 0.65 дает правильный код и структуру ответа, версия на 0.71 зацикливается. Видимо на 0.55 было бы ещё лучше. Переобучение ощутимо снижает качество, но оба чекпоинты были переобучены, так как val bpb был 0.7, потенциал датасета не раскрыт.
BPB, Loss и PPL
Простая и быстрая оценка LLM это показатель перплексии PPL.
PPL показывает степень уверенности модели в её ответе. PPL равный 10 означает, что у модели на выбор 10 вариантов, и она не уверена какой из них лучше, модель колеблется между этими 10 вариантами. Loss и PPL математически связаны:
Loss 3 дает PPL равную 2^3 = 8, loss 1.8 = PPL 3.5. Если Loss снижается, а val Loss растет, значит модель от обобщения перешла к запоминанию, модель переобучается (overfitting).
В nanochat для валидации используют BPB, более универсальную метрику, которую можно сравнивать на разных датасетах и токенизаторах. BPB не зависит от того, токенизатор разбил слово на 3 токена или на 1 токен, так как нормализует значение. BPB - сколько бит информации требуется модели, чтобы закодировать один байт текста:
SFT для pretrain
Пока продолжим с тем, что получилось. Pretrain умеет только продолжать текст, чтобы раскрыть этот потенциал нужно дообучение на другом датасете, который покажет модели:
Шаблон Assistant - User
Примеры вопросов и качественных ответов
Примеры где нужно останавливать генерацию, чтобы не генерировать до отсечки
Найти хороший датасет не тривиальная задача. Я нашел несколько вариантов:
Возможно, имеет смысл создать SFT датасет по статьям хабра в формате вопрос-ответ, чтобы знания у модели лучше усвоились. Например, создать что-то такое, для каждой статьи создать от 2 до 10 ответов, это позволит научиться отвечать на вопрос не целой статьей, а коротким ответом, и позволит лучше усвоить знания из статей:

saiga_preferences это DPO датасет, но если взять только chosen, и игнорировать rejected, то получится SFT. Но это маленький датасет на 30к записей, который не включает в себя многие сценарии. Дообучение на нем займет не много времени, как проверка концепции подойдет.
Я не сохранял промежуточные чекпоинты, поэтому версии с bpb 0.55 не осталось. Попробуем дообучить 0.71 версию, посмотрим, что получиться с переобученным pretrain. Запускаем SFT и смотрим, что показатели loss тут отличаются. Они ниже 1, но это нормально, так как датасет маленький, и показатель val bpb не показывает переобучение:

Свободный режим общения с моделью. Уже не плохо, модель ведет диалог, ответы короткие:

Подберет занятия, чтобы развеять скуку (конечно, если вам подходит вариант с путешествиями по времени или в космосе):

Если задавать вопросы, то ответы уже становиться длинными, но модель научилась выполнять инструкции и отвечать на вопросы по теме:

У pretrain размер генерации без остановки доходил до лимита в 8к, теперь же модель останавливается сама:

Можно попробовать написать статью, так как обучение было на статьях, то она не должна потерять навык генерировать очень длинный текст, сохраняя оформление:

Попытка написать стих. Всплывает проблема зацикливания:

Как концепция - всё работает.
После SFT выравнивание через DPO
В датасете DPO есть хорошие и отвергнутые ответы, увеличивая разрыв между ними, можно выровнять веса модели так, чтобы у неё был перевес в нужную сторону.
Тут сталкиваемся с той же проблемой обучения. Вначале у DPO loss всегда равен ~0.693, PPL 2 - cлучайное угадывание между 2 вариантами. При нормальном обучении DPO loss должен плавно снижаться, показывая, что модель учиться выбирать хорошие варианты. И вначале всё идет не плохо, loss снижается:

Но после 25% loss резко растет выше 0.69, что в целом не нормально для DPO:

Попробуем тот же способ как выше, снизим LR:
python -m scripts.chat_dpo --model-tag d16-8192 --beta 0.1 --dataset saiga_preferences --matrix-lr 0.00001 --embedding-lr 0.00001 --unembedding-lr 0.00001
Теперь нормально, loss плавал от 0.33 до 0.56, но не выходил выше 0.69:

Посмотрим, дало ли это хоть что-то.
Начало генерации в обоих случая одинаковое, перегенерирован только последний ответ:

Так как SFT версия получилась не достаточно хорошей, сложно сказать это случайность или действительно какой-то значимый эффект есть. Ответ стал лучше, DPO версия хотя бы сгенерировала код, а не впала в рассуждения, но код не того качества, как ожидалось.
Исследование. fp8 против bf16, 100% датасет без BOS best-fit
Первые попытки не стали полным провалом, но было видно, что они работают хуже, чем могли бы, и это заставляет искать другие стратегии обучения. Проверим несколько гипотез на микро модели размером d8, сравним загрузку датасета по стратегии bestfit с 100% flat, fp8 vs bf16.
У d8 размер 124M (как у базовой GPT-2 Small 124M). Для обучения 124M с учетом PLE нужно как раз 0.5B, что совпадает с размером датасета Хабра без bestfit.
Скрипт показывает, что обучение влезает в ~1 эпоху:

d8 это маленькая модель, модели такого размера почти сразу скатываются в повторы и зацикливание:

Поэтому сразу добавим штраф за повтор в размере 1.1. В целом ответы тут буду глупее чем на d16, так как размер совсем крохотный, хотя и d16 очень маленькая.
1 вариант. Размер d8, обучение fp8, контекст 2048 с 100% загрузкой датасета:

bpb 0.61:

2 вариант. Размер d8, обучение fp8, контекст 8192 с bestfit:

bpb 0.58:


3 вариант. Размер d8, обучение bf16, контекст 2048 с 100%:

bpb 0.61:

4 вариант. Размер d8, обучение bf16, контекст 8192 с bestfit:

bpb 0.58:

Ответы моделей слабые, но даже так можно сделать какие-то выводы:
даже при одинаковых loss и bpb связность ответа отличается.
ответы bf16 лучше согласованы
разница между bestfit и 100% загрузкой незначительная
Обучать в fp8 сложно, в случае обучения в bf16 это тоже самое, что fp32 и поэтому переход от bf16 к fp8 снижает диапазон в 4 раза и требует различных хаков с масштабированием. Для таких маленьких моделей это приводит к тому, что модели не имеют достаточно простора, чтобы сделать обобщение быстро и переобучаются раньше, чем обобщают. Требуется определенный опыт для обучения в fp8 и в условиях ограниченного датасета это не лучший вариант.
Что касается загрузки датасета, показатели loss и bpb - это усреднение ошибки на млн токенах, они не показывают качество усвоенных данных. И потеря 37% критична на таком размере, поэтому имеет смысл переключиться на полную загрузку. Как вариант, можно попробовать разбивать статьи длиннее T=2048 по абзацам, чтобы лучше влезать в besfit.
Нужно всё переделать и сделать правильно
Попробуем всё переделать. Обучение в bf16, ctx 2048, непрерывный 100% датасет.
На половине обучения bpb 0.54:

46%, обучение ещё не завершено, но pretrain уже ведет себя стабильнее:

Модель начала усваивать списки, что указывает на то, что диапазона хватает, и модель может извлекать более сложные признаки и паттерны, чем это получалось в fp8:

83%, 4500 шаг, bpb остается 0.54, модель не переобучается и продолжает выявлять паттерны:

К этому шагу модель освоила простой перевод, чего версия на fp8 не смогла:

Более сложные фразы удаются:

Обучение завершено на val bpb 0.55, loss 2.12. Пройдено 2.8B без bestfit, плоским списком с 100% загрузкой всех токенов. Переобучение минимальное, val bpb близок к лучшему значению.

Результат bf16
pretrain усвоил порядок планет до Нептуна:

Свободный чат:

Вопрос-ответ:

Генерация простого кода:

Написать корректный json это тоже навык:

Где будет провал
Модель не может знать как чинить кран на кухне, и что вообще такое кран на кухне, так как такой информации не было на Хабре.

Но зато смогла каким-то образом понять, что вообще такое "Кухня":

У модели нет знаний из Wiki, и встречая незнакомые сущности навык галлюцинаций выкручивается на 500%:

Но знает эмодзи, так как они встречались:

Сложность со следованием какой-то точной инструкции, например "не писать комментарии", просить перечислить точное количество чего-то, написать сложный код и тому подобное.

Более простые задания с небольшой конкретикой даются лучше:

Если pretrain мог переводить с помощью правильно составленного запроса, то SFT версия почти не умеет, так как не было или мало примеров такого сценария в SFT датасете. Вместо перевода начинает общение с текстом, при этом понимает смысл текста на английском.

Но простые примеры иногда получаются:

Потенциал не раскрыт
Как концепция - работает, но можно лучше. Если пройтись циклом дообучения:
Saiga SFT → Habr SFT → Vikhr SFT → Saiga DPO
Можно получить более интересную модель:

Файлы моделей
Чекпоинты: https://huggingface.co/shannonkun/nanochat-d16-habrgpt
Для запуска нужно использовать https://github.com/karpathy/nanochat
python -m scripts.chat_web --source sft --model-tag d16-dpo-step2-bf16
Поддержки gguf пока нет.
Заключение
Модель habrGPT 0.5B научилась связно говорить, соблюдать орфографию, пунктуацию, давать ответы на вопросы, писать статьи, выполнять задания, генерировать простой код, писать что-то похожее на стихи, немного переводить, несмотря на то, что английского языка было мало.
Первая GPT-2 124M обучалась на 10B токенов, Gemma3 1B обучалась на 2T (2048B) токенов. Датасет Хабра содержит всего 508M (0.49B) узкоспециализированных токенов и всё равно что-то получилось.
Возможно, вместо 0.5B стоит называть эту модель E0.25B, хоть тут и есть 0.5B, но вместо трансформных +0.25B тут легковесные +0.25B PLE, и на сколько они хороши и компенсируют качество - непонятно. Возможно, честные 0.5B были бы даже лучше.
Обучение в fp8 частично провалилось, частично удалось. Обучить такую маленькую модель в fp8 можно и какой-то результат достигнут, но результат хуже чем на bf16.
Комментарии (57)

linux-over
08.07.2026 17:45наверное на википедии вообще шикарное качество получится.
или попросить chatgpt выгрузить статьи для обучения моделей :)

Incognito4pda
08.07.2026 17:45Оффлайн версию Википедии можно подключить к модельке например через openzim-mcp. Недавно пробовал с вебмордой llama.cpp, почти мгновенно даёт вижимку из любой статьи.

DennisP
08.07.2026 17:45Пока пробежался по-диагонали, почитаю вдумчиво на выходных. Могу сразу сказать - очень впечатляет проделанная работа и системный подход.

rPman
08.07.2026 17:45Черт! неожиданно, что за такое короткое время, на таком слабом оборудовании, обучается модель которая в принципе инструкции выполняет хоть как то.
Следующий шаг - обучение с учителем (другая модель или агент) а так же генерация датасета (как я понимаю это и есть дистиляция), обучение reasoning.

enkill
08.07.2026 17:45Спасибо за статью! Я только поверхностно представлял как работают нейросети, эмбеддинги и все такое, но после прочтения захотелось изучить эту тему глубже и посмотреть что можно сделать на 4070)

xSVPx
08.07.2026 17:45Удалось целиком сграббить хабр ? Есть ли в виде с ссылками на графику и комментами ? Какой получился объем ?

achekalin
08.07.2026 17:45Вот буквально минут 10 назад он у меня 504 возвращал - прямо интересно, не связано ли?

Shannon Автор
08.07.2026 17:45Это не полный датасет хабра, в статье есть ссылка на датасет, которую выше уже продублировали. Датасет собрал @Takagi, его же датасет IlyaGusev/saiga_preferences я использовал для SFT.

Recursicorn
08.07.2026 17:45Отличная статья, спасибо!
Было бы интересно узнать как на эту модель повлияет grokking. Пару лет назад такой хайп был, а потом все как-то стихло.

Leo_sk
08.07.2026 17:45Обычно модельки меньше 5b так или иначе выдают осмысленный бред в 95% случаев. Было бы интереснее лично для меня обучить lora какой нибудь модельки (кстати там отдельная тема что у большинства моделей все очень плохо с выводом больше 2-3к токенов за раз, есть что то типа long writer Zero 32b, но он очень уж сухонький, под мою задачу с художкой в свое время не подошёл, а вот для хабра вероятно вполне) на 20-30млрд параметров в формате пар, промт к статье-сама статья (можно еще и комменты в конце генерить), для генерации промтов использовать deepseek v4, по стоимости +- приемлемо.
Но как эксперимент прикольно. Я ожидал что моделька меньше миллиарда вообще ни на что способна не будет, и чисто мешанину из тематических слов едва осмысленную будет выводить.
И кстати может качество будет получше если обучать на меньшем количестве токенов, но уже предобученную модельку? А то обучать с нуля обычно мало смысла...
ps. Интересно, если прогнать датасет через фильтр сгенерированного текста, какой процент отвалится...
pps. Неужто проблема с torchaudio не вылезла? Решается вроде относительно легко но как же сцуко бесит каждый раз.
avshkol
08.07.2026 17:45Я ожидал что моделька меньше миллиарда вообще ни на что способна не будет, и чисто мешанину из тематических слов едва осмысленную будет выводить.
На Хабре разносторонний и информационно насыщенный контент, и это сильно влияет на качество, как бы не в разы уменьшает объем контента для обучения и размер модели.
Вот статья на Хабре с оценками влияния качества обучающего датасета: Учебник - всё, что вам нужно

Shannon Автор
08.07.2026 17:45И кстати может качество будет получше если обучать на меньшем количестве токенов, но уже предобученную модельку? А то обучать с нуля обычно мало смысла…
Есть и такое. У меня готова, но не опубликована, статья, где я дообучал старую ruGPT3 XL 1.3B (как раз @efreelancer недавно публиковал статью, где сделал для этой модели конвертацию в современный формат и поддержку gguf). Это pretrain 2020-2021 года обученный на 80B токенов, который умеет только продолжать текст, и выглядит это часто не как ответ, а как повествование:

Создавался этот pretrain во времена, когда ещё не было понимания, как заставить хороший pretrain вести диалог в чате, следовать инструкциям. Это время за 2 года до выхода ChatGPT и первой InstructGPT. И после дообучения на SFT такая модель на 80B токенов куда богаче по возможностям, она больше знает, хорошо следует инструкциям, может работать с текстом, даже решать головоломки:

И чтобы было понятно, какой уровень получился у модели, то сравнил её с Gemma3 1B 2025 года, при чем получилось не всегда в пользу Gemma3.
Задача на внимательность, Gemma3 1B провалил:

Про квантовую причину горения Солнца, Gemma3 1B дал не правильное название явления:


Leo_sk
08.07.2026 17:45Да прям прикольно. Особенно про сравнение качества, даже не знаю что и сказать про уровень модельки 20-21 года. Я то был уверен что нормальные маленькие появились сильно позже, но видимо вся проблема была именно в нормальном sft . Я кстати предполагаю что просто миллиарда параметров недостаточно для языкового переноса знаний, и на английском gemma отвечала бы гораздо лучше. Возможно.
А кстати отвлечённый вопрос, а вы никогда не пытались запустить обучение в kaggle, на TPU v5e-8? Там теоретически 122 гб, буквально что-то среднее между h100 и h200, но вот настроить это всё так чтобы оно запускалось и нормально распределялось по чипам мне не удалось... А вот маленькую модельку может и на одном чипе получится, там в основном с распределением по 8 чипам каждый раз затык да и среда кастрированная. Для инференса ещё туда сюда, да и то через одно место а вот с обучением у меня не вышло.

InfusionKRD
08.07.2026 17:45Классный результат, для такой мелкой модельки.
Ещё хороший буст прокачки логики даёт перестройка SFT датасета с цепочек [Q/A], на цепочки [Q,A,Q,A] в рамках одного контекста (правда найти такие датасеты в сети - совсем сложная задача, что проще создать свои)
Для своих целей дообучал модель от RefalMachine/ruadapt_qwen2.5_3B_ext_u48_instruct_v4
Шикарная 3B модель, для своего времени.

Syzd
08.07.2026 17:45Сколько времени ушло на обучение такой модели?

Shannon Автор
08.07.2026 17:45Финальный pretrain ~9 часов и ещё пол часа на sft и dpo.

rPman
08.07.2026 17:45а на подбор гиперпараметров процесса обучения?

Shannon Автор
08.07.2026 17:45Там без подбора, гиперпараметры в nanochat выставляются автоматически, сам Карпатый уже давно занимается оптимизацией параметров обучения, поэтому выставлены по его личному опыту, закону Шиншиллы и так далее. Только на DPO пришлось снижать, но в nanochat вообще нет DPO этапа.
Если в целом на все эксперименты, то ушел где-то месяц, я обучал не только nanochat, обучал и MoE подобные модели, и чистый 0.25B на кастомной архитектуре которую собирал из разных новых архитектур, и даже пытался обучить 7B модельку, которую с помощью многих ухищрений удалось вместить в 32Гб, но скорость обучения была 500 t/s. Выше уже писал про дообучения 1.3B претрейна, в целом dense 1.3B вполне можно дома обучать.

rPman
08.07.2026 17:45с практической точки зрения такие слабые модели где и как можно использовать (особенно если речь идет о текстовых?) какие-нибудь сверхбыстрые классификаторы на специфических датасетах?

Moog_Prodigy
08.07.2026 17:45И классификаторы, и наверное в роли speculative pre-model. Очень быстрые, помогают основной LLM сориентироваться и не тупить на разборе промпта. Возможно, что-то еще.

foss22
08.07.2026 17:45пытался обучить 7B модельку, которую с помощью многих ухищрений удалось вместить в 32Гб, но скорость обучения была 500 t/s.
Расскажите плиз про эти ухищрения. Как искали границу чтобы влезала? Какие оптимизации? Скорость медленная не так важна, главное чтобы влезала. Пусть хоть месяц или полгода учится, на нужных кастомных датасетах.

Takagi
08.07.2026 17:45Пост хороший!
Вероятно после него получил следующее письмо от legal@habr.com
Добрый день, Илья
Просим в кратчайшие сроки удалить дата-сет Хабра https://huggingface.co/datasets/IlyaGusev/habr со всех известных носителей. Создание, существование и использование, в т.ч. распространение этого дата-сета нарушает сразу много всего: интеллектуальные права Хабра, интеллектуальные права каждого (!) автора, регулирование персональных данных (ведь там ФИО и никнеймы)…
Сообщите, пожалуйста, когда удалите.
Как видите, на данном этапе мы не составили полноценную претензию со ссылками на законы, возможными санкциями и так далее. Нарушение считаем очевидным и надеемся на его оперативное устранение.
C наилучшими пожеланиями, Habr Legal Team

rPman
08.07.2026 17:45что значит нарушает? а что по поводу лицензии на данные, которые помнится хабр заявлял про открытую CC BY? вроде бы про нее говорилось, когда подключаешься программе вознаграждения за публикации.

trinxery
08.07.2026 17:45Наверняка там:
Далеко не всё под CC BY;
Материалы, созданные сотрудниками Хабра и принадлежащие ему;
Можно притянуть авторское право Хабра на подборку материалов;
Тому подобное.

rPman
08.07.2026 17:45и как же определить, ведь информация об этом исчезла, т.е. лицензия вроде была, но потом вроде бы не стало (осталась общаяя - все права хабру)... но публикации тех кто делал их на правах этой лицензии не удалили а внезапно присвоили?
p.s. считаю общепринятую практику присваивания себе пользовательского контента (особенно когда контент наполняется с миру по нитке) - порочной вредной и не правильной. Если контент создается сообществом, то этот контент должен быть общедоступным в общем смысле, включая возможность его копирования и тем более использования для ИИ.
Я отчетливо помню ощущения, когда читал про то что статьи у хабра теперь по cc by лицензии, типа молодцы, сделали что то правильно, внезапно... и вдруг оказывается то были старые времена, допущения 'по глупости'.
Человечество создало что то прекрасное - интернет и огромный датасет знаний, и вместо того что бы использовать этот датасет что бы продолжать создавать что то еще более прекрасное (тот же ИИ), оно (человечество) создает само себе кучу проблем и ограничений. Взгляните на это со стороны, вот вы видите муравья, тянущего дохлую гусеницу, и смеетесь с того как не эффективно он это делает, как выбирает неэффективный путь, условно мешает и толкает других муравьев... вот это тот самый случай.

xSVPx
08.07.2026 17:45Нет документа - нет прав. Увы.
Сам мув, конечно предельно гадкий.
Мне всегда было интересно как это с офертами работает, их что куда-то депонируют ?

funca
08.07.2026 17:45В ППА есть отсылка к некоему договору https://habr.com/ru/docs/authors/ppa/
Скрытый текст
CC BY 3.0
Конструкция договора предусматривает полный переход прав на произведение от автора к сервису и при этом сервис распоряжается таким правом, предоставляя возможность распространения такого материала по лицензии CC BY 3.0 любому лицу, включая автора произведения.
В данном случае такая мера необходима для защиты от возможных претензий недобросовестных авторов, решивших предъявить претензии лицам, распространившим его материал с предварительным отзывом своего согласия на обнародование своего произведения.
В соглашении указана конструкция, когда автор, полностью отчуждая права на произведение, на основании лицензии CC BY 3.0, выданной сервисом неограниченному кругу лиц, включая автора, допускает размещение произведения в сети Интернет.

xSVPx
08.07.2026 17:45Вопрос в другом. Завтра по этой ссылке будет что-то еще. Как можно потом доказать, чтотсегодня действовали иные правила ?

funca
08.07.2026 17:45Это хороший вопрос. Страница по ссылке не выглядит как официальный обязующий документ. Я ее привел лишь как возможный источник, откуда могла возникнуть тема про CC BY.

xSVPx
08.07.2026 17:45Да там может быть написано даже "все мое движимое и недвижимое ...", это совершенно неважно. Даже будь он обязывающим, как доказывать каким он был ? С нотариусом фиксировать ? Такое себе....
Это должно как-то быть отрегулировано с офертами. Наверное :).

Shannon Автор
08.07.2026 17:45Хм, только в чем смысл. Ведь такими действиями по сути уничтожают ru ML сцену, которая и так очень слабо представлена, ни датасетов, ни материалов, лишь одни переводы.
Тоже прислали письмо
Добрый день,
Обратили внимание на Вашу статью https://habr.com/ru/articles/1054710/, точнее, на датасет, использованный для обучения LLM, ссылка на который содержится в статье - https://huggingface.co/datasets/IlyaGusev/habr. Этот дата-сет был создан нелегально, поэтому мы уже обратились к его создателю (тоже пользователю Хабра) с требованием об удалении. Просим Вас также удалить ссылку из статьи.
C наилучшими пожеланиями, Habr Legal Team

funca
08.07.2026 17:45Legal, которые рассылают письма со ссылками на нелегальный по их же заверениям контент, одновременно угрожая авторам, это ведь настоящий киберпанк). Скорее ожидаешь аргументы со ссылками на соглашения или законы, которые по их мнению были нарушены. @Boomburum

Neikist
08.07.2026 17:45Да уж, вот это дичь. И так почти перестал заходить на хабр последнее время, но пожалуй теперь и от rss пора отписаться. Это уже далеко не "уже не торт", а заметно хуже.

foss22
08.07.2026 17:45последовательности 2048 токенов.
Скорее всего появятся сотни клонов, где нашинкован датасет однажды опенсорснутый, который пытаются снова закрыть. Анонимайзером вычистить лэйблы, упоминания хабра, ПД и привязки к авторам и всё ОК ведь будет? Это уже не будет целостное произведение, не статья, не объект авторского права.

spacediver
08.07.2026 17:45Штош. Раньше глаз соскальзывал с ИИ-текстов, теперь начал соскальзывать с ИИ-иллюстраций.

Syzd
08.07.2026 17:45А кто устанавливал nanochat в windows 10? Я вроде все установил, все требуемые библиотеки, но уперся в то что предлагают заменить fnctl на portalocker, так как fnctl только для linux. chat_cli запустился, к базе нейросети подключаюсь, но сам чат не выводит в консоли.

buldo
08.07.2026 17:45А есть какие-то варианты, чтобы локально запушенная сеть всегда была в режиме обучения? Условно говоря, я хочу начать с сети, которая умеет разговаривать и пользоваться гуглом. А дальше задаю вопрос, она что-то ищет в сети, вываливает это мне, подходящие данные, которые я отмечаю как валидные, становятся частью датасета.

foss22
08.07.2026 17:45Да, стриминг. Добучать постоянно не на данных, лежащих на диске, а постоянно тянущихся из сети и временно кэшированных, за последнюю неделю например из кэша браузера.

StriganovSergey
08.07.2026 17:45Наверно, нужно автоматизировать создание LoRA и при желании, вмерживать ее в модель, или подгружать так, из отдельного файла.
Впрочем, если нужны точные ответы по новым темам, то потребуется интеграция с поисковым движком, сочетающим классический поиск и векторный.

Elbrus128
08.07.2026 17:45Спасибо большое! Но, есть замечания:
Раздел "Что такое PLE?" написан плохо. Новичкам непонятно. При первом упоминании термина его нужно раскрывать. Текст должен быть, по возможности, самодостаточным.
Иначе, как у Лема: сепулярий - место для сепуления, сепуление - процесс, производимый с помощью сепулек, сепульки — то, что используют в сепулярии.

ValeraZhot
08.07.2026 17:45Теперь можно генерировать очередное "доказательство" гипотезы Коллатца хоть каждый день.
efreelancer
Прочёл с удовольствием, словно остросюжетный детектив, автору огромное спасибо за проделанный труд!
Планируется ли релиз скриптов обучения, генераторов датасета и весов в публичный доступ или эта модель скорее эдакая лабораторная работа?
Shannon Автор
Спасибо, хотел как раз не сразу результат, а для тех кому интересна тема обучения LLM дома, чтобы было побольше материала, тупики, ошибки и гипотезы.
Чекпоинты загрузил, обновил статью. Поддержка gguf только в форках, поэтому запуск через nanochat, нужно только разобраться куда ложить файлы и как запустить.