optimizer_display#

Diagnostic display for the Newton-CG fitting loop – backend-owned, so a raw-.data user gets the identical display without touching the frontend (the anti-drift rule):

import t3toolbox.backend.optimizers as bopt import t3toolbox.backend.optimizer_display as bdisp cb, records = bdisp.make_newton_display(problem, val_sample=vs, val_data=vd) x, stats = bopt.newton_cg(problem, x0, callback=cb) # prints each iter; records == the history

Two layers, so the pure algorithm modules stay pure and the I/O is isolated:

  • format_newton_iter() – a pure function returning the formatted string block (a scalar header line + the per-(mode, order) relative-error table). Testable without capturing stdout.

  • make_newton_display() – builds a callback(NewtonInfo) for t3toolbox.backend.optimizers.newton_cg(): it precomputes the constant data-norm denominators once, then per iteration computes the train (and optional validation) error matrices, prints via an injectable print_fn, and records each iteration.

The relative-error table is ‖r_ij‖ / ‖y_ij‖ from the kind’s UNWEIGHTED block_sumsq() (D2) – the honest per-block recovery error, independent of any residual weight ω. The layout follows the kind’s axes (dev/newton_display_plan.md §2a): probe_derivatives (mode × order) -> mode rows, order cols, train|val cells; a single data axis (plain probe = mode, apply/entries_derivatives = order) -> dataset rows, that axis in columns; a scalar (plain apply/entries) -> a one-liner. The stored matrices are always canonical (n_mode, n_order) – the layout is cosmetic.

Formatting uses %.1e (Python pads the exponent to a signed 2-digit field, so every cell is exactly 7 chars -> columns align with no extra work). The callback is host-side (it reads the concrete residual), so it composes with newton_cg(use_jit=True) (only the inner CG jits) but not a fully-jitted outer loop.

Functions#

relative_errors(residual_block_sumsq, data_block_sumsq)

Per-(mode, order) relative error ‖r_ij‖ / ‖y_ij‖ = sqrt(block_sumsq(r) / block_sumsq(y)).

format_newton_iter(info, train_err[, val_err, ...])

Format one Newton iteration as a header line + the relative-error table (pure -- returns a string).

make_newton_display(problem[, val_sample, val_data, ...])

Build a callback(NewtonInfo) (+ its records list) that displays each Newton iteration.