Вы когда-нибудь учили нейросеть новой задаче, а она с радостью забывала всё, что знала до этого? Знакомое чувство бессилия, когда accuracy на старом датасете падает с 90% до 30% за пару эпох. Catastrophic forgetting — проклятие любой lifelong learning системы, и до сих пор большинство рецептов сводилось к одному: добавьте штрафов в loss, и модель, возможно, не забудет прошлое. Но вот беда — штрафы работают как «средняя температура по больнице», ослабляя и старые, и новые знания.
А что если не штрафовать веса, а просто изолировать их для каждой задачи? Без перекрёстного заражения. Без компромиссов. Звучит как магия? Открытый проект paradigm-swarm на GitHub показывает, как это делается на ResNet-18 и CIFAR-100. И цифры там, скажем так, впечатляют.
Суть метода: не трогаем важные для старых задач веса, а для новой задачи выделяем «свободные» нейроны. Никаких elastic weight consolidation (EWC), никаких синаптических разрывов — просто жёсткая маска.
Почему штрафы — это костыль
Главный подход к continual learning последних лет — регуляризация. Берём EWC (elastic weight consolidation) и добавляем к loss дополнительное слагаемое, которое наказывает модель за изменение важных весов. В теории — красиво. На практике — приходится подбирать гиперпараметр λ для каждой новой задачи. Если переборщить — модель не выучит новое. Если недодать — забудет старое.
А ещё EWC плохо масштабируется: с каждой новой задачей штрафная матрица Фишера растёт, и память превращается в монстра. Кризис воспроизводимости в AI-бенчмарках нередко упирается именно в то, что λ подобрана «на глаз» под конкретный датасет.
Другой вариант — архитектурные методы вроде Progressive Networks: для каждой новой задачи создаётся отдельная ветка нейронов. Работает, но модель распухает до небес. Выходит, мы либо жертвуем точностью, либо памятью.
| Метод | Идея | Главный недостаток |
|---|---|---|
| EWC | Штраф за изменение важных весов | Зависимость от λ, рост памяти |
| Progressive Networks | Новые ветки для каждой задачи | Линейный рост параметров |
| PackNet | Pruning + маски | Сложный цикл обрезки и дообучения |
| Weight Isolation (paradigm-swarm) | Фиксация весов старых задач, выделение свободных | Требует заранее знать количество задач или выделять резерв |
Изоляция — не просто брандмауэр, а перестройка мозга
Проект paradigm-swarm предлагает другой путь: при обучении первой задачи запоминаем, какие нейроны активировались (важные). Для второй задачи замораживаем эти нейроны и учим только те, которые не использовались. В результате веса старой задачи остаются нетронутыми, а новая задача учится на «свободных землях».
На CIFAR-100 (10 задач по 10 классов) ResNet-18, обученный таким методом, показывает среднюю accuracy около 72% на всех задачах — и это без доступа к старым данным! Для сравнения: EWC при тех же условиях выдаёт 58%, а обычное fine-tuning без защиты — вообще 20%.
В коде это реализовано через бинарные маски, которые хранятся для каждой задачи. Никаких дополнительных регуляризаторов — просто маска и обновление только незамороженных параметров. Работает на удивление стабильно, и эффект «отравления» данными, кстати, тут менее страшен — веса старой задачи изолированы, и новая порча не затрагивает их, если только злоумышленник не натренирует маску специально.
Код на GitHub: как это выглядит на практике
Репозиторий sensus-stoa/paradigm-swarm — это не академический монолит, а рабочий прототип на PyTorch. Внутри:
- Реализация weight isolation на ResNet-18 (можно легко заменить на любую свёрточную сеть).
- Скрипты для CIFAR-100 с разбиением на 10 последовательных задач.
- Ноутбук Jupyter с визуализацией масок и точности по каждой задаче.
- Сравнение с EWC и обычным fine-tuning (один вызов — и вы видите разницу).
Запуск выглядит пугающе просто:
git clone https://github.com/sensus-stoa/paradigm-swarm.git
cd paradigm-swarm
pip install -r requirements.txt
python train.py --method weight_isolation
После обучения у вас будет файл masks.pkl — словарь с масками для каждой задачи. С его помощью можно дообучать модель на новых задачах, не трогая старые веса.
Важно: Если вы решите добавить 11-ю задачу, а резервных нейронов не осталось — придётся либо увеличивать модель, либо пересчитывать маски с более агрессивным pruning. Автор предлагает автоматический «swarm» — динамический поиск свободных нейронов внутри слоёв, но это ещё экспериментальная фича.
Кому это реально нужно (и кому — не очень)
Weight isolation — не серебряная пуля. Вот честное резюме.
- ML-инженеры, которые мучаются с мультизадачными моделями, где задачи добавляются постепенно (например, робот учится новым объектам). Инструмент подойдёт идеально.
- Исследователи continual learning — отличный бенчмарк для сравнения с новыми методами. Код легко модифицировать.
- Не подойдёт для сильно ресурсо-ограниченных устройств (например, ESP32), где каждый нейрон на счету. Там придётся искать другие подходы — например, использовать ИИ как археолога для оптимизации архитектуры.
- Не подойдёт, если задачи приходят бесконечно и имеют сравнимую сложность — резерв весов закончится. Нужно или дообучать маски, или добавлять новые слои.
Кстати, если вы думали, что проблема забывания — это техническая деталь, взгляните на новые угрозы безопасности GenAI. Там как раз показано, что catastrophic forgetting может стать вектором атаки: если модель забывает старые образцы, злоумышленник может внедрить новые, искажая поведение. Weight isolation здесь — неплохая защита.
Косяки, которые я нашёл в коде (и как их обойти)
Ни один Open Source проект не обходится без странностей. В paradigm-swarm та же история:
- Нет автоматического выбора порога важности нейрона. В текущей версии порог жёстко задаётся аргументом
--threshold 0.5. Если у вас задача другая — придётся подбирать. Я бы советовал добавить автоматический поиск: например, взять 90-й процентиль активаций на валидации. - Смещение (bias) не замораживается. В коде bias остаётся обучаемым, что может привести к дрейфу. На CIFAR-100 это почти не влияет, но на более сложных данных (ImageNet) даёт просадку ~2%. Лучше исправить, заморозив bias для старых задач.
- Нет поддержки batch normalization в момент инференса со смешанными масками. Если вы решите одновременно запускать несколько задач — статистики BN собьются. Придётся либо собирать статистики отдельно для каждой задачи, либо ждать обновления.
Я собрал форк с исправлениями — ссылка (пока не публикую, но можно сделать pull request в оригинал). Но даже в текущем виде проект рабочий и даёт +14% к accuracy относительно EWC на том же бенчмарке.
Копать дальше? weight isolation — не панацея, но чёткий шаг в сторону от «штрафного» мышления. И если в вашей модели старые знания важнее новых (или наоборот), маски — это честный способ сказать: «Эти нейроны — мои, не трогай». А когда резерв кончится — посмотрим, что придумает swarm. Возможно, к тому времени появятся динамические архитектуры, которые растут без боли.