The reference path's training loop, for any NetSpec MlirCodegen lowers.
NetSpec.train generates the forward, eval-forward and train-step MLIR (compileVmfbs), opens
a runtime session, and runs runTraining: init params → for each epoch { shuffle, for each batch
{ train step, EMA, log }, val eval } → save. A trainer is one call:
def main (args : List String) : IO Unit :=
resnet34.train resnet34Config (args.head?.getD "data/imagenette")
Adding an architecture means defining the spec and a TrainConfig value. The per-dataset
loading and augmentation live in the per-dataset records below.
Region Dice off a confusion matrix #
Shared by the trainer's per-epoch val line and brats-eval's per-volume scorer, so the two
score a region the same way.
(inter, |gt|, |pred|) of the class-union region cls, read off an nc × nc confusion
matrix conf[gt * nc + pred]:
inter = Σ_{g∈R} Σ_{p∈R} C[g][p], |gt| = Σ_{g∈R} Σ_p C[g][p], |pred| = Σ_{p∈R} Σ_g C[g][p].
Counts stay exact Nat.
Equations
- One or more equations did not get rendered due to their size.
Instances For
2·inter / (|gt| + |pred|), with the BraTS convention for a region the ground truth lacks:
an empty prediction scores 1 and a non-empty one 0.
Equations
Instances For
File-path prefix for the generated MLIR / vmfb / saved-params files associated with this spec. Uses the sanitized spec name so adding a new spec automatically gets a unique non-colliding prefix without the trainer author having to pick one.
Equations
- spec.buildPrefix = ".lake/build/" ++ spec.sanitizedName ++ if spec.buildTag.isEmpty = true then "" else "_" ++ MlirCodegen.sanitize spec.buildTag
Instances For
Set buildTag, so an ablation arm owns its own artifacts. Reads as
(net.withBuildTag "ce").train … at the call site. (Not buildTag — that
name belongs to the field itself.)
Equations
- One or more equations did not get rendered due to their size.
Instances For
The fully qualified <module>.<func> name the train step's main
function lives at — what trainStepAdamF32 wants as its fnName.
Mirrors how MlirCodegen.generateTrainStep builds the module
name from the third argument it's given (jit_<sanitized>_train_step).
Equations
- spec.trainFnName = "jit_" ++ spec.sanitizedName ++ "_train_step.main"
Instances For
Path of the runnable artifact for one emitted graph, on whichever backend is
active at run time (LowererSession.backendName). No executable is linked against a
backend: every one links lowererLink, and ffi/lowerer.c dlopens the shim
$LEAN_MLIR_LOWERER names.
- IREE —
iree-compileturns{pfx}_{suffix}.mlirinto a.vmfb, and that.vmfbis whatLowererSession.createloads. - XLA — PJRT compiles the
.mlirin-process, so no.vmfbis ever produced and the.mliris the artifact.
Every pathExists guard and LowererSession.create call below routes through
this. The guards are the reason it exists: they are what decide whether eval
runs at all, and with a hardcoded .vmfb path they go silently false on XLA
— training would look perfectly healthy and simply stop reporting val
metrics, which is a much worse failure than not loading.
Equations
- One or more equations did not get rendered due to their size.
Instances For
The eval forward of spec over the n images of a flat f32 set (imgFloats floats each) at
batch batch, the tail batch padded with the last real image: the [n, nOut] f32 logits of
the real rows. The detector demos' infer dumps.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Compile one emitted graph to the artifact graphArtifact names: iree-compile on IREE; on
XLA nothing, since PJRT compiles the .mlir itself in-process. false on a failed compile
(the compiler's error is printed). Uncached; compileVmfbs keys its own compiles on the MLIR
text.
Equations
- NetSpec.compileArtifact mlirPath outPath = do let __do_lift ← LowererSession.backendName if (__do_lift == "xla") = true then pure true else NetSpec.runIree✝ mlirPath outPath
Instances For
Generate forward / eval-forward / train-step MLIR for spec and
write them to .lake/build/<sanitized>_*.mlir. On IREE, also compile
each to a .vmfb, cached on the MLIR content + IREE backend so a
second run with no codegen changes skips iree-compile; on XLA there is
no compile step. Returns the train-step artifact graphArtifact
resolves (.mlir on XLA, .vmfb on IREE).
The loss is cfg.lossKindFor ds; a per-pixel kind switches the train-step codegen to the
segmentation path, where labels are an int32 [B, H, W] tensor instead of a [B] class
index.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Equations
The named class-unions ds reports Dice for (DatasetIO.segRegions; empty for most).
Equations
Instances For
Adam or SGD+momentum (TrainConfig.optimizer), cosine LR, running-BN-stats training loop, generic over
DatasetKind. The dataset specifies how to load the train/val
data and what augmentation to apply per batch; everything else
(init, optimizer, BN EMA, val eval, save) is identical across
datasets.
spec must have been compiled via compileVmfbs first.
Instances For
Eval-only mode: skip training entirely, load saved params + bn_stats,
run the eval forward on val data, print accuracy. Used to re-eval
existing checkpoints against a fixed eval pipeline. Requires compileVmfbs to
have produced (or cached) the _fwd_eval.vmfb already.
Equations
- One or more equations did not get rendered due to their size.
Instances For
End-to-end: compile all three vmfbs, load the train-step session, and run the training loop on the chosen dataset. The entry point the reference trainers call.
LEAN_MLIR_EVAL_ONLY=1 short-circuits to evalOnly — skips
training, loads the saved checkpoint, runs eval. Used for re-eval
after a fixed eval pipeline.
Defaults to Imagenette.
Equations
- One or more equations did not get rendered due to their size.