Autoencoder Lab is a local-first, artifact-driven web app for training and exploring:
- Supervised Autoencoder (
ae) - Gaussian Mixture VAE (
gmvae)
The backend computes training/projections/neighbors and writes run artifacts to disk. The frontend renders those artifacts (plus live SSE updates) without recomputing ML outputs.
- Run creation from UI with configurable AE/GM-VAE hyperparameters
- Live run monitoring via SSE (
run.*,train.*,artifact.created,projection.progress) - Epoch playback for metrics and reconstructions
- Latent Explorer route:
/runs/[id]/latent - Projection methods:
- PCA 2D (default per epoch)
- PCA 3D (per epoch + latest; generated during training for new runs, backfillable for older runs)
- UMAP 2D (on-demand enable/backfill + future epochs)
- UMAP 3D (on-demand/backfill + future epochs, same UMAP settings with
n_components=3)
- 2D and 3D latent rendering with epoch/method/dimension controls
- Category legend toggles (show/hide labels) in 2D and 3D
- Selectable points with dataset sample preview (image + dataset index + label)
- Per-run persisted point-size controls in 2D and 3D for:
- sample points
- centroids
- GM-VAE cluster centers
- Latent Explorer UMAP controls (same behavior as run page):
- UMAP quality selector (
Standard 1024,High 2048) - compute UMAP directly from latent explorer when UMAP artifacts are missing
- UMAP quality selector (
- Sampling panel (GM-VAE, artifact-driven):
- posterior-local sampling for selected point (
q(z|x_i)decode grids) - component-conditional prior sampling (
p(z|c)decode grids) - deterministic seed by default, optional randomized seed
- cached artifact reuse and sample debug readout (
path,seed,compute_ms)
- posterior-local sampling for selected point (
- Neighbors / Extent panel (PAIR-style):
- Focus modes: Selected, Random 25, Random 100, All
kslider (2..50)- extent slider (
0..100%) - edge modes:
Gated by extent (PAIR)andAlways show top-k - optional radii and edge toggles
- debug panel with scale/radius/alpha/monotonicity counters
- 2D overlay modes in Latent Explorer:
OffDensity(GM-VAE only): Posterior/Prior source, opacity control, density debug statsDistortion: metric-ratio heatmap (mean d_proj / mean d_latentover kNN), opacity control, distortion debug stats- Supplemental legends in 2D:
- centroid and cluster-center marker legend (shown only when those layers are enabled)
- density/distortion gradient legend (shown only for the active overlay mode)
- UMAP density guidance note shown in UI to explain nonlinear embedding distortion
- Mixture Health panel (GM-VAE):
- reads empirical prior stats from artifacts
- shows
Neff,Neff/K,pmax, entropy, and collapse-status badge - student interpretation line (
Healthy/Moderate collapse/Severe collapse)
- On-demand backfill for legacy runs:
- UMAP projections
- PCA3 projections
- density artifacts (
pcaorumap) - distortion artifacts (
pcaorumap) - neighbors artifacts (
pcaorumap)
- Artifact browser for each run
- Run cancellation and resumable/reloadable run history
- Insights artifacts and UI panel on run detail
- GM-VAE anti-collapse training options in run config:
- categorical KL annealing (
categorical_kl_anneal*) - entropy bonus schedule (
entropy_bonus_*) - emitted metrics include
cat_kl_weight,entropy_bonus_weight,qc_entropy_mean,qc_neff,qc_pmax,qc_argmax_counts
- categorical KL annealing (
- Network Architecture / Feature Map Explorer (artifact-driven):
- architecture diagram and node details from
network/architecture*.json - single-image forward-pass artifacts by epoch/index/layer (
network/forward/...) - channel inspector artifacts (
network/inspect/...) with:- channel map, heat overlay, fixed overlay fallback
- optional
(x,y)probe and approximate receptive-field mapping back to input (rf) - RF spotlight (darkened outside region), hover zoom crop, and probe marker on channel map
- single-convolution-step explainer for conv1-like layers (
C_in=1,3x3) with patch/kernel/product math and model consistency check
- latent perturb + decode artifacts (
network/perturb/...) for decodable vectors:- AE:
z - GM-VAE:
mu,z_sample
- AE:
- GM-VAE forward reconstruction sample controls:
- lock sample / resample (
sample_id) - forward sampling metadata artifact (
forward_meta.json)
- lock sample / resample (
- kernel artifacts for selected conv channels (
network/kernels/...):- conv1 direct 3x3 kernel display (
C_in=1) - deeper conv aggregated kernel (
L2 over C_in) + top input-channel kernel slices
- conv1 direct 3x3 kernel display (
- top activating examples for encoder spatial layer+channel (
network/topk/...), with clickable thumbnails that set panel dataset index- score metric is backend-selected (
maxby default in UI;meansupported by API)
- score metric is backend-selected (
- compare mode:
- synchronized layer/channel/probe/opacity controls across both panels
- shared channel-level panels (kernel summary + top activating examples) shown once in full width
- architecture diagram and node details from
- Backend: FastAPI (
backend.app.main:app) + PyTorch - Frontend: Next.js App Router + TypeScript
- Transport: SSE for live events; filesystem artifacts for deterministic reloads
- Storage root:
runs/<run_id>/...
Canonical contracts live in:
AGENTS.md(operating rules)SPEC.md(architecture/artifact semantics)http://localhost:8000/openapi.json(authoritative API schema)
backend/FastAPI routes, run manager, training runner, projections/backfills, artifacts, testsfrontend/Next.js UI (/,/runs,/runs/[id],/runs/[id]/latent)models/PyTorch model definitionstrain_ae.py,train_vae.pylegacy CLI entry pointsapp.pylegacy Streamlit app (kept for incremental migration)runs/generated artifacts (gitignored)
Each run is persisted under:
runs/<run_id>/
config.json
events.jsonl
summary.json
checkpoints/
samples/
projections/
neighbors/
density/
distortion/
insights/
network/
Projection artifact naming:
- PCA 2D:
projections/latent_2d_epoch_<N>.jsonprojections/latent_2d_latest.json
- PCA 3D:
projections/latent_3d_epoch_<N>_pca.jsonprojections/latent_3d_latest_pca.json
- UMAP 2D:
projections/latent_2d_epoch_<N>_umap.jsonprojections/latent_2d_latest_umap.json
- UMAP 3D:
projections/latent_3d_epoch_<N>_umap.jsonprojections/latent_3d_latest_umap.json
Neighbors artifact naming (k_max=50, latent-space Euclidean kNN):
- PCA:
neighbors/knn_pca_epoch_<N>.jsonneighbors/knn_pca_latest.json
- UMAP:
neighbors/knn_umap_epoch_<N>.jsonneighbors/knn_umap_latest.json
Density artifact naming (2D only):
- PCA:
density/posterior_2d_epoch_<N>_pca.jsondensity/posterior_2d_latest_pca.jsondensity/prior_2d_epoch_<N>_pca.jsondensity/prior_2d_latest_pca.jsondensity/prior_empirical_2d_epoch_<N>_pca.jsondensity/prior_empirical_2d_latest_pca.json
- UMAP:
density/posterior_2d_epoch_<N>_umap.jsondensity/posterior_2d_latest_umap.jsondensity/prior_2d_epoch_<N>_umap.jsondensity/prior_2d_latest_umap.jsondensity/prior_empirical_2d_epoch_<N>_umap.jsondensity/prior_empirical_2d_latest_umap.json
Sampling artifact naming (GM-VAE, on demand):
- Posterior-local:
samples/posterior_local_epoch_<N>_idx_<i>_m_<M>.pngsamples/posterior_local_latest_idx_<i>_m_<M>.pngsamples/posterior_local_epoch_<N>_idx_<i>_m_<M>.json
- Prior-component:
samples/prior_component_epoch_<N>_c_<c>_m_<M>.pngsamples/prior_component_latest_c_<c>_m_<M>.pngsamples/prior_component_epoch_<N>_c_<c>_m_<M>.json
Metric distortion artifact naming (2D only):
- PCA:
distortion/metric_ratio_2d_epoch_<N>_pca.jsondistortion/metric_ratio_2d_latest_pca.json
- UMAP:
distortion/metric_ratio_2d_epoch_<N>_umap.jsondistortion/metric_ratio_2d_latest_umap.json
Network explorer artifact naming (on demand):
- Forward pass:
network/forward/epoch_<N>/idx_<i>/input.pngnetwork/forward/epoch_<N>/idx_<i>/recon.pngnetwork/forward/epoch_<N>/idx_<i>/layers.jsonnetwork/forward/epoch_<N>/idx_<i>/latent.jsonnetwork/forward/epoch_<N>/idx_<i>/forward_meta.json
- Layer summary/image:
network/forward/epoch_<N>/idx_<i>/layer_<layer_id>/summary.jsonnetwork/forward/epoch_<N>/idx_<i>/layer_<layer_id>/grid.png(spatial)network/forward/epoch_<N>/idx_<i>/layer_<layer_id>/vector.png(vector)
- Channel inspector:
network/inspect/epoch_<N>/idx_<i>/layer_<layer_id>/ch_<c>/inspect.jsonnetwork/inspect/epoch_<N>/idx_<i>/layer_<layer_id>/ch_<c>/channel.pngnetwork/inspect/epoch_<N>/idx_<i>/layer_<layer_id>/ch_<c>/heat_rgba.pngnetwork/inspect/epoch_<N>/idx_<i>/layer_<layer_id>/ch_<c>/overlay.png
- Perturb + decode:
network/perturb/epoch_<N>/idx_<i>/vector_<key>/dim_<d>/delta_<tag>/recon.pngnetwork/perturb/epoch_<N>/idx_<i>/vector_<key>/dim_<d>/delta_<tag>/meta.json
- Top activating examples:
network/topk/epoch_<N>/layer_<layer_id>/ch_<c>/metric_<metric>/subset_<n>/k_<k>/topk.jsonnetwork/topk/epoch_<N>/layer_<layer_id>/ch_<c>/metric_<metric>/subset_<n>/k_<k>/input_<dataset_idx>.png
- Kernel artifacts:
network/kernels/epoch_<N>/layer_<layer_id>/out_<c>/kernel.json(conv1)network/kernels/epoch_<N>/layer_<layer_id>/out_<c>/kernel.png(conv1 optional)network/kernels/epoch_<N>/layer_<layer_id>/out_<c>/kernel_agg.json(C_in>1)network/kernels/epoch_<N>/layer_<layer_id>/out_<c>/kernel_agg.png(optional)network/kernels/epoch_<N>/layer_<layer_id>/out_<c>/top_in_channels.json(C_in>1)network/kernels/epoch_<N>/layer_<layer_id>/out_<c>/kernel_in_<in_channel>.png(optional)
- Single convolution step:
network/conv_step/epoch_<N>/idx_<i>/layer_<layer_id>/out_<c>/x_<x>_y_<y>/conv_step.json
- Python
3.13 uv- Node.js + npm
From repo root:
uv sync
uv run uvicorn backend.app.main:app --reload --host 0.0.0.0 --port 8000Backend environment (local dev):
- Put local backend overrides in
backend/.env(auto-loaded on backend startup viapython-dotenv). - Keep secrets out of git; use
backend/.env.exampleas the committed template. - Tutor-related keys commonly used:
TUTOR_LLM_ENABLED=falseTUTOR_PROVIDER=openaiTUTOR_MODEL=gpt-4o-miniTUTOR_TEMPERATURE=0.2TUTOR_MAX_TOKENS=500OPENAI_API_KEY=...OPENAI_BASE_URL=https://api.openai.com/v1
From frontend/:
npm install
npm run devOptional backend override:
NEXT_PUBLIC_BACKEND_URL=http://localhost:8000 npm run devFor frontend-only local overrides, Next.js reads frontend/.env.local.
- Frontend:
http://localhost:3000 - OpenAPI docs:
http://localhost:8000/docs - OpenAPI JSON:
http://localhost:8000/openapi.json - Health:
http://localhost:8000/api/health
- Create a run from
/. - Monitor live training on
/runs/<run_id>. - Open
/runs/<run_id>/latentfor method/dimension/epoch exploration. - If needed for older runs:
- click
Compute PCA 3D for this run - enable/recompute UMAP on run detail or latent explorer
- in Neighbors panel click
Compute <METHOD> neighbors for this run - in Projection controls set overlay to
DensityorDistortion; use compute buttons if artifacts are missing
- click
- Use point selection + sample preview, Sampling panel, Neighbors/Extent controls, Mixture Health, and overlay modes for exploration.
- Open
/runs/<run_id>/network. - Choose epoch, layer, and dataset index in the Forward Pass / Feature Map Explorer.
- For GM-VAE, use Lock sample + Resample to control sampled-
zreconstruction deterministically (sample_id). - In Channel Inspector (spatial layers):
- click activation tiles or channel map to inspect channel responses
- click activation-map coordinates to probe
(x,y)and view receptive-field overlay on input - for conv1-like layers, inspect Single convolution step to connect a probed activation to patch/kernel/product math
- use Top activating examples to compute/show top-K dataset items for a selected encoder channel
- In latent/vector views, use Perturb + Decode to compare baseline (
delta=0) vs perturbed reconstructions.
- Density and distortion overlays are visualization-space diagnostics.
- In PCA space, geometry is linear and often easier to interpret globally.
- In UMAP space, geometry is nonlinear:
- UMAP is not a coordinate transform of latent probability space.
- UMAP does not preserve volume or Gaussian structure.
- UMAP primarily preserves local neighborhood relationships.
- Practical guidance:
- compare PCA vs UMAP overlays side-by-side
- treat UMAP overlays as local-structure aids, not direct probability maps
Base prefix: /api
GET /healthPOST /runsGET /runsGET /runs/{run_id}POST /runs/{run_id}/cancelGET /runs/{run_id}/events(SSE withLast-Event-IDreplay)GET /runs/{run_id}/artifactsGET /runs/{run_id}/artifacts/{artifact_path}GET /runs/{run_id}/dataset-samples/{sample_idx}POST /runs/{run_id}/projections/umap(enable/backfill/recompute UMAP)POST /runs/{run_id}/projections/pca3(backfill PCA3)POST /runs/{run_id}/neighbors/backfill?method=pca|umapPOST /runs/{run_id}/density/backfill?method=pca|umapPOST /runs/{run_id}/distortion/backfill?method=pca|umapPOST /runs/{run_id}/sample/posterior_localPOST /runs/{run_id}/sample/prior_componentPOST /runs/{run_id}/network/forwardPOST /runs/{run_id}/network/inspectPOST /runs/{run_id}/network/conv_stepPOST /runs/{run_id}/network/kernelPOST /runs/{run_id}/network/perturbPOST /runs/{run_id}/network/topk
- CORS / fetch errors:
- ensure frontend is on
http://localhost:3000orhttp://127.0.0.1:3000 - ensure backend is on
http://localhost:8000
- ensure frontend is on
Neighbors artifact not ready yet for this method/epoch:- use the Neighbors panel backfill button or
POST /runs/{id}/neighbors/backfill
- use the Neighbors panel backfill button or
Density artifact not ready/Distortion artifact not ready:- use the corresponding compute button in Latent Explorer
- or call
POST /runs/{id}/density/backfill/POST /runs/{id}/distortion/backfill
- UMAP options unavailable:
- enable UMAP from run detail or latent explorer (
POST /runs/{id}/projections/umap)
- enable UMAP from run detail or latent explorer (
- 3D PCA unavailable for old runs:
- trigger PCA3 backfill (
POST /runs/{id}/projections/pca3)
- trigger PCA3 backfill (
- command-not-found issues:
- run
uv syncfor Python deps - run
npm installinfrontend/
- run
Backend tests:
uv run pytest -q backend/testsFrontend typecheck:
cd frontend && npx tsc --noEmit