8.9 KiB
Отчёт: модель altai на MNIST
Oct 12, 2026
Модель altai заметно лучше blifat: на полном MNIST без правок она даёт 73,3% верных ответов против 30,9%, а с порогом, подобранным на отдельной валидационной выборке, — 82,5%.
Что это
В примере mnist-learn две модели с одинаковой архитектурой: blifat (нейроны с вещественными параметрами) и altai (нейроны под чип «Алтай»). У altai все веса и пороги умножены на 1000, а перед проверкой сеть квантуется: веса и пороги сжимаются в целые числа в диапазоне ±255, как требует чип.
В прошлом отчёте выяснилось, что blifat теряет точность из-за порога, который застывает после обучения. Здесь проверено, есть ли та же проблема у altai.
Результаты
Все прогоны на одних и тех же 10 000 тестовых картинках, однопоточный CPU-бэкенд. Порог для altai выбран на валидационной выборке (обучающие картинки 50 000–59 999), тестовые картинки в подборе не участвовали.
| Обучение | blifat как есть | altai как есть | altai, act=40, без добавки к порогу |
|---|---|---|---|
| 3 000 | 49,5% | 76,2% | 84,2% |
| 30 000 | 42,0% | 75,6% | 84,1% |
| 60 000 | 30,9% | 73,3% | 82,5% |
Подробнее по altai (верно / ошибки / молчание):
| Обучение | Как есть | С подобранным порогом | Время прогона |
|---|---|---|---|
| 3 000 | 7622 / 1545 / 833 | 8418 / 1521 / 61 | 1–3,5 мин |
| 30 000 | 7563 / 787 / 1650 | 8409 / 1068 / 523 | 5,5–7 мин |
| 60 000 | 7326 / 790 / 1884 | 8247 / 1235 / 518 | 14 мин |
- Почти весь выигрыш даёт ответ на картинки, на которые сеть раньше молчала: на полном MNIST молчаний стало 518 вместо 1884.
- Для сравнения:
blifatс подобранным порогом давал 75,5%, но тот порог подбирался прямо на тесте, так что оценка была оптимистичной.
Полный MNIST, altai с порогом act=40: результаты по цифрам
| Цифра | Верно | Не отвечено | Ложные срабатывания | Precision | Recall |
|---|---|---|---|---|---|
| 0 | 825 | 63 | 92 | 0,900 | 0,929 |
| 1 | 1062 | 2 | 71 | 0,937 | 0,998 |
| 2 | 674 | 127 | 231 | 0,745 | 0,841 |
| 3 | 699 | 142 | 169 | 0,805 | 0,831 |
| 4 | 754 | 27 | 201 | 0,790 | 0,965 |
| 5 | 718 | 34 | 140 | 0,837 | 0,955 |
| 6 | 881 | 22 | 55 | 0,941 | 0,976 |
| 7 | 913 | 31 | 84 | 0,916 | 0,967 |
| 8 | 856 | 47 | 71 | 0,923 | 0,948 |
| 9 | 865 | 23 | 121 | 0,877 | 0,974 |
| Итого | 8247 (82,5%) | 518 | 1235 |
Самые слабые цифры — 2 и 3 (их чаще всего путают), самые надёжные — 1 и 6.
Что выяснилось
- Почему altai лучше. У
blifatпотенциал теряет треть за каждый шаг, и нейрон фактически видит только последние 2–3 шага картинки. Уaltaiутечки нет (potential_leak = 0): нейрон суммирует все 10 шагов, то есть сравнивает с шаблоном всю картинку целиком. - Проблема с порогом та же. Порог входного нейрона — это основная часть плюс добавка, пропорциональная сумме положительных весов. Добавка растёт с длиной обучения (до квантования 1797 → 3008 → 3342 для 3k → 30k → 60k) и застывает на проверке. Поэтому и
altaiтеряет точность при более длинном обучении. - Квантование почти ничего не стоит. После него веса становятся целыми от −6 до +2, и 37–60% из них нули. Но без квантования точность 76,8% против 76,2% (3 000 картинок). Вариант, где веса растягиваются на весь диапазон ±255, а порог масштабируется тем же множителем, дал 76,7%.
- Потенциал переносится между картинками. Между картинками он не сбрасывается, и недобранный заряд переходит на следующую картинку. Сброс в офлайн-симуляции помогал только при высоком пороге; при подобранном пороге выигрыша нет, поэтому в сеть я его не добавлял.
- Лучший порог не зависит от длины обучения. На валидации плато при
actот 20 до 60 и для 3k, и для 30k; выбранact=40для всех. - Altai воспроизводим. Повторные прогоны совпали до картинки (на 30k и 60k), коллапса весов, как у одного прогона
blifat, не было. - Колонки из 20 нейронов и у altai работают как один нейрон: веса внутри колонки идентичны.
Как проверял
- Добавил в пример
altaiвыгрузку весов и порогов входного слоя до и после квантования. - Написал на numpy офлайн-симулятор нейрона AltAI по формулам бэкенда (без утечки, сброс в 0 при спайке, обнуление отрицательного потенциала, округление). Он совпадает с KNP до картинки: например, 8418 / 1521 / 61 и в KNP, и в симуляторе.
- На симуляторе перебрал пороги, утечку и сброс между картинками на валидационной выборке.
- Выбранный вариант подтвердил полными прогонами в KNP; все цифры в таблицах результатов — из KNP.
Что изменено
В examples/mnist-learn/models/altai/prepare_network_for_inference.cpp добавлены переменные окружения. Без них пример работает как раньше; изменение видно в git diff, его можно откатить.
| Переменная | Что делает |
|---|---|
KNP_MNIST_THR |
заменяет порог входных нейронов на проверке (в единицах после квантования) |
KNP_MNIST_ADD_THR_SCALE |
умножает добавку к порогу входных нейронов на проверке (0 — убрать) |
KNP_MNIST_QUANT |
none — без квантования, weights — масштаб только по весам |
KNP_MNIST_DUMP=<папка> |
сохраняет веса и пороги до (float_*.csv) и после (quant_*.csv) квантования |
Как запускать
cd ~/run/exp
# лучший вариант для полного MNIST
MODEL=altai ./run.sh myrun 60000 KNP_MNIST_THR=40 KNP_MNIST_ADD_THR_SCALE=0
cat myrun/result.csv
| Путь | Что внутри |
|---|---|
~/run/exp/tr<N>.bin, tr<N>.target |
N обучающих картинок + одни и те же 10 000 тестовых |
~/run/exp/val<N>.bin, val<N>.target |
N обучающих картинок + валидация (картинки 50 000–59 999) |
~/run/exp/run.sh |
запуск: MODEL=altai run.sh <имя> <N> [ПЕРЕМЕННАЯ=значение] |
~/run/exp/altai*/ |
результаты прогонов altai и выгрузка весов |
Следующие шаги
- Исправить порог в самом обучении, а не только на проверке
- Использовать колонки по-настоящему: развести 20 нейронов колонки, чтобы они учили разные варианты написания цифры
- Запустить altai на GPU, когда заработает GPU-бэкенд