Игорь Градов
Игорь Градов
6 мин
ai

Нейросети CIFAR на Cortex-M0+ теряют до 40% точности: пять багов и их исправления

Нейросети на микроконтроллерах ARM Cortex-M0+ теряют от 30 до 40 процентов точности из-за багов квантизации и особенностей компилятора GCC, и в этом разборе собраны конкретные исправления, которые возвращают потерянное качество на датасетах вроде CIFAR-10.

Нейросети CIFAR на Cortex-M0+ теряют до 40% точности: пять багов и их исправления
Почему это важно

Квантизация (сжатие весов модели из 32-битных чисел в 2-битные тернарные значения) позволяет запускать нейросети cifar на устройствах без математического сопроцессора, но скрытые баги обнуляют веса и ломают точность, причём ошибки проявляются только на целевом железе, а не в Python.

Автор проекта Fakeonomics опубликовал детальный разбор пяти архитектур нейросетей, которые он довёл до работы на ARM Cortex-M0+, микроконтроллере без аппаратной поддержки операций с плавающей точкой (FPU). Полный пайплайн замкнут: обучение в Python, экспорт, генерация кода на C11, компиляция через arm-gcc, запуск в эмуляторе Unicorn. 192 файла, 34 тысячи строк кода, 95 тестов. Три из пяти архитектур показали прирост точности после исправлений, две не взлетели по архитектурным причинам.

Что понадобится

  • Среда для обучения моделей в Python (PyTorch или аналог)
  • Компилятор arm-none-eabi-gcc для сборки под ARM Cortex-M0+
  • Эмулятор Unicorn для прогона бинарников без реального железа
  • Датасеты: MNIST, Fashion-MNIST или CIFAR-10
  • Время: обучение одной модели занимает от 20 до 49 минут в зависимости от архитектуры и числа эпох

Пять багов, которые крадут точность, и как их чинить

  1. Проверьте таблицу тернарного маппинга. В кодогенераторе для свёрточных сетей (CNN) третий элемент таблицы ternary_map[2] был равен нулю вместо +1. Это значит, что при распаковке весов из сжатого формата все значения +1 молча превращались в ноль, и модель работала с испорченными весами. Исправление: убедитесь, что ternary_map содержит ровно три значения: -1, 0, +1.
// Было (баг):
const int8_t ternary_map[3] = {-1, 0, 0};
// Стало (исправлено):
const int8_t ternary_map[3] = {-1, 0, 1};
  1. Отключите встроенные функции GCC флагом -fno-builtin. При оптимизации -O2 компилятор GCC превращает цикл while(n--) внутри memset в рекурсивный вызов bl memset. На Cortex-M0+ это приводит к бесконечному циклу и зависанию. Добавьте флаг при сборке:
arm-none-eabi-gcc -mcpu=cortex-m0plus -O2 -fno-builtin -o model.bin model.c
  1. Замените простое приведение типа на явное ограничение диапазона (saturation). Выражение (int8_t)(acc >> 7) при переполнении даёт мусор. Нужна функция sat_q7(), которая ограничивает значение диапазоном от -128 до 127 перед приведением к int8_t.
static inline int8_t sat_q7(int32_t val) {
    if (val > 127) return 127;
    if (val < -128) return -128;
    return (int8_t)val;
}
  1. Расширьте тип индекса выхода с uint8 до uint16. Если в модели больше 255 нейронов на выходном слое, индексы 834 и выше не помещаются в 8-битную переменную. Результат: неверная классификация, которая выглядит как «модель плохо обучилась», хотя виноват тип данных.

  2. Добавьте обучаемое масштабирование для Vision Transformer (ViT). Тернарные значения в проекциях Q, K, V (query, key, value, три проекции входных данных в механизме внимания) без нормализации дают дисперсию на порядки выше нормы. Функция softmax вырождается в «горячий» вектор, градиенты обнуляются, модель не учится. Решение: пять обучаемых параметров масштабирования.

self.log_scale_qk = nn.Parameter(torch.zeros(1))
self.log_scale_v = nn.Parameter(torch.zeros(1))
self.log_scale_o = nn.Parameter(torch.zeros(1))
self.log_scale1 = nn.Parameter(torch.zeros(1))
self.log_scale2 = nn.Parameter(torch.zeros(1))

Какие результаты дали исправления?

  • GraphKAN на MNIST: после перехода на полный датасет (60 тысяч примеров вместо 10 тысяч) и исправления бага с ternary_map точность составила 94.46% за 20 эпох обучения с плавающей точкой плюс 5 эпох STE (Straight-Through Estimator, метод обратного распространения градиентов через дискретные значения)
  • Fashion-MNIST: с 76.6% до 86.73% при 30 эпохах плюс 10 эпох STE, полный датасет, 49 минут обучения
  • CNN на Fashion-MNIST: аугментация данных (искусственное расширение обучающей выборки поворотами, сдвигами) плюс cosine annealing (плавное снижение скорости обучения по косинусоиде) дали 90.54% при сжатии модели в 16 раз. Тернарная версия не потеряла точность по сравнению с float, а выиграла 0.44 процентных пункта
  • ViT на CIFAR-10: 60.30% при размере модели 25.4 КБ. Для микроконтроллера без FPU это рабочий результат, хотя и далёк от лучших показателей на полноценном оборудовании
  • RNN и LSTM: не взлетели. 18.2% и 20.64% соответственно, при float на той же архитектуре около 25%. Причина не в тернарности, а в малом размере скрытого слоя: hidden_dim=64 не справляется с 28 шагами по пикселям, нужно 128 или 256, что увеличивает число параметров в 4 и 8 раз

Что делать с этим прямо сейчас?

Если вы разработчик встраиваемых систем: проверьте таблицу маппинга и тип индексов в первую очередь. Эти баги не ловятся юнит-тестами на стороне Python, только bit-exact прогон на эмуляторе или железе покажет проблему.

Если вы автор на Дзене и пишете про нейросети cifar или edge AI: этот кейс даёт конкретные цифры для контента: сжатие в 16 раз, модель в 25 КБ, точность 90% на Fashion-MNIST. Это понятные читателю числа, которые показывают, что ИИ работает не только в облаке.

Если вы предприниматель и думаете об ИИ на устройствах: тернарные модели помещаются в дешёвые микроконтроллеры ценой менее доллара. Но путь от обученной модели до рабочей прошивки требует именно такой ручной отладки, готовых коробочных решений пока нет.

Как это выглядит на практике

Автор обучил свёрточную сеть на Fashion-MNIST по схеме 10+20+5+10 эпох. Первые 10 эпох обучение с аугментацией и высокой скоростью обучения. Следующие 20 эпох с cosine annealing. Затем 5 эпох квантизации через STE. Финальные 10 эпох тонкая подстройка тернарной модели. Результат: 90.54% точности, сжатие в 16 раз. При этом тернарная модель оказалась на 0.44 процентных пункта точнее, чем версия с плавающей точкой, что контринтуитивно, но объяснимо: квантизация выступила как регуляризатор (метод борьбы с переобучением).

Частые ошибки

Первая: проверять точность только в Python. Баг с ternary_map и переполнение sat_q7 проявляются только после компиляции и запуска C-кода. Без bit-exact сверки результатов Python и эмулятора вы не увидите потерю 30 и более процентов точности.

Вторая: использовать флаг оптимизации -O2 без -fno-builtin. На x86 это безвредно, на Cortex-M0+ приводит к зависанию через рекурсию в memset.

Третья: пытаться запустить RNN или LSTM с маленьким скрытым слоем на последовательных задачах. Проблема не в квантизации, а в том, что 64 нейрона недостаточно для 28 временных шагов. Увеличение до 128 или 256 решает задачу, но кратно раздувает модель.

Мнение редакции dzen.guru

Этот проект показывает реальную цену запуска ИИ на копеечном железе: не «скачал библиотеку и заработало», а 34 тысячи строк кода и ручная охота за багами, которые теряют точность молча. По моим наблюдениям, большинство туториалов по edge AI заканчиваются на этапе «экспортировали модель», а самое ценное начинается дальше. Честная оговорка: результаты получены на эмуляторе Unicorn, а не на реальном микроконтроллере. На железе могут появиться дополнительные проблемы с таймингами и памятью. Кроме того, ViT с 60% на CIFAR-10 пока далёк от практического применения, но сам факт, что трансформер влезает в 25 КБ и работает без FPU, заслуживает внимания.

Хотите разобраться в нейросетях глубже?

Подписывайтесь на канал dzen.guru, чтобы получать разборы технологий ИИ с конкретными цифрами и применимыми советами.

Подписаться

Путь от Python-модели до рабочей прошивки на Cortex-M0+ усеян ловушками, которые не описаны ни в одном стандартном туториале, и именно поэтому этот разбор ценен: он перечисляет грабли поимённо, с кодом и цифрами, а не обещает, что «всё заработает из коробки».

Поделиться:TelegramVK
Игорь Градов
Игорь Градов

Основатель dzen.guru. Эксперт по монетизации и продвижению на Дзен. Автор курса «Старт на Дзен 2026».

Комментарии

Читайте также

Минторг США обвинил ASML в утечке чипов в Китай, но не показал доказательств
ai

Минторг США обвинил ASML в утечке чипов в Китай, но не показал доказательств

Компания ASML (производитель литографического оборудования, без которого невозможно выпускать самые передовые чипы в мире) оказалась в центре конфликта с…

5 мин
Midjourney строит сканер тела на 500 000 датчиков, а генератор картинок открыла бесплатно
ai

Midjourney строит сканер тела на 500 000 датчиков, а генератор картинок открыла бесплатно

Midjourney, компания, которую знают по генерации картинок, 4 июня 2025 года объявила о запуске медицинского сканера тела, работающего на ультразвуке и…

5 мин
США обязали Anthropic Claude отозвать две модели: найден обход защиты
ai

США обязали Anthropic Claude отозвать две модели: найден обход защиты

Правительство США на прошлой неделе обязало компанию Anthropic отозвать две новейшие модели, Claude by Anthropic, Fable 5 и Mythos 5, сославшись на угрозу…

4 мин