Visualizer: shift buttons and all-nets answer line; page with augmented net B
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
e5d50c8d65
commit
27279ab242
2 changed files with 504 additions and 3 deletions
44
viz/app.html
44
viz/app.html
|
|
@ -109,7 +109,7 @@ table.conf td { color: var(--fg); }
|
||||||
<header>
|
<header>
|
||||||
<div>
|
<div>
|
||||||
<h1>Колонки AltAI</h1>
|
<h1>Колонки AltAI</h1>
|
||||||
<p class="lead">Как сеть mnist-learn на нейронах AltAI узнаёт цифру. Картинка превращается в спайки, 784 пикселя заряжают входные нейроны, и первая колонка, дошедшая до порога, голосует за свою цифру.</p>
|
<p class="lead">Как сеть mnist-learn на нейронах AltAI узнаёт цифру. Картинка превращается в спайки, 784 пикселя заряжают входные нейроны, и первая колонка, дошедшая до порога, голосует за свою цифру. Кнопки сдвига двигают картинку на пиксель: так видно, насколько сеть держится за точное положение цифры.</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="stack" style="gap:6px">
|
<div class="stack" style="gap:6px">
|
||||||
<span class="label">Сеть</span>
|
<span class="label">Сеть</span>
|
||||||
|
|
@ -126,6 +126,14 @@ table.conf td { color: var(--fg); }
|
||||||
<span class="note" id="srcnote">Нарисуйте цифру</span>
|
<span class="note" id="srcnote">Нарисуйте цифру</span>
|
||||||
</div>
|
</div>
|
||||||
<p class="note">Рисунок уменьшается до 28×28 и перерисовывается тонкой линией, как в MNIST: размер и толщина вашего штриха не важны.</p>
|
<p class="note">Рисунок уменьшается до 28×28 и перерисовывается тонкой линией, как в MNIST: размер и толщина вашего штриха не важны.</p>
|
||||||
|
<div class="row" role="group" aria-label="Сдвинуть картинку на 1 пиксель">
|
||||||
|
<span class="label">Сдвиг</span>
|
||||||
|
<button class="btn" id="sh-left" aria-label="Влево">←</button>
|
||||||
|
<button class="btn" id="sh-right" aria-label="Вправо">→</button>
|
||||||
|
<button class="btn" id="sh-up" aria-label="Вверх">↑</button>
|
||||||
|
<button class="btn" id="sh-down" aria-label="Вниз">↓</button>
|
||||||
|
<span class="mono note" id="shiftlabel">0, 0</span>
|
||||||
|
</div>
|
||||||
<span class="label">Тестовые картинки MNIST</span>
|
<span class="label">Тестовые картинки MNIST</span>
|
||||||
<div class="gallery" id="gallery"></div>
|
<div class="gallery" id="gallery"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -160,6 +168,7 @@ table.conf td { color: var(--fg); }
|
||||||
<span style="--c: var(--spike-soft)">спайкал раньше</span>
|
<span style="--c: var(--spike-soft)">спайкал раньше</span>
|
||||||
<span style="--c: var(--muted)">справа: голоса колонки</span>
|
<span style="--c: var(--muted)">справа: голоса колонки</span>
|
||||||
</div>
|
</div>
|
||||||
|
<p class="note" id="allnets"></p>
|
||||||
<p class="note" id="inhibnote"></p>
|
<p class="note" id="inhibnote"></p>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
@ -170,7 +179,7 @@ table.conf td { color: var(--fg); }
|
||||||
<h2>Чему научилась колонка</h2>
|
<h2>Чему научилась колонка</h2>
|
||||||
<div class="seg" id="digits" role="group" aria-label="Цифра"></div>
|
<div class="seg" id="digits" role="group" aria-label="Цифра"></div>
|
||||||
</div>
|
</div>
|
||||||
<p class="note">Каждый квадрат — веса одного нейрона колонки к 784 пикселям. Оранжевое возбуждает нейрон, синее тормозит. В исходной сети все нейроны колонки одинаковые; с разбросом стартовых весов каждый учит свой вариант написания.</p>
|
<p class="note">Каждый квадрат — веса одного нейрона колонки к 784 пикселям. Оранжевое возбуждает нейрон, синее тормозит. Благодаря разбросу стартовых весов каждый нейрон колонки учит свой вариант написания.</p>
|
||||||
<div id="mapblocks" class="stack"></div>
|
<div id="mapblocks" class="stack"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="panel stack">
|
<div class="panel stack">
|
||||||
|
|
@ -305,10 +314,39 @@ function play() {
|
||||||
}
|
}
|
||||||
function stop() { clearInterval(timer); timer = null; $("play").textContent = "▶ Пуск"; }
|
function stop() { clearInterval(timer); timer = null; $("play").textContent = "▶ Пуск"; }
|
||||||
|
|
||||||
function setImage(img, label, note) { image = img; imageLabel = label; $("srcnote").textContent = note; recompute(); if (!timer) { step = -1; play(); } }
|
// --- shift: the source image moves by whole pixels, empty edge fills with black ---
|
||||||
|
let baseImage = null, shift = [0, 0];
|
||||||
|
function shifted(img, dx, dy) {
|
||||||
|
const out = new Uint8Array(PIX);
|
||||||
|
for (let y = 0; y < 28; y++) for (let x = 0; x < 28; x++) { const sx = x - dx, sy = y - dy; if (sx >= 0 && sx < 28 && sy >= 0 && sy < 28) out[y * 28 + x] = img[sy * 28 + sx]; }
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
function applyShift() {
|
||||||
|
if (!baseImage) return;
|
||||||
|
image = shifted(baseImage, ...shift);
|
||||||
|
$("shiftlabel").textContent = `${shift[0]}, ${shift[1]}`;
|
||||||
|
showOnDraw(image); recompute(); if (!timer) { step = -1; play(); }
|
||||||
|
}
|
||||||
|
[["sh-left", -1, 0], ["sh-right", 1, 0], ["sh-up", 0, -1], ["sh-down", 0, 1]].forEach(([id, dx, dy]) => {
|
||||||
|
$(id).onclick = () => { shift = [Math.max(-4, Math.min(4, shift[0] + dx)), Math.max(-4, Math.min(4, shift[1] + dy))]; applyShift(); };
|
||||||
|
});
|
||||||
|
|
||||||
|
function setImage(img, label, note) {
|
||||||
|
baseImage = img; image = img; imageLabel = label; shift = [0, 0]; $("shiftlabel").textContent = "0, 0";
|
||||||
|
$("srcnote").textContent = note; recompute(); if (!timer) { step = -1; play(); }
|
||||||
|
}
|
||||||
|
function renderAllNets() {
|
||||||
|
if (models.length < 2) { $("allnets").textContent = ""; return; }
|
||||||
|
$("allnets").textContent = "Итог всех сетей: " + models.map(m => {
|
||||||
|
const v = (m === model ? trace : simulate(image, m))[STEPS - 1].votes, a = argmax(v);
|
||||||
|
const mark = imageLabel === null || a < 0 ? "" : a === imageLabel ? " ✓" : " ✗";
|
||||||
|
return `${m.name} — ${a < 0 ? "нет ответа" : a}${mark}`;
|
||||||
|
}).join(" · ");
|
||||||
|
}
|
||||||
function recompute() {
|
function recompute() {
|
||||||
if (!image) return;
|
if (!image) return;
|
||||||
trace = simulate(image, model);
|
trace = simulate(image, model);
|
||||||
|
renderAllNets();
|
||||||
firstWinner = -1;
|
firstWinner = -1;
|
||||||
for (const s of trace) { const j = s.fired.indexOf(1); if (j >= 0) { firstWinner = j; break; } }
|
for (const s of trace) { const j = s.fired.indexOf(1); if (j >= 0) { firstWinner = j; break; } }
|
||||||
digit = firstWinner >= 0 ? Math.floor(firstWinner / model.col) : (imageLabel ?? digit);
|
digit = firstWinner >= 0 ? Math.floor(firstWinner / model.col) : (imageLabel ?? digit);
|
||||||
|
|
|
||||||
463
viz/aug_viz.html
Normal file
463
viz/aug_viz.html
Normal file
File diff suppressed because one or more lines are too long
Loading…
Add table
Reference in a new issue