Browse the handbook
Guides

Visual training reports

Capture actual CPU training steps and inspect bounded network, loss, and gradient information offline.

Aner records real tensor computations during an Aner program and turns selected training steps into an interactive, standalone report. The built in aner.viz module works alongside aner.nn: training remains ordinary Aner code, while viz.capture makes its tensors, operations, loss, and available gradients inspectable.

This first implementation supports CPU neural network snapshots, a loss history, and a browser report. aner.plot is a proposed separate library for reusable data charts; it is not implemented. Keeping plotting separate will allow charts to serve data exploration, statistics, and other Aner libraries as well as training.

Run the example

Follow the one time installation guide to put aner on your PATH. From the folder containing the binary bundle's examples directory, run:

sh
aner run examples/neural_xor_debug.aner --debug-viz reports/xor --debug-values

The same command works on macOS, Linux, and Windows, including VS Code's terminal. Aner creates the parent reports folder if needed.

reports/xor must be a new directory. Aner refuses to overwrite any existing file or directory at that destination. Choose a different name for another run. The example uses synthetic XOR data, so opting into raw values makes its small network easier to inspect.

The model's ordinary output remains on standard output. A report status goes to standard error. Reports are written after successful execution; a failed run does not currently produce a partial trace.

The new directory contains:

FilePurpose
index.htmlInteractive report with the trace embedded; opens directly in a browser without a server or network access.
trace.jsonStructured observations for inspection or future tools.
summary.txtPlain text summary suitable for a terminal or an SSH session.

Open index.html in a browser. On a computer without a graphical desktop, read summary.txt and copy the HTML file to a computer with a browser. The HTML is standalone; it does not need its neighboring files to display the captured run.

sh
cat reports/xor/summary.txt

The equivalent PowerShell command is Get-Content reports\xor\summary.txt. The text report includes each captured step, bounded graph topology, operation labels, shapes, parameter status, and value/gradient means and root mean square statistics. It never prints raw arrays, even with --debug-values; those are available through JSON and the browser report within the recording limits. Aner starts no web server and sends no telemetry.

Use the report controls

  • Move the captured step slider, use Previous and Next, or select a point on the loss chart to inspect a stored frame. Connecting chart lines are visual guides between captured measurements.
  • Switch between Forward values and Gradients to inspect the corresponding recorded arrays. This switch does not execute a forward or backward pass.
  • In the neuron view, choose a Batch row to inspect its activation cells and their recorded loss derivatives. Weight and bias gradients still refer to the captured full batch loss; changing the row does not produce per example parameter gradients.
  • Use Dependency focus to walk the inferred layer chain. Select a neuron to inspect its activation, incoming weights, bias, and available gradients. Operation blocks and table rows expose shapes, dependencies, and tensor statistics. Keyboard selection is supported.

Individual neurons are drawn only for a recognized dense chain with all required raw cells, at most 64 neurons, and at most 256 weight connections. Otherwise a recognized dense network uses layer blocks; other graphs use an operation dependency table. These display limits are separate from the recording limits below.

Add captures to a training loop

Import both included modules before the function declarations. Each module may be imported once, in either order.

aner
import aner.nn;
import aner.viz;

fn main() -> Unit {
    var weight = nn.parameter([[2.0]]);
    let target = [[0.0]];
    let loss = nn.mse(weight, target);

    nn.backward(loss);
    viz.capture(0, loss);
    weight = nn.sgd(weight, 0.1);
}

The current API is:

aner
viz.capture(step: Int64, loss: Tensor) -> Unit

This is a signature reference, not an Aner function declaration to paste into a program. step is a user chosen counter and loss must have shape 1 × 1. The visual import does not implicitly import aner.nn; Tensor types and operations still require the neural module.

Capture after nn.backward(loss) and before updating parameters to inspect the values and gradients used by that update. Capturing before backward is allowed and shows no gradient data. Gradients are exported only if they came from a successful backward pass rooted at the captured tensor. If another backward pass has overwritten a shared tensor’s gradient, that gradient is omitted from a capture of the earlier loss. Capturing an intermediate tensor after differentiating an outer loss also shows no gradients: those derivatives belong to the outer loss. Previously stored snapshots remain unchanged. A capture observes the graph reachable from the supplied loss; it does not run backward or build additional training computations.

Without --debug-viz, viz.capture is an operation with no effect. Its imports and argument types are still checked, and its arguments still undergo ordinary expression evaluation. With recording enabled, snapshots copy observations without changing tensor values, gradients, optimizer updates, or the random number sequence. Recording adds time and memory overhead.

Enabled captures require nonnegative, strictly increasing steps no greater than 9007199254740991, the largest integer exactly representable by the browser's number type. The same rule applies after the frame limit is reached. This makes each stored step unambiguous. Step validity and scalar loss shape are runtime recording requirements.

Read the XOR network

The example network has 2 input features, 8 hidden neurons, and 1 output neuron. It has 33 trainable numbers:

ParameterShapeTrainable values
w12 × 816
b11 × 88
w28 × 18
b21 × 11

The four rows of x are a batch of four examples, not four copies of the model's architecture. Training changes those 33 parameter values. It does not add or remove neurons.

The example stores 33 captures: steps 0, 1, 2, then every 100 completed updates, and finally step 3000. At step 0, the parameters have not yet been updated: the first forward and backward passes have produced the initial loss and gradients. A capture at step 100 describes the weights after 100 updates and the gradients available for the next update. The final capture evaluates and differentiates the final model without applying another update.

Every update in this example uses the complete four row dataset, so one update is one epoch. With minibatches, an epoch normally contains several updates; Aner does not infer or equate those counters automatically.

The tensor operation view follows the actual recorded dependency graph. A small compatible dense network can also be shown as neurons and connections when the required raw values are available. That presentation is inferred from the recorded operations; ordinary Aner code remains the authority for the model. More complex topologies or large layers use operation blocks and summaries.

Understand the recorded graph

A frame contains operations and tensor observations in the runtime graph retained for its captured loss. It is the neural differentiation graph, not a static graph of the complete program. The runtime does not retain the internal history of computations that need no gradients, so a constant only calculation can appear as one summarized operation. Untaken branches, unrelated tensors, and operations detached from that loss are absent. A later capture may have a different graph.

Node labels come from Aner Tensor bindings when recording is enabled. The first name attached to a shared tensor is retained, so an alias need not appear as another node. Node IDs are local to each frame; equal IDs in different frames do not establish that they are the same allocation. Metadata stores the source basename, not the full path or source contents.

Moving between captures compares stored observations. It does not replay instructions, pause the running interpreter, or animate measured GPU execution. The current runtime is CPU only, and these captures contain no GPU timing. Graphical model editing, breakpoint control, live streaming, and execution timing are future work.

Choose the information to record

Omit --debug-values to record shapes and statistics without raw tensor arrays:

sh
aner run examples/neural_xor_debug.aner --debug-viz reports/xor-stats

Statistics include element count, minimum, maximum, mean, and root mean square value. Gradient statistics appear only where gradients still belong to the captured root’s successful backward pass. The report may still include the scalar loss and variable names. Derived statistics can expose sensitive information; this mode is not an anonymization or privacy guarantee. Inspect reports before sharing them.

--debug-values explicitly enables raw values and available raw gradients within these initial limits:

LimitBehavior
64 recorded framesFurther captures are counted as dropped. Step validation continues.
256 nodes in one captured graphA larger graph produces a root only summary with its actual total node count; detailed topology is omitted.
1024 cells per tensorLarger tensors retain statistics while their raw arrays are omitted.
8192 raw cells per frameValues and gradients share this budget. An array that does not fit is omitted in full; arrays are never truncated into misleading partial tensors.

An absent raw array is not an array of zeros. A missing gradient is not a zero gradient. Omission can reflect recording settings, size limits, or the absence of a valid backward pass. Reports retain those distinctions.

These are inspection limits, separate from the neural runtime's tensor and graph limits. Visual training reports make a small example understandable, with deliberate summaries as models grow.

VS Code support

The local Aner extension 0.1.16 highlights both imports and viz.capture with the current light or dark theme. The snippets importviz and vizcapture add the corresponding source statements. The extension provides syntax support; the Aner executable creates the report. It does not install a VS Code debug adapter or add a live debugger panel.

Current scope

These reports inspect stored CPU training snapshots. They do not provide graphical model editing, breakpoint control, live streaming, or execution timing. CNN, RNN, GPU, and distributed views depend on neural capabilities that are not implemented yet.

The current loss chart is part of the training report. A reusable aner.plot API, general data charts, experiment comparison, and other output formats remain future work.

Iris classification and dataset attribution

The Iris example captures a 4 → 8 → 3 dense model with linear output logits and cross entropy loss. This graph is recognized alongside the earlier XOR/MSE case. Output cells are labeled as logits; the viewer does not fabricate a softmax computation. Cross entropy gradients refer to the mean loss across the captured batch rows.

When an Aner program loads a built in dataset during a captured run, trace.json includes a datasets array with its name, source, citation, license and license URL, source version/hash, and transformation notice. The standalone HTML retains these credits in a collapsed dataset section; the text summary includes them too. This records datasets loaded in the run and is not complete tensor level lineage. Old traces without this optional field remain readable. See the dataset guide for the exact Iris source variant and reproduction steps.

Aner handbook · Guides and API reference