Registry and method contract¶
The registry resolves a configuration's method name to a BaseMethod
subclass. BaseMethod defines the lifecycle used by both training and
evaluation.
methods
¶
Method registry.
The unified train.py calls get_method(name)(cfg) to obtain a
BaseMethod instance. Adding a new entry below is enough to expose
it on the command line.
get_method
¶
Resolve a method name or supported alias to its adapter class.
Imports are intentionally lazy so registry inspection does not initialize foundation models or require every method's optional dependencies.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
Canonical method name or a documented command-line alias. |
required |
Returns:
| Type | Description |
|---|---|
Type['BaseMethod']
|
The matching :class: |
Raises:
| Type | Description |
|---|---|
KeyError
|
If |
Source code in methods/__init__.py
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 | |
list_methods
¶
get_backbone_contracts
¶
Return every adapter's declared encoder contract, keyed by method.
Returns:
| Type | Description |
|---|---|
dict[str, 'MethodBackboneContract']
|
A mapping from canonical registry name to its immutable |
dict[str, 'MethodBackboneContract']
|
class: |
Source code in methods/__init__.py
base
¶
Method registry.
Every paper in this codebase is exposed through a BaseMethod adapter
that has a uniform interface. The unified train.py then dispatches
to the right method by looking it up in the registry below.
Adding a new method¶
- Create a folder
methods/<my_method>/with a__init__.py. - Put the method's unique model file(s) there. Re-use anything you
can from
common/. -
Subclass
BaseMethod(filemethods/<my_method>/adapter.py) and implement at minimum:build_model(self, cfg) -> nn.Module train_step(self, batch, model, optimizer, loss_fn) -> dict eval_step(self, batch, model, loss_fn) -> dict
Many methods can simply inherit CLAMScaffoldMethod (defined below)
which already wires up the FOCUS/ViLa-MIL training loop.
4. Register the adapter in methods/__init__.py METHODS = {...}.
That's it -- train.py --method <my_method> --config configs/<my>.yaml
will pick it up.
BaseMethod
¶
Bases: ABC
Define the uniform lifecycle implemented by every method adapter.
A method adapter holds the recipe for a paper: - how to instantiate the model from a config dict - how a single train step looks - how a single eval step looks
State that survives across steps (e.g. running EMA, prototypes,
pseudo labels) should live as attributes on self.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cfg
|
Dict[str, Any]
|
Validated run configuration. Each adapter receives a private copy so method-specific defaults cannot alter the persisted run identity or leak into another cross-validation fold. |
required |
device
|
str
|
PyTorch device used for model parameters and input batches. |
'cuda'
|
Source code in methods/base.py
get_backbone_contract
classmethod
¶
get_backbone_contract() -> MethodBackboneContract
Return the encoder/feature contract declared by the adapter.
Raises:
| Type | Description |
|---|---|
NotImplementedError
|
If the adapter omitted its required contract. |
Source code in methods/base.py
load_encoder
¶
load_encoder(
*,
weights_path: Optional[str] = None,
**loader_options: Any,
) -> EncoderBundle
Build and validate the configured encoder in one operation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
weights_path
|
Optional[str]
|
Optional local checkpoint or model identifier. When
omitted, |
None
|
**loader_options
|
Any
|
Family-specific options forwarded to the encoder registry, such as a pinned revision or offline-only loading. |
{}
|
Returns:
| Type | Description |
|---|---|
EncoderBundle
|
A validated capability-aware encoder bundle. |
Raises:
| Type | Description |
|---|---|
RuntimeError
|
If the adapter has no runtime backbone contract. |
BackboneCompatibilityError
|
If the bundle violates the method contract or declared feature provenance. |
Source code in methods/base.py
build_model
abstractmethod
¶
train_step
abstractmethod
¶
Run one optimization step.
Returns:
| Type | Description |
|---|---|
Dict[str, float]
|
A mapping containing at least |
Source code in methods/base.py
eval_step
abstractmethod
¶
Run a forward-only validation or test step.
Returns:
| Type | Description |
|---|---|
Dict[str, float]
|
A mapping containing at least |
Source code in methods/base.py
build_optimizer
¶
Build Adam over trainable parameters using the configured recipe.
Source code in methods/base.py
build_scheduler
¶
Default: ReduceLROnPlateau(min, factor=0.1, patience=10).
Adapters override this whenever the released executable recipe uses a different scheduler or constructs one without ever stepping it.
Source code in methods/base.py
validation_monitor
¶
Return the minimized value used for best-checkpoint selection.
The unified loop cannot assume that every released method selects its checkpoint by cross-entropy. Several paper repositories use validation error, while MSCPT uses a task-dependent F1/AUC or F1/ACC composite. Adapters override this hook to preserve that executable recipe. Values are always expressed as a minimization objective so the checkpoint writer has one unambiguous contract.
Source code in methods/base.py
prepare_fold
¶
Prepare training-split-only state after model/data construction.
Methods such as PathPT use this boundary to select prompts without seeing validation or test slides. The default is deliberately a no-op.
Source code in methods/base.py
on_train_epoch_start
¶
on_epoch_end
¶
on_validation_end
¶
Handle a completed validation pass, including epoch -1.
The default forwards to the historical on_epoch_end hook. Adapters
which accumulate validation predictions therefore get a clear boundary
for the optional initial evaluation as well as every trained epoch.
Source code in methods/base.py
on_fold_end
¶
on_checkpoint_loaded
¶
interpret_step
¶
interpret_step(
batch: Any,
model: Module,
target_class: int | None = None,
) -> "InterpretabilityResult"
Return native, patch-aligned evidence for one evaluation slide.
Adapters must override this hook only when their score semantics and patch ordering are known. The default intentionally refuses to invent a generic "attention" map from hidden activations.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
batch
|
Any
|
One loader batch for a single slide. |
required |
model
|
Module
|
Loaded fold checkpoint in evaluation mode. |
required |
target_class
|
int | None
|
Optional class index for class-specific evidence. |
None
|
Raises:
| Type | Description |
|---|---|
NotImplementedError
|
If the method has no audited patch-evidence mapping in PGVL-Gym. |