Skip to main content

NeuroLens

PyPI Python CI License: MIT

Watch neural networks train, live. NeuroLens is a fast C++/OpenGL window that shows what your model is doing while it trains: loss curves, gradient flow through every layer, update sizes, and the neurons themselves. Built-in checks tell you when something goes wrong: NaN loss, exploding gradients, a learning rate that is too high, overfitting.

pip install neurolens
import neurolens

neurolens.launch()                        # opens the window
mon = neurolens.monitor(model, optimizer) # any PyTorch model

for step, (x, y) in enumerate(loader):
    loss = loss_fn(model(x), y)
    optimizer.zero_grad(); loss.backward(); optimizer.step()
    mon.step(step, loss=loss)

Training monitor flagging overfitting

Live network view LR far too high: the checks catch it
Network view LR too high

Contents: Quick start · Training monitor · Network view · Any framework · How it works · Protocol · Examples · Troubleshooting · Roadmap · Contributing

Why NeuroLens

  • Works with any PyTorch model. CNNs, transformers and LoRA fine-tunes all work: monitor() only reads parameters and gradients.
  • Tells you what's wrong. It runs about ten rule-of-thumb checks continuously, and each warning says what to try.
  • Never slows training down. Data goes out on a background thread. If the window is closed or busy, data is dropped instead of blocking your loop.
  • Open the window any time. Curves are replayed from step 0, so you can start the viewer halfway through a run.
  • No setup. The viewer is compiled into the wheel. There is nothing to build, no browser, and no server.
  • Any language. It uses a tiny plain-text TCP protocol, so a few lines of code are enough to send data from JAX, TensorFlow, C++ or a shell script.

Quick start

  1. Install on macOS (Intel or Apple Silicon) or Linux, with Python 3.9+:
    pip install neurolens              # add [torch] to also install PyTorch
    
  2. Add three lines to your training script:
    import neurolens
    neurolens.launch()                          # once, before training
    mon = neurolens.monitor(model, optimizer)   # once, before training
    ...
    mon.step(step, loss=loss)                    # every step, after optimizer.step()
    
  3. Run your script as usual. The window opens, and curves appear within a second.

Windows is not supported yet (help wanted). Platforms without a prebuilt wheel compile the viewer during pip install. That needs a C++ compiler, plus OpenGL and X11 headers on Linux.

Start the viewer

From a terminal:

neurolens                  # opens the window and waits for your training script
neurolens model.nlens      # opens a saved network
neurolens --help           # all options

Or from Python, in a script or notebook: neurolens.launch(). If a viewer is already open, launch() does nothing.

Training monitor

mon = neurolens.monitor(model, optimizer)

for step, (x, y) in enumerate(loader):
    out = model(x)
    loss = loss_fn(out, y)
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()
    mon.step(step, loss=loss, acc=(out.argmax(1) == y).float().mean())  # before the next zero_grad

    if step % 500 == 0:
        mon.log(step, val_loss=evaluate(), val_acc=val_acc)  # sent as is, not averaged
Panel Shows Read it like this
Curves every metric you pass; val_x shares a chart with x; lr and total grad_norm are added for you Training loss falling while validation loss rises means overfitting. Loss charts switch to a log scale when the range is wide.
Layer health per layer: gradient norm (log bar) and update size |ΔW|/|W| per optimizer step Healthy updates are around 1e-3. Above 5e-2 the LR is too high; below 1e-6 the layer barely learns. A gradient of 0 means nothing reaches the layer.
Checks warnings with a suggested fix see below
Check Fires when
NaN / Inf loss the latest loss is not finite
Loss spike a loss point is more than 10× the first value
Diverging recent loss is more than 3× the best seen
Plateau the last quarter of the run did not beat the earlier best by 1%
Overfitting val_loss is 5% above its best while training loss keeps falling
Exploding gradient a layer's gradient norm is over 100
No gradient a trainable layer's gradient norm is about 0 (vanishing, or detached from the loss)
LR too high / too low updates are over 5% / under 1e-6 of the weights per step
Dead ReLUs over half of a hidden ReLU layer outputs 0 for every input (network view)

Options: monitor(model, optimizer, every=0.5, max_layers=40, track_updates=True, port=5757). Metrics are averaged over every seconds. Large models are grouped into max_layers rows. Update sizes need the optimizer and one temporary copy of the trainable weights per send, and turn off automatically above 200M trainable values. With LoRA, only the adapters count toward that limit.

Network view

For MLPs, you can watch the neurons themselves, during training or inference:

handle = neurolens.watch(model, labels=["cat", "dog", "bird"])
model(x)            # each forward pass lights up the network (max 20 per second)
handle.remove()

Connections glow by |activation × weight|. Gold means positive and red means negative, and the signal travels from left to right. Hover a neuron to see its value, and click it to mute it and watch how the output changes. Layers wider than 64 neurons are drawn as an evenly spaced sample.

Key / mouse Action
drag / wheel rotate / zoom
hover / click show a neuron's value / mute it (C unmutes all)
V flat or 3D view
T / N show or hide the training panel / the network
Space pause
S save a PNG screenshot
R randomize the weights
[ ] connection brightness
A / D / 0 auto-rotate / layer delay / reset camera
H / Esc hide the key help / quit

Any framework

v = neurolens.Viewer()
v.metric("loss", 0.42, step)                                  # curves
v.layer_stats([("encoder", grad_norm, weight_norm, update_ratio), ...])
v.topology([784, 128, 10], ["relu", "softmax"])               # network view
v.weights(0, W0, b0)                                          # shape (out, in)
v.input(x)                # the viewer runs the forward pass, or:
v.frame([x, h, y])        # send real activations
v.status(epoch=3)

Save a network to a file with neurolens.save_torch(model, "net.nlens") or neurolens.save_nlens(...). Open it later with neurolens net.nlens.

How it works

 your training script                                 NeuroLens window
┌─────────────────────────────┐                     ┌───────────────────────────┐
│ monitor() / watch() hooks   │  TCP 127.0.0.1:5757  │ C++ / OpenGL, 60+ fps     │
│ read params, grads, acts    │ ── plain text ──────▶│ curves · layer health     │
│ background thread, drops    │   one command/line   │ checks · network view     │
│ data rather than block      │                      │                           │
└─────────────────────────────┘                     └───────────────────────────┘
  • Separate process. The viewer runs in its own process, so a slow frame never stalls a training step, and a crashed training run never takes the window down.
  • Lightweight hooks. The Python side is a few hooks and a socket. It measures about every half second (every=0.5), so the cost per training step is close to zero.
  • Analysis lives in the viewer. The checks run in the viewer, on the data it receives, so a client in any language gets them too.

Protocol

.nlens files and the TCP stream (127.0.0.1:5757) use the same plain-text commands, one per line. You can try them by hand with nc localhost 5757.

Command Meaning
metric NAME VALUE [STEP] add a point to a curve (nan and inf are kept, so they can be flagged)
pstats N then pstat I NAME GRAD WEIGHT UPDATE layer health table; -1 means unknown or no gradient
clearmetrics drop all curves and layer stats
layers 16 26 24 layer sizes, input first
act relu sigmoid activation per non-input layer: relu tanh sigmoid softmax linear
w L v... / b L v... weights (row-major, out x in) / biases from layer L to L+1
input v... input; the viewer computes the other layers
acts L v... real activations of layer L (0 = input)
labels a b c output neuron names
status text one line of text in the header
reset forget sent activations and input
# ... comment

Examples

git clone https://github.com/Yaiphaba189/TrainLens && cd TrainLens
# each example opens the viewer window itself with neurolens.launch()
python examples/torch_monitor_cnn.py          # CNN: the monitor flags overfitting
python examples/torch_monitor_cnn.py --lr 3   # learning rate far too high
python examples/torch_spiral_train.py         # MLP: network view plus monitor, then inference
python examples/numpy_xor_train.py            # no PyTorch: plain numpy

Troubleshooting

Problem Fix
Training on a remote GPU server over SSH The window needs a screen, so run it on your laptop and tunnel the port backwards: run neurolens locally, connect with ssh -R 5757:localhost:5757 gpu-box, and start training on the server as usual.
Google Colab, Kaggle, or a headless server with no SSH from your machine Not supported yet: the viewer needs a display it can reach.
cannot find the neurolens-viewer program The compiled viewer is missing. Reinstall with pip install --force-reinstall neurolens.
not listening for clients (port 5757 ...) Another viewer is already open. Use that one, or pick another port: neurolens --port 6000 and monitor(..., port=6000).
Curves appear but the layer table is empty, or every layer shows NO GRAD Call mon.step() after loss.backward() and before the next optimizer.zero_grad(). The monitor prints this hint once.
No update sizes in the layer table Pass the optimizer: monitor(model, optimizer). They also turn off above 200M trainable values.
pip install compiles for a long time No prebuilt wheel exists for your platform, so it builds the viewer, and SDL2 if needed. This happens only once.

Limits

  • The network view draws dense layers only: MLPs, or the MLP head of a bigger model. The training monitor has no such limit.
  • watch() finds layers in the order they are registered, which matches nn.Sequential.
  • The viewer accepts connections from this machine only (127.0.0.1). Use an SSH tunnel for remote training, as shown above.

Roadmap

  • Windows support: the viewer needs Winsock networking.
  • Remote and notebook training: Colab and Kaggle.
  • Network view for convolution and attention layers.
  • monitor() helpers for JAX and TensorFlow.
  • Export a run (curves and checks) to a report you can share.

Ideas and pull requests are welcome. See CONTRIBUTING.md.

Contributing

See CONTRIBUTING.md. MIT licensed. Inspired by m607stars/Neural-Network-Visualization-using-OpenGL.

Metadata

Release files for neurolens 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for neurolens 0.1.1
File Size Uploaded Provenance
neurolens-0.1.1.tar.gz 56.2 kB With provenance Details

Built distributions (wheels)

Table of built distributions (wheels) for neurolens 0.1.1
File
neurolens-0.1.1-py3-none-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl Python 3 none Linux glibc 2.28+ x86-64, Linux glibc 2.27+ x86-64 Details
neurolens-0.1.1-py3-none-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl Python 3 none Linux glibc 2.27+ ARM64, Linux glibc 2.28+ ARM64 Details
neurolens-0.1.1-py3-none-macosx_11_0_x86_64.whl Python 3 none macOS 11.0+ x86-64 Details
neurolens-0.1.1-py3-none-macosx_11_0_arm64.whl Python 3 none macOS 11.0+ ARM64 Details

Total release size: 3.2 MB

Release files / neurolens-0.1.1.tar.gz

Download URL neurolens-0.1.1.tar.gz
Size 56.2 kB
Tags Source
SHA-256 checksum
How to use checksums
3c989a83ae94d53fb6a6204c7cc4fc25927213b2aae97d97f7941c67664b4bfa
BLAKE2b-256 checksum
How to use checksums
3787782c3b2485a25340389657710e90d6b62a66f36a40e603d241dd2cef4540
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 24, 2026.

Transparency log

Release files / neurolens-0.1.1-py3-none-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl

Download URL neurolens-0.1.1-py3-none-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Size 963.8 kB
Tags Linux glibc 2.27+ x86-64 Linux glibc 2.28+ x86-64 Python 3
SHA-256 checksum
How to use checksums
82a8ea818685aba72af87fe6ed0ebac19667090cd68bfe8b42ff03267e59431f
BLAKE2b-256 checksum
How to use checksums
3dac3a6cc8c614ed4f5f3e1c82ffb2b31c7d2a8fe69a3497f353d227caccdf1d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 24, 2026.

Transparency log

Release files / neurolens-0.1.1-py3-none-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl

Download URL neurolens-0.1.1-py3-none-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
Size 865.4 kB
Tags Linux glibc 2.27+ ARM64 Linux glibc 2.28+ ARM64 Python 3
SHA-256 checksum
How to use checksums
2e975152e229991a91daec7b6bb88d3c43b98ff221e9802415932c0412932470
BLAKE2b-256 checksum
How to use checksums
1cba15eddd9b11d9137914a1c558d94a10ecc0acac66121d3837cdce69d21e09
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 24, 2026.

Transparency log

Release files / neurolens-0.1.1-py3-none-macosx_11_0_x86_64.whl

Download URL neurolens-0.1.1-py3-none-macosx_11_0_x86_64.whl
Size 728.6 kB
Tags Python 3 macOS 11.0+ x86-64
SHA-256 checksum
How to use checksums
5737f111dc101f59dd616751d69aa954ab204a7ac0829b72f2fd75e0183ee063
BLAKE2b-256 checksum
How to use checksums
d45c1ed95654ddfc53eb736b1c49dbdd9991c4cca94db0a441621258e9f90ce8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 24, 2026.

Transparency log

Release files / neurolens-0.1.1-py3-none-macosx_11_0_arm64.whl

Download URL neurolens-0.1.1-py3-none-macosx_11_0_arm64.whl
Size 635.2 kB
Tags Python 3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
3c979b77c52cf536a3c697f79116b75724457ebbc69631188fc0f55c6a39c85a
BLAKE2b-256 checksum
How to use checksums
79b6467110ddf66f0d51f95a56b3e82834f3ddfdf23f7800030d6474ea5a67f6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 24, 2026.

Transparency log

Security for neurolens 0.1.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 5 files in this release have been uploaded with provenance metadata.

Select from 5 files

Attestation for neurolens-0.1.1.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 24, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.1 This release

5 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page