Diagnostics

Diagnostics#

Every check in prophys reports its findings in one format, whether it concerns the layer widths of a network surrogate, the convergence of a training run, a licence limit, a symbolic surrogate or a physics primitive. A finding has a stable code, a severity, a location and a hint, and renders like a compiler message:

error[NN104] width 6 does not split into 4 heads
  --> surrogate 'wake', layer L1 (SelfAttention)
   = hint choose heads dividing 6 or change the previous layer width

Errors raise ProphysError, a ValueError carrying every finding in diagnostics and their codes in codes. Warnings are issued as ProphysWarning, whose diagnostic attribute holds the finding. Reports keep their findings too: PretrainResult.diagnostics and CalibrationResult.diagnostics list them and converged summarises the convergence checks. Colour is used on a terminal unless NO_COLOR is set.

from prophys.diagnostics import ProphysError

try:
    nn.Surrogate("wake", ["x"], layers=[nn.Dense(6), nn.SelfAttention(4)])
except ProphysError as e:
    e.codes            # ["NN104"]
    e.diagnostics      # the findings

Convergence#

Training of surrogates and calibration of models are checked the same way. A non finite loss is a divergence (NN202, CAL202). Otherwise the loss slope over the first and the last quarter of the run is divided by the step size in effect there, and when the final progress per unit step size is still above a tenth of the initial one the run stopped while improving (NN201, CAL201). Normalising by the step size keeps decaying schedules, which flatten every curve at the end, from hiding unfinished training.

A flat loss is not proof of convergence. On a plateau, a slope in a flat valley or before a sigmoid saturates, the loss barely moves while the parameters keep walking in one direction, and a larger drop can follow much later. The second check therefore watches the parameters over the last quarter of the run (at least six steps). It divides their net displacement by the length of the path they travelled. Around a minimum the optimiser oscillates and the ratio is small. On a plateau every step points the same way and the ratio stays near one. Above one half the run is reported as not converged, with the ratio in the message. The tracker keeps only the first and the latest parameters and the running path length, so it costs nothing in memory.

A calibration that stops on a plateau before the loss drops A calibration that stops on a plateau before the loss drops

A calibration through a saturated sigmoid. Its loss is flat for the first forty steps and then falls by three orders of magnitude. A forty step run already reports ``CAL201`` because the parameter still drifts.

Pretraining adds overfitting (NN203), poor fit (NN204), miscalibrated intervals (NN205), unrepresentative validation data (NN206) and a vanishing initial gradient (NN207), and checks its data for non finite values, constant columns and too few rows.

Symbolic surrogates#

prophys.Surrogate wraps any JAX function. Its validate() method evaluates it once and reports whether the output broadcasts with the inputs (SUR102) and is finite (SUR103).

Codes#

NN101

unknown or malformed layer argument

NN102

network program rejected by the native planner

NN103

layer input width mismatch

NN104

attention width does not split into heads

NN105

layer needs a context that the surrogate does not declare

NN106

layer breaks a declared monotonicity guarantee

NN107

layer breaks the convexity guarantee

NN108

reshape changes the element count

NN109

too many residual slots

NN110

output head does not match the declared outputs

NN111

program entry not exact in single precision

NN112

physics layer did not compile to native code

NN121

missing or unknown surrogate input

NN122

input unit incompatible with the declared unit

NN123

input shape does not match the surrogate

NN124

data contain non finite values

NN125

input column is constant in the training data

NN126

few training samples relative to the parameter count

NN127

inputs and targets differ in length

NN128

loss or distribution targets do not suit the output head

NN201

training did not converge

NN202

training diverged

NN203

validation loss rises, the model overfits

NN204

poor fit on validation data

NN205

prediction intervals are miscalibrated

NN206

validation data lie outside the training support

NN207

gradient vanished at initialisation

NN301

no head posterior available

NN302

no support region available

LIC101

surrogate exceeds the free tier

LIC102

licensed asset needs a valid license

LIC103

model exceeds the free tier

LIC104

license rejected

AMO101

invalid amortization envelope, statistic or query

AMO102

amortized attribute is not scalar

AMO201

operational surrogate misses its accuracy criterion

AMO202

operational surrogate is stale

CAL201

calibration did not converge

CAL202

calibration diverged

CAL203

parameters are not identified by the data

SUR101

surrogate function is not callable

SUR102

surrogate output shape does not broadcast with its inputs

SUR103

surrogate output is not finite

PHY101

physics primitive argument has the wrong shape

PHY102

physics primitive argument outside its valid range

TREE101

tree ensemble shape invalid

TREE102

imported booster not supported

TREE103

monotone constraint on a learned split feature