JT
  • Home
  • Projects
  • Extras
  • Contact

© 2026 Joshua Tjhie. All rights reserved.

GitHubLinkedInEmail
Back to Projects
  1. Home
  2. Projects
  3. Neural Network Visualizer (Placeholder)
2024-03-15

Neural Network Visualizer (Placeholder)

Real-time training insights with animated node graphs and metric overlays.

Interactive tooling to watch neural networks train with animated layers, metrics, and D3-driven visuals.

ReactD3.jsTensorFlow.js
Neural Network Visualizer (Placeholder)
Neural Network Visualizer (Placeholder) supporting visual

Quick Stats

Role: Frontend Engineer
Duration: 8 weeks
React 19D3 Force LayoutTensorFlow.jsWebGL

Links

Source CodeLive Demo

Neural Network Visualizer

This is a feature-complete demo build. The playground is live — give it a few seconds to warm up the WebGL context on first load.

This project turns raw model data into an interactive playground where you can watch layers activate, weights adjust, and metrics evolve in real time.

Motivation

Most debugging workflows for neural networks are blind: you stare at loss curves and guess what the geometry is doing. I wanted to see the network — edges brightening as gradients flow, nodes clustering by activation magnitude, dead neurons greying out.

The result is something between a debugger and a data visualisation. It surfaces intuition that pure metrics hide.

Architecture

Data streams from TensorFlow.js into a worker thread, which keeps the visualisation buttery smooth even when training larger models.

  1. Train model in TensorFlow.js
  2. Stream weight matrices over postMessage
  3. Render D3 force layout with WebGL-backed nodes
  4. Sync epoch scrubber to the timeline store via useReducer
Training metrics dashboard
Loss and accuracy curves update live alongside confusion matrices.

Worker isolation

The training loop runs in a SharedWorker so multiple browser tabs can observe the same session without re-running computations. Messages are batched every 50 ms to avoid saturating the main thread.

Feature Highlights

  • Animated force-directed graphs with gradient weight edges.
  • Epoch timeline scrubber with playback controls.
  • Heatmaps for layer activations alongside each node cluster.
  • WebGL instancing for fast rendering at scale — 2 000+ nodes stay interactive.
  • Export snapshots as SVG or PNG at any epoch.

Implementation

Screen recording of a training session with node highlights and metric overlays.

The renderEdge function maps weight magnitude to stroke opacity, so high-gradient connections visually dominate the graph during rapid learning phases.

Tech choices

I tried three renderers before settling on WebGL instancing:

  • SVG — readable but collapses past ~300 nodes.
  • Canvas 2D — fast enough but no sub-pixel anti-aliasing on edges.
  • WebGL instancing — handles 2 000+ nodes at 60 fps with smooth weight interpolation.

Using inline code for API surface: the public hook is useSimulation(modelRef, { fps: 30 }), which returns { nodes, links, epoch, isTraining }.

Ambient feedback tones — each layer maps to a frequency bandListen
Your browser does not support the audio element.

Lessons learned

  • Offloading training to a worker makes the 60 fps target achievable, but serialising large weight tensors is the new bottleneck — sparse delta encoding helped.
  • D3's force simulation is not designed for real-time mutation; batching node updates and calling simulation.nodes(updated) once per frame avoids layout thrashing.
  • WebGL instancing requires careful attribute buffer management; I ended up writing a small helper that handles resizing and avoids stale buffer references.

Observability shouldn't stop at metrics dashboards — seeing the structure evolve unlocks intuition.

Launch the playground

Have thoughts?

Curious what others see or think

Feel free to reach out or leave feedback

Share Feedback

Prefer email? joshuatjhie@pm.me