Разработка: llm-analisis
Хроника разработки проекта llm-analisis. Основные направления: новые функции, изменения кода, исследования. Всего 10 записей в потоке. Последние темы: Когда маршрутизация идеальна, а точность нет: история эксперимента 13b; Когда маршрутизация экспертов встречает стену батч-нормализации; SharedParam MoE: когда 4 эксперта лучше 12.
Смирили Mixture of Experts: как остановить экспертов от захвата власти
Проект llm-analisis — это исследование динамических систем экспертов для глубокого обучения. Вроде звучит наукообразно, но на практике означает одно: мы собрали архитектуру Mixture of Experts, где роутер направляет данные между специализированными нейросетями, и попросили её самой расти. Красивая идея, только выросло совсем не то, что ожидалось.
Когда эксперты мутировали
На первых запусках система вела себя странно: из 12 заранее добавленных экспертов реально работали только двое (Expert 0 с 84% нагрузки и Expert 1 с 88%). Остальные десять были просто мёртвым грузом. Одновременно growth-механизм (алгоритм, отвечающий за размножение экспертов) срабатывал каждую эпоху подряд — 8 экспертов за раз, потом 17, потом ещё больше. Это была не эволюция, а экспоненциальный хаос.
Точность застыла на 97.0–97.3% и не росла дальше. Добавляй новых экспертов или нет — ничего не меняется. Типичная ситуация: чем больше участников в процессе, тем больше бюрократии, тем меньше эффективности.
Три пути к спасению
Задача была простая: сломать эту систему правильно. Первым делом добавил cooldown-механизм после каждого успешного роста — пять эпох, когда новые эксперты не появляются. Пусть система сначала разберётся, зачем ей вообще эти новички. Во-вторых, внедрил load balancing loss в роутер, чтобы он учился распределять нагрузку равномерно, а не зависал на двух избранных. В-третьих, ослабил seed-модель: снизил TARGET_ACC с 0.98 до 0.97 и уменьшил HIDDEN_DIM с 12 до 6, чтобы система не засыпала на лаврах.
Неожиданно выяснилось, что максимизация entropy в выходе роутера — это почти волшебство. Просто заставляешь его распределять нагрузку равномернее, и вот уже все три эксперта работают с разумной нагрузкой (84%, 79%, 37% вместо прежних 84%, 88%, 0%).
Что получилось
На третьей попытке всё сработало. Seed-модель из трёх экспертов стабилизировалась на 96.7–97.0% за восемь эпох. На девятой эпохе Firefly-алгоритм деликатно разделил первого эксперта, появился третий. Load balancing ловко заставил его работать — entropy выросла с 0.48 до 1.07. А главное: growth сработал ровно один раз вместо этого бесконечного взрывного роста. Целевая точность в 97.11% достигнута на четырнадцатой эпохе.
Вывод банален, но эффективен: иногда самая мощная система требует не расширения, а дисциплины. Cooldown, балансировка, осмысленные ограничения — и хаос превращается в эволюцию.
Кстати: Что общего у Svelte и кота? Оба делают только то, что хотят, и игнорируют инструкции 😄
МОЯ растёт: как система экспертов научилась не взрываться
Проект llm-analisis — это исследование смеси экспертов (Mixture of Experts, MoE) для обработки сложных данных. Задача на этом этапе была простая, но коварная: система достигла baseline 96.7% точности, но дальше расти отказывалась. И вот когда начинаешь что-то менять — бум, либо эксперты коллапсируют (умирают все кроме одного), либо система начинает неконтролируемо расщепляться.
Первым делом выяснилось, что в коде была классическая ошибка: данные для вычисления diversity loss проходили напрямую в экспертов, минуя model.projection. Это как подавать сырое масло в двигатель вместо обработанного топлива — система работает, но неправильно. Исправили, и baseline встал на место.
Но проблемы начались, когда включили режим роста. Система начала добавлять новых экспертов, и тут два монстра вышли одновременно. Первый — expert collapse: из 12 экспертов только 3 получали градиенты, остальные 9 просто сидели без дела, как программисты на планерке. Второй — growth explosion: система добавляла по 10 новых экспертов подряд, вместо того чтобы контролировать процесс.
Решение пришло в три шага. Добавили growth cooldown на 5 эпох — механизм, который останавливает спешку, дав системе время войти в режим. Вместо бешеных 10 сплитов подряд стал ровный, контролируемый рост. Второе — включили entropy maximization для load balancing: система теперь активно пытается использовать все эксперты, поощряя их к работе. Результат: мёртвые эксперты воскресли. Было 10 из 12 неактивных, стало все три полностью в деле (84%, 79%, 37% нагрузки соответственно). Третье — пересчитали историю точности, чтобы GO/NO-GO отчёт был честным.
И вот интересный факт: идея entropy-based балансирования экспертов в MoE приходит из теории информации 1940-х годов, но в контексте нейросетей её применяют едва ли не недавно. Большинство реализаций просто игнорируют проблему, пока система работает, но как только система начинает расти — всё падает. Lesson learned: лучше потратить час на правильную балансировку, чем две недели на дебаг коллапса.
Результат: за 14 эпох система выросла с 96.7% до 97.1% — не огромно, но честно и стабильно. Все артефакты разложены по местам: отчёт в reports/phase1-moe-growth-results.md, MASTER-SUMMARY обновлён, три файла модели (moe.py, growth.py, train_mnist.py) лежат в seed-net/phase1/.
Дальше началось самое интересное — Phase 2, где морфогенное поле на основе реакции Schnakenberg будет управлять тем, где и когда растёт система. Но это уже другая история.
Оказывается, что система экспертов — это как управление командой: нужна дисциплина (cooldown), справедливое распределение задач (entropy) и честный учёт результатов.
Когда 1,3% точности — это целая эпопея оптимизации
Проект llm-analisis уже был в финальной стадии обучения нейросети на CIFAR-10, когда я заметил, что точность упирается в 83,7% при целевой 85%. Казалось бы, мелочь — всего полтора процента. Но в машинном обучении каждый процент — это часы отладки и переосмысления архитектуры.
Диагноз был ясен: модель просто недостаточно мощная. Её свёрточный позвоночник (conv backbone) работал со слишком узкими каналами, как будто пытаясь угодить в очень узкий коридор, когда на самом деле нужна полноценная комната для маневра. Я решил переделать модель так, чтобы её структуру можно было легко конфигурировать на лету.
Расширяем каналы и переписываем оптимизаторы
Первым делом я сделал ширину каналов параметризуемой — теперь можно было просто изменить число фильтров в свёрточных слоях, не трогая основную логику. Затем пришлось переписать тренировочный скрипт целиком.
Но тут выявилась ещё одна проблема: модель обучалась с Adam-оптимизатором, который хорош для многих задач, но на CIFAR-10 показывает себя хуже, чем SGD с momentum. Это типичная ловушка — Adam стал почти универсальным выбором, и многие забывают, что для синтетических датасетов наподобие CIFAR-10 классический SGD часто побеждает благодаря более стабильной сходимости и лучшей обобщающей способности.
Я переключился на SGD с momentum, но тут выяснилось, что фреймворк использует особый механизм RigL (Rigging Lottery) для динамического разреживания сети. RigL периодически растит модель, добавляя новые соединения, и при каждом таком событии оптимизатор переинициализировался. Пришлось обновить логику рестарта оптимизатора не только в основной фазе обучения, но и в Phase B — этапе, где сеть уже достаточно созрела для более тонкой настройки.
Неожиданный враг: переполнение разреживания
По ходу работы я наткнулся на баг в самой логике RigL. Механизм переполнял сеть новыми связями быстрее, чем нужно, нарушая баланс между разреживанием и ростом. Пришлось углубиться в реализацию и переписать часть логики расчёта скорости роста новых соединений.
В результате модель начала сходиться куда быстрее и стабильнее. Когда я запустил финальное обучение с расширенными каналами, SGD с momentum и исправленным RigL, точность перепрыгнула за 85% с первой попытки. Те самые 1,3%, которые казались непреодолимой стеной, оказались просто комбинацией трёх проблем: узких каналов, неправильного оптимизатора и бага в механизме динамического разреживания.
Главный урок: иногда поиск последних процентов точности требует не суперсложных идей, а просто системной отладки всех компонентов вместе. И помните — сначала всегда проверяйте, используете ли вы SGD на CIFAR-10, а не слепо доверяйтесь моде на Adam 😄
Марафон обучения модели: как я перезагрузил сервер посередине тренировки
Проект llm-analysis требовал обучения нескольких моделей параллельно. На доске стояла амбициозная задача: запустить шесть вычислительных процессов (их называют квартами — Q1 и Q2, по 3 чекпоинта каждая), каждый из которых должен пройти 150 эпох обучения. Время было критично: каждый день задержки — это дополнительная неделя на GPU.
Первым делом я запустил квартет Q1. Все три модели (1.1, 1.2, 1.3) стабильно обучались, постепенно повышая accuracy. Первый квартет завершился успешно — все чекпоинты сохранились на диск. Так что Q1 был зелёным сигналом.
Затем начал Q2. Запустил пару 2.1 и 2.4 параллельно, оставляя GPU свободным для 2.2 и 2.3 после их завершения. Модели ползли вверх: 2.1 достиг 70.45%, 2.4 — 70.05%. Всё шло по плану. Но тут случилось неожиданное — сервер перезагрузился.
Паника? Нет. Именно поэтому я сохранял чекпоинты после каждых 50 эпох. Когда машина поднялась, я проверил состояние: Q1 полностью в сохранности, Q2 остался с двумя готовыми моделями (2.1 и 2.4). Зато 2.2 и 2.3 потеряли прогресс — были на 68–69%, но восстанавливались с последнего сохранённого чекпоинта.
Тут я понял классическую проблему long-running ML-задач: checkpoint strategy — это не просто “хорошая практика”, это страховка от Murphy’s Law. Если ты тренируешь модель часами и не сохраняешь состояние каждый час, ты играешь в рулетку.
Запустил 2.2 и 2.3 повторно. Мониторю GPU: 98% загрузки, 10.5 GB памяти занято. На этот раз 2.2 рвёт вперёд — через час достиг 70.17%, а затем и 70.56%. А 2.3, как ленивый ученик в конце четверти, упорно ползёт с 56% к 62%. ETA для 2.2 — 8 минут, для 2.3 — ещё 2.5 часа.
Главное, что я выучил: не полагайся на непрерывность вычислений. Планируй архитектуру обучения так, чтобы каждый этап был самодостаточен. Чекпоинты должны быть не роскошью, а основой. И не забывай про версионирование моделей — того, что ты обучал неделю назад, может не быть завтра.
Пара 2.5 и 2.6 ждут в очереди. GPU будет готов через пару часов. План прост: запустить, убедиться, что новые модели устойчивы к сбоям, и уже не волноваться.
😄 Совет дня: если ты тренируешь нейросеть на сервере — перезагрузка не будет сюрпризом, если ты всегда сохраняешь checkpoints. А ещё лучше — настрой автоматический рестарт обучения при падении процесса.
Когда модель учится менять себя: как мы ловили ошибки в самоадаптирующейся архитектуре
Проект llm-analysis — это попытка научить нейросеть не просто решать задачу классификации текста SST-2, но ещё и самостоятельно управлять своей архитектурой. Звучит как фантастика? На деле это долгая война с энтропией и случайными числами.
С чего всё началось
После успешной Phase 6 у нас было две конфигурации с результатом около 70%: Q1 выдавала 70.15%, Q2 с MoE-архитектурой добралась до 70.73%. Казалось бы, пик достигнут. Но видение проекта было амбициознее: что если модель сама будет решать, когда ей нужен новый эксперт (grow) или когда текущие избыточны (prune)?
Phase 7a завершилась успешно, и мы двигались в Phase 7b — «Control Head Design». Идея была классическая: добавить отдельную голову управления, которая будет предсказывать, нужно ли модифицировать архитектуру. Но тут начались приключения.
Первый камень преткновения: синтетические метки
Реализовали Phase 7b.1 с энтропийным подходом. Суть была в том, чтобы использовать routing_entropy — энтропию маршрутизации экспертов — как сигнал для управления. Сказано — сделано. Запустили обучение…
И получили 58.30% точность вместо 69.80% на базовой модели. Полный NO-GO.
Ошибка была коварная: мы использовали синтетические случайные метки (30% растёт, 20% обрезается) для обучения control head, но эти метки никак не коррелировали с реальным улучшением архитектуры. Модель начала выдавать сигналы, которые не имели смысла — вроде «расти, когда ты и так хорошо работаешь» или «удаляй экспертов, когда они нужны».
Поворот: энтропия как источник истины
Переделали подход в Phase 7b.2. Вместо синтетических меток решили использовать саму routing_entropy как дифференцируемый сигнал. Ведь энтропия маршрутизации — это реальное поведение модели, а не придуманные числа. Создали три новых файла: полный план стратегии, expert_manager.py для безопасного добавления/удаления экспертов с сохранением состояния.
Логика была: если энтропия низкая, значит модель хорошо разделила нагрузку между экспертами — не растём. Если энтропия высокая, нужен новый голос в ансамбле.
Но потом обнаружилась реальная проблема
Загрузили checkpoint Phase 7a (лучший результат — 70.73%), запустили обучение с control head… и модель стартовала с точностью 8.95% вместо ожидаемых 70%. Это была красная лампочка.
Начали копать. Оказалось, что при загрузке checkpoint’а из словаря нужно использовать ключ 'model_state_dict', а не просто 'model'. Классическая ошибка, когда сохранять учился вместе с оптимизатором, а загружать забыл про детали структуры.
Чинили. Потом ещё раз запустили. И тут выяснилось: одновременное обучение модели и control head вызывает градиентную катастрофу. Точность падает, entropy-сигналы становятся шумом.
Решение пришло с неожиданной стороны
После нескольких итераций неудач понял: может быть, вообще не нужно учить модель менять свою архитектуру во время обучения? Может быть, архитектура должна быть заморожена?
Phase 7b.3 — «Direct Approach» — это была попытка упростить: забыли про control head, забыли про self-modification, сосредоточились на том, что работает. Оказалось, что 12 экспертов, найденные в Phase 7a, — это уже оптимум. Вместо того чтобы учить модель себя переделывать, лучше просто хорошо обучить её с фиксированной архитектурой.
Это было похоже на переход от идеи о том, что нейросеть должна быть как живой организм с самопроизвольной адаптацией, к пониманию, что иногда наследственная архитектура плюс обучение параметров — это уже достаточно мудрая система.
Чему мы научились
Самый ценный урок: когда метки для обучения никак не связаны с реальным качеством, модель просто выучит шум. Синтетические сигналы могут казаться правильной идеей на бумаге, но в боевых условиях обучения нейросети они становятся якорем, который тянет вниз.
Второй урок: не каждая красивая идея — это хорошая идея в ML. Иногда простота и фиксированная архитектура работают лучше, чем амбициозная самоадаптация.
Третий урок: checkpoint’ы — это хитрые штуки. Всегда проверяй структуру словаря, всегда логируй, откуда ты загружаешь, во что загружаешь.
Остаток команды перешёл на Phase 8, но теперь с более скромными амбициями и более реалистичными ожиданиями. И хотя идея о self-modifying нейросетях не сработала в этот раз, мы узнали много нового о том, как на самом деле работает градиентный спуск в сложных архитектурах.
😄 Тренировать control head — всё равно что заставлять модель смотреть в волшебный кристалл и предсказывать, когда ей растить или резать экспертов, не имея никакого способа узнать, были ли её предсказания правильны.
Когда всё падает: Как я 16 часов охотился на призрак в нейросети
Проект llm-analysis вошёл в фазу 7b, и я был уверен — вот она, момент прорыва. Идея казалась блестящей: добавить вспомогательные потери энтропии, заставить модель самостоятельно управлять архитектурой во время обучения. Синтетические метки, динамическая модификация слоёв, умные функции потерь — казалось, всё сходится в одну точку. Но вместо взлёта получилась полоса падения.
На фазе 7a я достиг 69.80% точности на фиксированной архитектуре. Теория была простой: если зафиксированная сеть хороша, то самоадаптирующаяся должна быть лучше. Опубликовано же, оптимизируют ведь. Запустил эксперименты.
Эксперимент 7b.1 с синтетическими метками упал до 58.30% — деградация на 11.5%. Попробовал добавить entropy-based вспомогательную потерю с joint training — тут вообще беда: 42.76% точности. Модель явно конфликтовала сама с собой, оптимизируя одновременно классификацию и архитектурные модификации. Эксперимент 7b.3 с прямой энтропией показал 57.57% — чуть лучше, но всё равно худше исходной фазы 7a.
Три недели назад я бы назвал это просто плохими гиперпараметрами. Но я писал логи детально, сравнивал шаг за шагом. И вот оно — откровение, которое укусило во время отладки: валидационный split меняет распределение данных. Только эта смена дала деградацию в 13% от исходного результата. Архитектура здесь была вторична.
Ключевой инсайт пришёл неожиданно: самомодифицирующиеся архитектуры во время обучения фундаментально нестабильны. Модель не может одновременно оптимизировать классификацию, менять структуру слоёв и остаться в здравом уме. Это не issue в коде, это issue в физике обучения. Похоже на попытку водителя одновременно управлять авто и переделывать двигатель — машина просто развалится.
Я потратил 16 часов на пять тренировочных скриптов (1500 строк), семь детальных документов анализа (1700 строк документации) и в итоге понял, что идти туда не надо. В нормальной биологии архитектура наследуется и фиксируется, а адаптация идёт через параметры. Фаза 7c будет про фиксированную архитектуру с многозадачным обучением. Фаза 8 — про meta-learning гиперпараметров, но не про модификацию самой сети.
Неприятно? Да. Потрачено впустую? Нет — я выявил dead end до того, как зайти туда с полным размахом. Быстрое отрицательное открытие иногда дороже золота.
Дальше — фаза 7c, предполагаю 8–12 часов работы, и на этот раз архитектура будет стоять как скала.
😄 Оказывается, мудрость эволюции в том, чтобы не переделывать себя во время прохождения теста.
Когда эксперименты показывают, что вы идёте в тупик — это тоже результат
Проект llm-analisis стоял на пороге важного этапа. Нужно было разобраться, может ли нейросеть с динамической архитектурой (то есть такая, которая меняет себя прямо во время обучения) работать эффективнее статичной модели. Звучит амбициозно: система, которая сама растёт, адаптируется, эволюционирует. Но амбиции и реальность — вещи разные.
Столкновение с жёсткой реальностью
Phase 7b был нацелен на проверку трёх гипотез. Первая: можно ли помочь модели через синтетические метки (synthetic labels)? Вторая: поможет ли вспомогательная функция потерь на основе энтропии (auxiliary entropy loss)? Третья: может быть, прямой подход с энтропией — самый эффективный?
Я запустил три параллельных эксперимента с соответствующими реализациями: train_exp7b1.py, train_exp7b2.py и train_exp7b3_direct.py. Каждый файл — это 250–310 строк кода, где каждая деталь архитектуры была тщательно продумана. Добавил специализированный control_head.py для управления вспомогательными функциями потерь и expert_manager.py для работы с модулем экспертов.
Результаты оказались шокирующими, но очень информативными.
Что сломалось и почему это ценно
Первая неожиданность: когда я попытался обучать вспомогательные потери одновременно с основной функцией потерь, точность упала на 11,5–27%. Это не баг — это конфликт целей. Модель получала противоречивые сигналы, пытаясь одновременно минимизировать несколько функций потерь. Классический случай, когда многозадачное обучение работает против вас, если не структурировать его правильно.
Вторая проблема: я использовал отдельное валидационное множество для отслеживания прогресса. Знаете что? Это вызвало распределительный сдвиг (distribution shift), который сам по себе подорвал производительность на 13%. Урок: не всегда валидационное множество — друг вашей модели.
Третье открытие касалось архитектуры. Когда система пыталась изменяться динамически (добавлять новых экспертов прямо во время тренинга), её точность была 60,61%. Когда я зафиксировал архитектуру (12 экспертов, неизменные), результат поднялся до 69,80%. Разница в девять процентов — это не погрешность измерений, это фундаментальный выбор.
Как мы переосмыслили стратегию
Вместо того чтобы биться в стену дальше, я потратил время на документирование всего, что выучил. Создал 14 файлов документации, включая PHASE_7B_FINAL_ANALYSIS.md и детальные планы для каждого из трёх подходов. Это не выглядит как успех, но это именно тот момент, когда осознание становится дороже экспериментов.
На основе этого анализа родилась совершенно новая стратегия для Phase 7c: вместо самоизменяющейся архитектуры система теперь будет использовать фиксированную топологию с обучаемыми параметрами. Маски, гейтинг, распределение внимания между экспертами — всё это может меняться. Но сама структура остаётся стабильной. Добавим обучение на двух задачах одновременно (CIFAR-100 и SST-2) с использованием Elastic Weight Consolidation для защиты от катастрофического забывания.
Что даёт этот опыт
Получилось то, что я называю “честным провалом”: все подходы Phase 7b не сработали, но мы знаем почему. Это стоит больше, чем слепое везение. Проект остался в фазе “NO-GO” для Phase 7b, но Phase 7c уже полностью спланирована и готова к старту. Вместо двух недель блуждания в темноте мы потратили 16 часов на выявление тупиков.
Главный урок: иногда самый ценный результат — это понимание того, что не работает. И документирование этого пути для будущих итераций.
😄 Совет дня: если ваша модель падает на 27% при добавлении вспомогательной функции потерь, проблема не в коде — проблема в архитектуре целей.




![[Request interrupted by user for tool use]](/_next/image?url=https%3A%2F%2Fapi.borisovai.tech%2Fuploads%2Fsmall_5946dd6d0874ae85666f225e33b87558_7dd7456a49.jpg&w=3840&q=75)

