LANTERN — Aβ plaque segmentation in 3D light-sheet microscopy (ki3 model 2)

5-fold ensemble of 3D U-Nets that segment amyloid-β plaques in cleared whole mouse brain imaged by light-sheet microscopy. Each fold is a frozen self-supervised ResEncL encoder with a fine-tuned decoder.

LANTERN = Light-sheet Automask Network for Transferable Embedding Representations.

What this is

Architecture ResEncLUNet — ResEncL encoder (6 stages, features [32,64,128,256,320,320]) + UNetDecoder
Parameters 102.3 M total, 12.1 M trainable (encoder frozen)
Encoder init nnBYOL3D self-supervised pretraining on ~50k near-iso-4 light-sheet patches
Input 1 channel, 128³ voxels, near-iso-4 grid (4.4 × 3.25 × 3.25 µm)
Output 2 classes (background, plaque)
Folds 5, from patch-level 5-fold CV — use all 5 and vote

Intended use

Detecting and delineating Aβ plaques in App-NLGF mouse brain, Abeta-stained channel, acquired at 4x and resampled to the near-iso-4 grid above. It is a research model for plaque burden quantification, not a diagnostic tool.

The 5 folds are meant to be run together: predict with each, threshold at 0.5, and take votes >= 3. The per-fold disagreement (votes/5) is useful on its own — model–model agreement correlates 0.85 with out-of-fold accuracy, so it flags regions needing human review without any ground truth.

Usage

The model is unusable without matching its preprocessing exactly — it is scale- and intensity-normalisation sensitive (see Limitations).

import numpy as np, torch

def normalize(vol):                      # per-tile, exactly as in training
    lo, hi = np.percentile(vol, [0.5, 99.5])
    v = np.clip(vol, lo, hi).astype(np.float32)
    s = float(v.std())
    return (v - float(v.mean())) / (s if s > 1e-8 else 1.0)

# `ResEncLUNet` comes from the LANTERN repo (lantern/models/unet_seg.py)
nets = []
for k in range(5):
    ck = torch.load(f"fold{k}/seg_model.pt", map_location="cpu", weights_only=False)
    n = ResEncLUNet(num_classes=2, num_input_channels=1)
    n.load_state_dict(ck["state_dict"])
    nets.append(n.eval().cuda())

x = torch.from_numpy(normalize(tile))[None, None].cuda()   # tile: float32 (128,128,128)
votes = torch.zeros((128, 128, 128), dtype=torch.uint8, device="cuda")
with torch.no_grad(), torch.autocast("cuda", dtype=torch.bfloat16):
    for n in nets:
        votes += (torch.softmax(n(x).float(), 1)[0, 1] >= 0.5).to(torch.uint8)
mask = (votes >= 3)

For volumes larger than 128³, tile at stride 64 (50% overlap) and combine overlapping tiles with a max over votes — a plaque clipped at one tile edge is recovered by the tile that contains it whole. Benchmarked throughput on one L40S: 27.8 ms/tile at bf16, batch 8 (batching past 4 buys almost nothing; bf16 over fp32 is worth ~1.4×).

Training data

75 patches of 128³ from 30 App-NLGF mice (mouse_app_lecanemab_ki3_aggregated), Abeta channel, hand-QC'd. Labels are re-curated: the previous model's held-out predictions were reviewed patch by patch and each patch assigned the segmentation judged best.

label source patches
model prediction (previous LANTERN model, held-out) 57
original hand GT 10
hand-revised model prediction 5
prediction from a lower size-floor model 1
hand GT with a size floor applied 2

Ground truth carries a 9-voxel minimum connected-component floor, applied before training and before evaluation — objects smaller than that are neither learned nor scored.

Loss DiceCE with batch-Dice, 250 epochs, AdamW lr 1e-3, batch 2 × 4 accumulation, bf16. Augmentation: axis flips, one 90° rotation, mild gamma and Gaussian noise.

Evaluation

Object F1 at IoU ≥ 0.5 on 26-connected components, micro-averaged. Two references, and the difference matters:

reference object F1 precision recall FP/patch
the re-curated labels (out-of-fold) 0.6345 0.574 0.710 106
fixed original hand GT (80 patches) 0.4482 0.413 0.490 158
previous model, same fixed GT 0.4295 0.380 0.493 181

The first row is inflated and should not be quoted as accuracy: 57 of 75 training labels are the previous model's own output, so the model is partly graded against an answer key its predecessor wrote. Against the fixed hand GT — the one reference that did not move — this model beats its predecessor by +0.019 object F1 (paired per-patch, better on 44/80). The real gain is precision, 0.380 → 0.413, at unchanged recall: fewer false positives, not more plaques found.

Voxel Dice is 0.806 but is a poor primary metric here — plaque foreground is ~1% of a patch, and Dice barely moves when ~100 false-positive components per patch are removed.

Limitations

  • Scale sensitivity is severe. The model is trained at 4.4 × 3.25 × 3.25 µm and has no scale invariance. On a cohort acquired at z = 2.75 µm (1.6× finer) it predicted 0.21× the expected foreground volume. Resample to the training grid before inference; do not run it on a different pyramid level.
  • Intensity normalisation must match. Percentile clip then z-score, computed per tile on raw intensities. The model was never trained on N4-corrected or otherwise rescaled data.
  • Self-training bias. Most labels derive from an earlier model, so the ensemble reinforces that model's systematic biases. Judge it on human-annotated data only.
  • Optimistic validation. The 5-fold split is patch-level, not subject-grouped, so patches from the same mouse appear in train and val. Expect worse performance on an unseen animal.
  • Cohort narrowness. One study, App-NLGF genotype, one stain and acquisition protocol. Four PBS-treated subjects contributed no training patches, so the treated (Lecanemab) arm is over-represented: 41 patches vs 29.
  • Small objects. Anything under 9 voxels is outside the task definition by construction.
  • Not validated for absolute burden. Reported numbers are detection metrics on 128³ patches; whole-brain plaque-load quantification has not been validated against an independent measure.

Files

fold0..fold4/seg_model.pt   torch checkpoint: state_dict, config, per-fold val metrics
config.json                 architecture + preprocessing contract

Each checkpoint also carries the training config and that fold's validation metrics.

Citation

Code: https://github.com/Arshya-Guru/LANTERN

Released for non-commercial research use (CC BY-NC 4.0). The underlying imaging data is not included and is not released here.

Downloads last month
17
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support