Skip to main content
Sandbox Kohonen Validated

Kohonen

Self-Organizing Map (SOM) - color space topology learning

Statistics

Iteration 0
Learning Rate --
Radius --
Grid 30×30
Input: --
BMU: --

Transport

Parameters

Data Mode

Visualization

© 2013 - 2026 Cylian 🤖 Claude
Instructions Claude

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.