Prompt utilisé pour régénérer cette page :
Page: Kohonen — Self-Organizing Map (SOM) Visualization
Category: sandbox
Description: "Self-Organizing Map (SOM) - color space topology learning"
Icon: "grid"
Tags: ["neural-network", "som", "visualization", "machine-learning"]
Status: ["validated"]
Front matter (index.md):
---
title: "Kohonen"
description: "Self-Organizing Map (SOM) - color space topology learning"
icon: "grid"
tags: ["neural-network", "som", "visualization", "machine-learning"]
status: ["validated"]
---
Directory structure:
- index.md — page content (HTML UI)
- default.js — single JS file (~950 lines, all classes inline)
- default.scss — SCSS styles
HTML structure (index.md body):
div.kohonen-app wrapping two panels:
1. div.canvas-panel:
- section.container.visual.size-600.ratio-1-1.canvas-contain containing canvas#som-canvas
- div.view-toggle: two buttons — #btn-view-som (class "active") and #btn-view-umatrix
2. div.sidebar with 5 cards (div.card each with h3 title):
Card 1 — "Statistics":
- div.stats-grid (2-column grid) with 4 stat items:
- Iteration (#stat-iter, default "0")
- Learning Rate (#stat-lr, default "--")
- Radius (#stat-radius, default "--")
- Grid (#stat-grid, default "30x30")
- div.input-color-row: color swatch (#swatch-input) + label (#label-input "Input: --")
- div.input-color-row: color swatch (#swatch-bmu) + label (#label-bmu "BMU: --")
Card 2 — "Transport":
- div.btn-row: 3 buttons — #btn-play, #btn-pause, #btn-reset
Card 3 — "Parameters":
- 4 control-row divs, each with label (containing span.val for live value) + input[type=range]:
- Speed (iter/frame): #slider-speed, min=1 max=100 value=10, #val-speed
- Grid size: #slider-grid, min=10 max=50 value=30, #val-grid
- Initial learning rate: #slider-lr, min=10 max=100 value=50, #val-lr (display as /100)
- Initial radius: #slider-radius, min=1 max=25 value=15, #val-radius
Card 4 — "Data Mode":
- select#select-mode with 4 options:
- "random" — Uniform Random Colors
- "palette" — Restricted Palette (8 colors)
- "gradient" — Linear Gradient (Red-Blue)
- "image" — Image Sampling
- input[type=file]#file-input (accept="image/*", class="hidden", margin-top:8px)
Card 5 — "Visualization":
- div.view-toggle: 3 toggle buttons:
- #btn-toggle-bmu (class "active") — BMU Marker
- #btn-toggle-trail — BMU Trail
- #btn-toggle-pulse — Pulse
=== default.js (single file, ~950 lines) ===
No external imports. All classes defined inline.
Utility functions:
- distSq(r1,g1,b1,r2,g2,b2): squared Euclidean distance in RGB space (avoids sqrt).
- gaussianInfluence(dSq, radiusSq): exp(-dSq / (2*radiusSq)) — Gaussian decay factor.
- clamp(v, lo, hi): bounds a value.
Class Neuron:
- Constructor(x, y): grid position + random RGB weights (0-255).
- randomize(): re-randomizes weights.
- Properties: x, y, r, g, b (flat, no array — performance optimization).
Class SOMGrid:
- Constructor(size): creates size*size Neuron array (flat, row-major).
- findBMU(r,g,b): linear scan of all neurons, returns index of closest by distSq.
- updateWeights(bmuIdx, r,g,b, lr, radius): Gaussian neighborhood update. Computes bounding box (3*radius extent, clamped to grid). For each neuron in box, computes gridDistSq, gaussianInfluence, factor=lr*influence. Skips if factor < 0.0001. Updates n.r/g/b += factor * (input - n).
- uMatrixValue(x,y): average Euclidean distance to 4 direct neighbors (left/right/up/down). Used for U-Matrix visualization.
Class Trainer:
- Constructor(grid, params): stores grid, initialLR, initialRadius, totalIterations (default 10000), mode, iteration counter, currentLR/Radius, lastInput[3], lastBMU, bmuTrail[] (max 50), palette (8 colors: RGB primaries + CMY + black + white).
- timeConstant = totalIterations / Math.log(initialRadius + 1).
- generateInput(): returns [r,g,b] based on mode:
- 'random': uniform random 0-255 each channel
- 'palette': picks random from 8-color palette
- 'gradient': linear red-to-blue interpolation (t random 0-1)
- 'image': samples random pixel from loaded imageData (fallback to random)
- step(): generates input, finds BMU, records trail position (shift if >50), updates weights, increments iteration, decays LR (exp(-iter/totalIter)) and radius (exp(-iter/timeConstant)). Enforces minimums: radius >= 0.5, LR >= 0.001.
- setImageData(imgData, width, height): stores pixel data for image mode.
Class Renderer:
- Constructor(canvas): gets 2D context. State: viewMode ('som'/'umatrix'), showBMU (true), showTrail (false), showPulse (false), pulsePhase.
- render(grid, trainer, timestamp): dispatches to renderSOM or renderUMatrix, then overlays trail, pulse, BMU marker in that order.
- renderSOM(grid, cellW, cellH): clears canvas, draws each neuron as colored fillRect. Gap=1px if cellW>8, else 0.
- renderUMatrix(grid, cellW, cellH): two-pass — first finds maxDist for normalization, then draws grayscale cells (d/maxDist * 255).
- renderBMUMarker(bmu, cellW, cellH): white circle (radius=0.45*min(cellW,cellH)) + dark outline at +1px.
- renderTrail(trail, cellW, cellH): fading polyline segments, alpha increases with index, color rgba(255,200,50,alpha*0.8), lineWidth 1.5.
- renderPulse(bmu, radius, cellW, cellH, timestamp): pulsing circle around BMU. Pulse = 1 + 0.15*sin(timestamp*0.006). Pixel radius = radius*cellW*pulse. Color rgba(88,166,255,0.5).
Class KohonenApp:
- Constructor: gets canvas#som-canvas, sets canvas resolution 600x600. Creates SOMGrid(30), Trainer, Renderer. Calls bindUI(). Initial render.
- State: running, speed(10), gridSize(30), initialLR(0.5), initialRadius(15), mode('random'), rafId, storedImageData/Width/Height.
- bindUI(): binds all buttons, sliders, select, file input, view toggles, visualization toggles. Grid size slider change updates radius slider max.
- bindToggle(id, callback): generic toggle button helper.
- handleImageUpload(e): creates offscreen canvas (max 256px dimension), extracts ImageData, stores for reuse on reset.
- play(): sets running=true, requestAnimationFrame loop: runs speed*step() per frame, renders, updates stats.
- pause(): cancels RAF, sets running=false.
- reset(): pauses, recreates grid+trainer with current params, restores image data if image mode, renders fresh.
- updateStats(): updates #stat-iter, #stat-lr, #stat-radius, input/BMU color swatches (background + text).
Entry point: const kohonenApp = new KohonenApp();
=== default.scss ===
Layout: .kohonen-app = flex, wrap, center, full width, gap var(--layout-spacing).
.canvas-panel: flex column, center, gap 0.75rem.
#som-canvas: 100% width/height, 1px solid border, 8px radius, image-rendering pixelated.
.sidebar: flex column, gap 0.875rem, min-width 280px, max-width 320px.
.card: surface background, 1px border, 8px radius, padding 0.875rem 1rem. h3: 0.8rem uppercase, muted color.
.stats-grid: 2-column CSS grid, 0.5rem gap.
.stat: flex column. .stat-label: 0.7rem uppercase muted. .stat-value: 1.05rem bold, tabular-nums.
.input-color-row: flex row, center, gap 0.625rem, margin-top 0.5rem.
.color-swatch: 36x36px, 6px radius, 2px border. .color-label: 0.8rem monospace.
.btn-row: flex, 0.5rem gap.
button: surface bg, secondary text, 1px border, 6px radius, 0.4375rem 1rem padding, 0.82rem font, pointer, transition. Hover: surface bg. Active: primary bg+border, inverted text.
.control-row: flex column, 0.25rem gap, 0.375rem margin-bottom. label: flex space-between, 0.78rem muted. .val: bold tabular-nums.
input[type=range]: custom webkit appearance, 4px track, 14px circular thumb (primary color).
select, input[type=file]: secondary bg, surface border, 6px radius, full width, pointer.
.view-toggle: flex, 0.375rem gap, wrap. Buttons: unset flex, smaller padding/font.
.hidden: display none.
Page entièrement générée et maintenue par IA, sans intervention humaine.