Продолжение цикла. До этого были базовые цифры и анонс 5 архитектур. Теперь — что сломалось, как чинили, что узнали.
GraphKAN: полный датасет меняет всё
В прошлых постах я показывал 96.15% на MNIST на 10K сабсете. Переход на полный датасет (60K) — 94.46% после 20 эпох float + 5 STE. Нашёл баг: ternary_map[2]=0 — +1 молча обнулялся на unpack.
Fashion-MNIST: 76.6% -> 86.73% (30 эпох float + 10 STE, полный датасет, 49 минут).
CNN Fashion: аугментация + cosine annealing
Было 87-88%. Схема 10+20+5+10 эпох с аугментацией и cosine annealing дала 90.54%. Сжатие 16x. Тернарная версия не потеряла точность — выиграла 0.44 п.п.
ViT: история про взрыв дисперсии
Первая попытка: loss 8.57, accuracy 16.3%. Чуть лучше random. Копаю — attention scores в one-hot, градиенты нулевые. Причина: ternary Q/K/V без нормализации выхода дают variance на порядки выше, чем нужно. Softmax вырождается.
Фикс — learnable per-projection scaling: log_scale_qk, log_scale_v, log_scale_o, log_scale1, log_scale2. Пять параметров, каждый учится гасить variance до входа в softmax.
Результат: 60.30% на CIFAR-10, 25.4 КБ. Не SOTA, но для микроконтроллера без FPU — честно.
RNN/LSTM: не взлетело
SMNIST, 28 шагов по пикселям. RNN: 18.2%. LSTM: 20.64%. Float на той же архитектуре — ~25%. Причина: hidden_dim=64 не тянет 28 шагов. Нужно 128-256, но это 4-8x больше параметров. Тернарность тут ни при чём.
C-кодогенерация: все пять под Unicorn
5 архитектур генерируются в C11, компилируются под cortex-m0plus, прогоняются через Unicorn. Bit-exact для всех.
|
Архитектура |
.bin |
R0 |
Статус |
|---|---|---|---|
|
GraphKAN MNIST |
192 KB |
-88 |
PASS |
|
CNN Fashion |
107 KB |
0 |
PASS |
|
Transformer |
20 KB |
0 |
PASS |
|
LSTM |
17 KB |
-3 |
PASS |
|
ViT CIFAR-10 |
43 KB |
1 |
PASS |
M0+ специфичные грабли
memset recursion с -O2. GCC превращает while(n–) в рекурсивный bl memset. Бесконечный цикл. Лечится -fno-builtin.
sat_q7(). (int8_t)(acc >> 7) — переполнение. Нужна явная saturation.
ternary_map[2]=0. В CNN-кодогенераторе третий элемент (val=2, +1) маппился в 0. Вес обнулялся.
output_idx uint8 -> uint16. Для моделей с >255 нейронов индексы выхода — 834-843. Не влезают в uint8.
Итог
192 файла, 34K строк, 95 тестов. Пайплайн замкнут: Python -> train -> export -> C11 -> arm-gcc -> .bin -> Unicorn. Две модели не взлетели (RNN/LSTM — архитектурное ограничение), остальные работают с приростом точности относительно float.
Ссылки:
2026. Fakeonomics. Все права защищены.
ссылка на оригинал статьи https://habr.com/ru/articles/1050030/