Wiki: remove out-of-context project details, define terms

Drop the ON/OFF aside, the 8-replica anecdote and "next step" wording;
explain the per-line spike rule, define drawn-digit accuracy, separate
GoldenModel accuracy from counter verification, and phrase backend and
neuron-flag notes without project-internal references.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XFVgZ8Nct8BEh9k7bjuRdw
This commit is contained in:
int 2026-10-19 08:42:01 +00:00
parent 917808edda
commit 69ad76bde2
No known key found for this signature in database

View file

@ -12,7 +12,7 @@ import sys
from pathlib import Path from pathlib import Path
from docslib import HeaderButton, build, run from docslib import HeaderButton, build, run
from docslib.components import Callout, Code, Details, H1, H2, H3, List, LocalLink, P, Table from docslib.components import Callout, Code, H1, H2, H3, List, LocalLink, P, Table
from docslib.hooks import Component, Page from docslib.hooks import Component, Page
HERE = Path(__file__).resolve().parent HERE = Path(__file__).resolve().parent
@ -194,10 +194,10 @@ def neuron_page():
"если потенциал ниже отрицательного порога — при saturate он упирается в этот порог.", "если потенциал ниже отрицательного порога — при saturate он упирается в этот порог.",
], ordered=True), ], ordered=True),
Table(["Флаг", "Что делает", "Как используется"], [ Table(["Флаг", "Что делает", "Как используется"], [
["is_diff", "после выстрела вычитает порог, остаток сохраняется", "в наших сетях: точный счёт заряда"], ["is_diff", "после выстрела вычитает порог, остаток сохраняется", "заряд сверх порога не теряется"],
["is_reset", "после выстрела сбрасывает потенциал в значение сброса", "штатный пример KNP"], ["is_reset", "после выстрела сбрасывает потенциал в значение сброса", "штатный пример KNP"],
["saturate", "не даёт потенциалу уйти ниже отрицательного порога", "отрицательный порог 0: уровень не ниже нуля"], ["saturate", "не даёт потенциалу уйти ниже отрицательного порога", "отрицательный порог 0: уровень не ниже нуля"],
["leak_rev", "утечка всегда тянет потенциал к нулю", "в наших сетях утечка 0"], ["leak_rev", "утечка всегда тянет потенциал к нулю", "при нулевой утечке нейрон копит заряд всю картинку"],
]), ]),
Callout("Все числа нейрона целые, потенциал — 16 бит со знаком (от −32 768 до 32 767). " Callout("Все числа нейрона целые, потенциал — 16 бит со знаком (от −32 768 до 32 767). "
"Сеть, у которой сумма входов за такт выходит за этот диапазон, на чипе не заработает.", title="Ограничение", kind="note"), "Сеть, у которой сумма входов за такт выходит за этот диапазон, на чипе не заработает.", title="Ограничение", kind="note"),
@ -219,11 +219,6 @@ def coding_page():
]), ]),
P("Частотный код проще: число спайков приближённо равно активации обычной нейросети, поэтому её веса можно перенести. " P("Частотный код проще: число спайков приближённо равно активации обычной нейросети, поэтому её веса можно перенести. "
"Временной код экономнее, но нейроны должны реагировать на порядок прихода спайков, поэтому сеть учат прямо на динамике."), "Временной код экономнее, но нейроны должны реагировать на порядок прихода спайков, поэтому сеть учат прямо на динамике."),
Details("Почему вход ON/OFF не нужен сети, обученной на компьютере",
"Канал OFF стреляет на пустых пикселях, его значение равно «255 − яркость». У нейрона с весами разного знака и смещением "
"это уже выражается через канал ON, поэтому нового сигнала OFF не даёт, а входов и спайков становится вдвое больше. "
"Проверка на нативной сети: 96,3% с ON/OFF против 97,7% без него. Колонкам STDP такой сигнал нужен, но они "
"от лишних спайков замолкают."),
] ]
@ -264,8 +259,8 @@ def learning_page():
H2("Сравнение способов"), H2("Сравнение способов"),
Table(["Способ", "Где идёт", "Чему учит", "Цифры MNIST"], [ Table(["Способ", "Где идёт", "Чему учит", "Цифры MNIST"], [
["STDP (классический)", "в KNP", "частые узоры, без меток", "—"], ["STDP (классический)", "в KNP", "частые узоры, без меток", "—"],
["STDP с ресурсом + дофамин (колонки KNP)", "в KNP", "«похоже на мою цифру»", "≈92%"], ["STDP с синаптическим ресурсом и дофамином: вес растёт с насыщением, награда закрепляет изменения", "в KNP", "«похоже на мою цифру»", "≈92%"],
["Дофамин по ошибке (дельта-правило)", "в KNP", "один слой по ошибке ответа", "≈94,8% (валидация)"], ["Дофамин по ошибке: связь меняется на разницу «должен был выстрелить» минус «выстрелил»", "в KNP", "один слой по ошибке ответа", "≈94,8% (валидация)"],
["Перенос обычной сети", "на компьютере", "всю сеть обратным распространением по аналоговой копии", "97,8%"], ["Перенос обычной сети", "на компьютере", "всю сеть обратным распространением по аналоговой копии", "97,8%"],
["Суррогатный градиент по тактам", "на компьютере", "всю сеть прямо на динамике спайков", "97,4% за 8 тактов"], ["Суррогатный градиент по тактам", "на компьютере", "всю сеть прямо на динамике спайков", "97,4% за 8 тактов"],
]), ]),
@ -315,13 +310,13 @@ def backends_page():
["CPU, один поток", "LIF, BLIFAT, AltAILIF и STDP-варианты", "да", "эталон"], ["CPU, один поток", "LIF, BLIFAT, AltAILIF и STDP-варианты", "да", "эталон"],
["CPU, много потоков", "LIF, BLIFAT", "частично", "AltAILIF не поддерживает"], ["CPU, много потоков", "LIF, BLIFAT", "частично", "AltAILIF не поддерживает"],
["CUDA (официальный)", "BLIFAT", "нет", "AltAILIF не поддерживает"], ["CUDA (официальный)", "BLIFAT", "нет", "AltAILIF не поддерживает"],
["CUDA для AltAILIF (наш)", "AltAILIF, Delta", "нет", "побайтно совпадает с CPU; при угрозе потери точности float32 падает с ошибкой"], ["CUDA для AltAILIF (разработан в проекте)", "AltAILIF, Delta", "нет", "результат побайтно совпадает с CPU, в 5 раз быстрее на больших наборах"],
["Алтай: GoldenModel и чип", "AltAILIF, Delta", "нет", "закрытая библиотека Мотив НТ, deb-пакет 1.0.2"], ["Алтай: GoldenModel и чип", "AltAILIF, Delta", "нет", "закрытая библиотека Мотив НТ, deb-пакет 1.0.2"],
]), ]),
Table(["Модель нейрона", "Что это", "Где исполняется"], [ Table(["Модель нейрона", "Что это", "Где исполняется"], [
["LIF", "классический нейрон с утечкой", "CPU"], ["LIF", "классический нейрон с утечкой", "CPU"],
["BLIFAT", "расширенная модель Kaspersky: адаптивный порог, торможение", "CPU, CUDA"], ["BLIFAT", "расширенная модель Kaspersky: адаптивный порог, торможение", "CPU, CUDA"],
["AltAILIF", "ровно возможности нейрона Алтая", "CPU, наш CUDA, Алтай"], ["AltAILIF", "ровно возможности нейрона Алтая", "CPU, CUDA проекта, Алтай"],
]), ]),
P("Для распознавателя на Алтае имеет значение только AltAILIF с синапсами Delta: остальные модели на чип не переносятся."), P("Для распознавателя на Алтае имеет значение только AltAILIF с синапсами Delta: остальные модели на чип не переносятся."),
] ]
@ -374,7 +369,7 @@ def rules_page():
["один тип связи, знак в весе", "торможение — отрицательный вес"], ["один тип связи, знак в весе", "торможение — отрицательный вес"],
["потенциал 16 бит со знаком", "сумма входов за такт ограничена"], ["потенциал 16 бит со знаком", "сумма входов за такт ограничена"],
["начальный потенциал игнорируется", "смещение подаётся отдельными входными спайками"], ["начальный потенциал игнорируется", "смещение подаётся отдельными входными спайками"],
["одинаковые номера входа в одном такте склеиваются", "каждой линии свой номер"], ["два спайка по одной входной линии в одном такте считаются одним", "если нужно подать несколько событий за такт, у каждого своя линия"],
["обучения нет", "веса загружаются готовыми"], ["обучения нет", "веса загружаются готовыми"],
]), ]),
H2("Квантование"), H2("Квантование"),
@ -398,9 +393,9 @@ def placement_page():
["GoldenModel", "размещение и правила чипа соблюдены, счётчики совпадают"], ["GoldenModel", "размещение и правила чипа соблюдены, счётчики совпадают"],
["Чип AltAI_HW", "работа на железе"], ["Чип AltAI_HW", "работа на железе"],
]), ]),
Callout("Принятие сети размещателем ещё не доказывает правильность. Конфигурация с 8 копиями сети в сетке 4×4 " Callout("То, что размещатель принял сеть, ещё не доказывает её правильность: размещение может пройти, а счёт — разойтись "
"была принята, но счётчики спайков разошлись с эталоном. Критерий — совпадение счётчиков каждого нейрона.", "с эталоном. Критерий — совпадение счётчика спайков каждого нейрона во всех ступенях.",
title="Наблюдение", kind="note"), title="Критерий", kind="note"),
] ]
@ -487,7 +482,7 @@ def native_page():
"выход заново обучается по настоящим счётчикам спайков скрытого слоя и раскладывается на группы."], ordered=True), "выход заново обучается по настоящим счётчикам спайков скрытого слоя и раскладывается на группы."], ordered=True),
Table(["Свойство", "Значение"], [ Table(["Свойство", "Значение"], [
["Точность на MNIST", "97,8%; с выпрямлением наклона на хосте — 98,0%"], ["Точность на MNIST", "97,8%; с выпрямлением наклона на хосте — 98,0%"],
["Проверка", "KNP CPU и CUDA — все счётчики совпали; GoldenModel — 975 из 1000"], ["Проверка", "KNP на CPU и CUDA и GoldenModel: счётчики спайков всех нейронов совпали с эталоном (в GoldenModel — на 1000 картинках)"],
["Цена", "≈3200 входных спайков и ≈338 тыс. синаптических событий на картинку"], ["Цена", "≈3200 входных спайков и ≈338 тыс. синаптических событий на картинку"],
]), ]),
] ]
@ -514,9 +509,9 @@ def ticks_page():
"к ошибке добавлен штраф за спайки скрытого слоя — сеть учится молчать, когда может;", "к ошибке добавлен штраф за спайки скрытого слоя — сеть учится молчать, когда может;",
"настройки выбираются по валидации, итог считается отдельным целочисленным симулятором."], ordered=True), "настройки выбираются по валидации, итог считается отдельным целочисленным симулятором."], ordered=True),
Table(["Свойство", "Значение"], [ Table(["Свойство", "Значение"], [
["Точность на MNIST", "97,4%"], ["Имитация рисования мышью", "95,9%"], ["Тактов", "8"], ["Точность на MNIST", "97,4%"], ["Точность на рисунках", "95,9%"], ["Тактов", "8"],
["Входных спайков", "≈143"], ["Синаптических событий", "≈20 тыс. — в 17 раз меньше нативной сети"], ["Входных спайков", "≈143"], ["Синаптических событий", "≈20 тыс. — в 17 раз меньше нативной сети"],
["Проверка", "целочисленный эталон; KNP и GoldenModel — следующий шаг"], ["Проверка", "целочисленный эталон; в KNP и GoldenModel не проверялась"],
]), ]),
] ]
@ -572,6 +567,7 @@ def metrics_page():
H1("Метрики и методика"), H1("Метрики и методика"),
Table(["Метрика", "Определение"], [ Table(["Метрика", "Определение"], [
["Точность", "доля правильных ответов на тесте"], ["Точность", "доля правильных ответов на тесте"],
["Точность на рисунках", "та же доля, но на тестовых цифрах, перерисованных пером постоянной толщины, как при рисовании мышью"],
["Синаптические события", "число сложений «спайк × вес» на одну картинку; главная мера энергии на нейроморфном чипе"], ["Синаптические события", "число сложений «спайк × вес» на одну картинку; главная мера энергии на нейроморфном чипе"],
["Входные спайки", "сколько событий хост отправляет на чип"], ["Входные спайки", "сколько событий хост отправляет на чип"],
["Такты", "длительность распознавания в шагах чипа"], ["Такты", "длительность распознавания в шагах чипа"],
@ -582,8 +578,8 @@ def metrics_page():
"цифра без источника (файл метрик или журнал проверки) не считается результатом;", "цифра без источника (файл метрик или журнал проверки) не считается результатом;",
"разница меньше 0,3 п.п. при одном прогоне — в пределах шума;", "разница меньше 0,3 п.п. при одном прогоне — в пределах шума;",
"точность на тесте MNIST не равна точности на рисунках мышью: это другой «почерк»."]), "точность на тесте MNIST не равна точности на рисунках мышью: это другой «почерк»."]),
P("Для оценки рисования используется имитация: скелет цифры MNIST перерисовывается пером постоянной толщины. " P("Рисунок мышью отличается от рукописной цифры: перо одной толщины, жёсткие края, другая толщина линии. Поэтому точность "
"Нативная сеть теряет на ней около 4 п.п.; обучение на таких копиях и выпрямление сокращают потерю до 2 п.п."), "на рисунках обычно ниже точности на тесте; её сокращают обработкой на хосте и обучением на перерисованных копиях."),
] ]