Skip to content

Plots outliers interactions and Model Tracking Upgrade - #296

Merged
guillaume-byte merged 8 commits into
devfrom
plots-outliers-interactions
Aug 18, 2026
Merged

Plots outliers interactions and Model Tracking Upgrade#296
guillaume-byte merged 8 commits into
devfrom
plots-outliers-interactions

Conversation

@guillaume-byte

@guillaume-byte guillaume-byte commented Aug 18, 2026

Copy link
Copy Markdown
Member

Model signals: docs + example

Adds documentation and a worked example for the new per-step, per-layer model
signal tracking feature ("model signals"), covering how to use and interpret
these training-dynamics signals, updated API references, and a gallery entry.

UI Plots Zoom on Outliers

Allow the UI to request outlayers for a specific run and step.

Documentation and examples

  • New example page model_signals.rst: tracking and interpreting per-layer
    training dynamics (gradient norms, weight norms, activation stats) on
    Fashion-MNIST, with explanations and code samples.
  • Listed the example in the use-cases index and the gallery, with tags and a
    summary for discoverability.

API and usage docs

  • Documented wl.save_model_signals and wl.track_model_signals, plus the new
    wl.watch_or_edit arguments for configuring model signal collection.
  • Expanded the logger docs to distinguish per-sample, per-annotation, per-group,
    and per-step (model) signals, with guidance on correct usage and plotting
    behavior.

Concepts and best practices

  • New sections in the model interaction guide and the conventions guide
    explaining the purpose, integration, and interpretation of model signals,
    including diagnostic patterns and model-architecture best practices.

Navigation

  • Standardized section captions in the main index, added a MIGRATION section,
    and clarified where to find integrations and references.

guillaume-byte and others added 4 commits August 16, 2026 20:25
A curve point is the mean of one step's batch, which hides the samples
that blew up inside it. Alongside each averaged point the logger now
reports which samples sat off the curve's own rolling trend, so a plot
can show both the aggregate and the anomalies within it.

Detection (_TrendTracker) keeps an EMA of the per-step average plus an
EMA of squared deviation, and flags a sample when it falls further from
the trend than k rolling standard deviations. Two guards keep it quiet:
no flagging until the curve has min_steps of history (so a fresh loss
curve's steep warm-up isn't one long anomaly), and the band never
narrows below a fraction of |EMA| (so ordinary jitter on an almost-flat
curve can't clear a 3-sigma test). Deviation is measured two-sided, so
this works for accuracy-shaped signals as well as loss-shaped ones.

Each point carries the top-N off-trend samples with their ids plus the
true flagged count, which is what lets a consumer tell "one sample
spiked" from "the whole batch drifted" — and gives the UI real sample
ids to filter a data grid on.

Notable details:
- signals gains outliers/outlier_count/sample_count. A DB file written
  before those columns is ALTERed on open, and every INSERT now names
  its columns, since migrated columns land at the end of the table and
  would break a positional INSERT ... SELECT *.
- The full-history downsample keeps every outlier-bearing point. An
  outlier is by nature a single step, so plain striding would have
  thrown away most of exactly what this feature exists to surface.
- Detection is env-tunable (WL_SIGNAL_OUTLIER_*) and can be turned off.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Detection already maintained a rolling band (EMA plus k rolling standard
deviations, with a relative floor) to decide which samples are off-trend,
but only the verdict reached the UI. The band itself is now recorded on
every point, so a plot can draw the region a value was expected to fall
inside instead of showing an unexplained marker.

The band is snapshotted BEFORE the point is folded into the trend — the
same instant find_outliers reads it — so what the UI draws is exactly what
the flag was judged against, and a spike is never measured partly against
itself.

Two behaviour notes:
- Signals with no per-sample data now advance a trend too. A band describes
  the curve, not the batch, so an aggregate-only signal (lr, a scalar
  metric) gets one; it simply has no sample ids to attribute an outlier to.
- Evaluation markers are excluded. They are separate points under their own
  hash, and folding them in would corrupt the training curve's trend.

signals gains trend_value / trend_margin, defaulted to NULL rather than 0 so
"no band recorded" stays distinguishable from a real band centred on zero.
On the wire the pair is accompanied by an explicit has_trend_band flag,
since proto3 scalars have no presence.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Two changes driven by moving anomaly display into the error band itself.

1. Absolute value range. Each point now carries value_min / value_max: the
   real lowest and highest sample value in that step's batch, not a standard
   deviation. This is what the UI draws the band from, so a step containing
   an outlier pushes the band out to that outlier's own value. A std-derived
   band does the opposite — it averages the spike toward the batch mean and
   buries the thing worth seeing. The trend band is still recorded (it is
   what decides which samples count as off-trend) but is no longer drawn.

2. GetStepSamples. "Highlight step samples" now means the WHOLE batch behind
   a plotted point, not only its off-trend members, so the ids have to come
   from the per_sample table rather than from the outlier list on the
   aggregated point. get_step_sample_ids answers that with a cap plus the
   true pre-cap total, so a caller can say "showing 2000 of 4096". Ids sort
   numeric-aware, so "9" precedes "10".

An empty result is returned as success, not failure: signals that log only
an aggregate legitimately have no per-sample rows, and the UI needs to tell
that apart from an error.

signals gains value_min / value_max, NULL-defaulted so "not recorded" stays
distinguishable from a real zero range, with the same ALTER-on-open migration
as the existing added columns.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Copilot AI lite review requested due to automatic review settings August 18, 2026 08:59

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR extends WeightsLab’s signal/plot pipeline to (1) carry per-step outlier context to the UI (including fetching the full batch behind a plotted point) and (2) add a new “per-step model signals” API (gradient/weight norms and activation stats) with end-to-end examples, docs, and tests.

Changes:

  • Add signal outlier payloads (trend band, per-step min/max range, top-N outliers) and downsampling that preserves outlier-bearing points; introduce GetStepSamples RPC to fetch the full batch behind a plotted step.
  • Introduce wl.save_model_signals and wl.track_model_signals plus an implementation module that installs hooks and flushes per-step metrics.
  • Add extensive docs/examples/tests for both outliers and model signals.

Reviewed changes

Copilot reviewed 20 out of 21 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
weightslab/trainer/services/experiment_service.py Forwards new outlier/trend/range fields to proto points, preserves outliers when downsampling, adds GetStepSamples.
weightslab/src.py Adds public per-step model-signal write path + wiring for model-signal tracking via watch_or_edit.
weightslab/proto/experiment_service.proto Adds SignalOutlier, additional LoggerDataPoint fields, plus GetStepSamples RPC/messages.
weightslab/proto/experiment_service_pb2.py Regenerated protobuf Python stubs to include new messages/fields.
weightslab/proto/experiment_service_pb2_grpc.py Regenerated gRPC service/client stubs to include GetStepSamples.
weightslab/examples/Usecases/wl-fashion-mnist-signals/main.py New runnable example demonstrating model-signal tracking.
weightslab/examples/Usecases/wl-fashion-mnist-signals/config.yaml Config for the Fashion-MNIST model-signals example.
weightslab/examples/Notebooks/Usecases/ws-segmentation-loss-shapes-classification.ipynb New/updated notebook use case content (segmentation + decorated signal).
weightslab/examples/Notebooks/Local/wl-local-studio-quickstart.ipynb Notebook updated, but currently contains unresolved merge conflict markers.
weightslab/components/model_signals.py New implementation for per-step model-signal collection/flush via hooks.
weightslab/backend/logger.py Adds outlier detection, trend tracking, schema migrations, range tracking, and step-sample-id queries.
weightslab/init.py Re-exports save_model_signals / track_model_signals from the public API.
tests/general/test_model_signals.py Unit tests for save_model_signals and hook-based track_model_signals.
tests/backend/test_signal_outliers.py Tests for trend/outlier/range plumbing, persistence/migration, and service-level downsampling behavior.
docs/user_functions.rst Documents new public APIs and model kwargs.
docs/model_interaction.rst Adds model-signal guidance and best practices.
docs/logger.rst Explains signal types and plot grouping (including model signals).
docs/examples/usecases/model_signals.rst New docs page for the model-signals use case.
docs/examples/usecases/index.rst Adds model-signals use case to the index.
docs/_static/examples-gallery.js Adds model-signals card to the examples gallery.
AGENTS.md Adds guidance on choosing the right save_* verb and model-signal tracking.
Files not reviewed (1)
  • weightslab/proto/experiment_service_pb2.py: Generated file
Suppressed comments (2)

weightslab/examples/Notebooks/Local/wl-local-studio-quickstart.ipynb:72

  • This cell has merge conflict markers around the source field; the resulting notebook JSON is invalid.
<<<<<<< HEAD
   "source": "import os\n\n# Imports weightslab\nimport weightslab as wl\n\n# Serve the weightslab app\nwl.serve()\n\n# Define root log dir for experiment\nroot_log_dir = os.environ.get(\"WEIGHTSLAB_ROOT_LOG_DIR\", None)"
=======
   "source": [
    "import os\n",

weightslab/examples/Notebooks/Local/wl-local-studio-quickstart.ipynb:102

  • There are merge conflict markers at the end of the notebook as well, leaving duplicate/marked closing braces and invalid JSON.
<<<<<<< HEAD
}
=======
}
>>>>>>> origin/main

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread weightslab/examples/Notebooks/Local/wl-local-studio-quickstart.ipynb Outdated
Comment thread weightslab/src.py Outdated
Comment thread weightslab/trainer/services/experiment_service.py Outdated
Comment thread weightslab/trainer/services/experiment_service.py
Comment thread weightslab/backend/logger.py Outdated
Comment thread weightslab/src.py
@guillaume-byte
guillaume-byte changed the base branch from main to dev August 18, 2026 09:04
@guillaume-byte guillaume-byte changed the title Plots outliers interactions Plots outliers interactions and Model Tracking Upgrade Aug 18, 2026
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: guillaume-byte <237722353+guillaume-byte@users.noreply.github.com>
@guillaume-byte
guillaume-byte merged commit 8b049ed into dev Aug 18, 2026
9 checks passed
@guillaume-byte
guillaume-byte deleted the plots-outliers-interactions branch August 18, 2026 13:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants