ResNet Module#

1-D ResNet-18-style residual stack adapted to MALDI-TOF spectra. A Conv1d stem (optionally followed by MaxPool1d), four stages of BasicBlock1D pairs with strided downsampling between stages, global average pooling, and a linear head. Engineering adaptation of ResNet-18 (He et al., 2016) to spectral input; not a novel architecture.

Peak-friendly defaults. MaldiDeepKit deliberately deviates from the literal ResNet-18 stem in three ways that matter on ~6000-bin MALDI-TOF input: stem_stride=1 (was 2), block_kernel_size=7 (was 3), and use_stem_pool=False (no stem MaxPool). Empirically, the literal ResNet-18 configuration (combined 4x initial downsampling) collapses peak-scale features on MALDI spectra and the model underfits. The literal backbone remains reachable via stem_stride=2, block_kernel_size=3, use_stem_pool=True.

MaldiResNetClassifier#

class maldideepkit.MaldiResNetClassifier(input_dim=None, n_classes=2, stem_channels=32, stage_channels=(64, 128, 256, 512), blocks_per_stage=(2, 2, 2, 2), stem_kernel_size=7, stem_stride=1, block_kernel_size=7, use_stem_pool=False, dropout=0.2, learning_rate=0.001, weight_decay=0.0001, grad_clip_norm=1.0, label_smoothing=0.0, loss='cross_entropy', focal_gamma=2.0, use_amp=False, swa_start_epoch=None, tune_threshold=False, threshold_metric='balanced_accuracy', calibrate_temperature=False, min_val_auroc_for_threshold_tune=0.6, use_sam=False, sam_rho=0.05, batch_size=32, epochs=100, early_stopping_patience=10, val_fraction=0.1, warmup_epochs=5, standardize=False, input_transform='log1p', warping=None, metrics_log_path=None, track_train_metrics=False, augment=None, mixup_alpha=0.0, cutmix_alpha=0.0, ema_decay=None, retry_on_val_auroc_below=None, max_retries=2, class_weight=None, device='auto', random_state=0, verbose=False)[source]#

Bases: BaseSpectralClassifier

sklearn-compatible 1-D ResNet classifier for MALDI-TOF spectra.

Parameters:
  • stem_channels (int) – Output channels of the stem.

  • stage_channels (tuple[int, ...]) – Output channels of each residual stage.

  • blocks_per_stage (tuple[int, ...]) – Number of residual blocks per stage (ResNet-18 topology).

  • stem_kernel_size (int) – Kernel size of the stem Conv1D. Calibrated for bin_width=3; from_spectrum() scales it for other bin widths.

  • stem_stride (int) – Stride of the stem Conv1D. Defaults to 1 so the first residual stage sees full-resolution input.

  • block_kernel_size (int) – Kernel size inside every BasicBlock1D. Widened from ResNet-18’s 3 so each block has enough local context for peak-scale features.

  • use_stem_pool (bool) – If True, append the literal ResNet-18 MaxPool after the stem Conv. Defaults to False because the combined stem(stride=2) + MaxPool(stride=2) 4x downsampling is too aggressive for MALDI-TOF peak structure. Set to True to reproduce the literal ResNet-18 backbone.

  • dropout (float) – Dropout before the final linear layer.

  • input_dim (int | None)

  • n_classes (int)

  • learning_rate (float)

  • weight_decay (float)

  • grad_clip_norm (float | None)

  • label_smoothing (float)

  • loss (str)

  • focal_gamma (float)

  • use_amp (bool)

  • swa_start_epoch (int | None)

  • tune_threshold (bool)

  • threshold_metric (str)

  • calibrate_temperature (bool)

  • min_val_auroc_for_threshold_tune (float)

  • use_sam (bool)

  • sam_rho (float)

  • batch_size (int)

  • epochs (int)

  • early_stopping_patience (int)

  • val_fraction (float)

  • warmup_epochs (int)

  • standardize (bool)

  • input_transform (str | None)

  • warping (Any | None)

  • metrics_log_path (str | Path | None)

  • track_train_metrics (bool)

  • augment (Any | None)

  • mixup_alpha (float)

  • cutmix_alpha (float)

  • ema_decay (float | None)

  • retry_on_val_auroc_below (float | None)

  • max_retries (int)

  • class_weight (str | np.ndarray | list | None)

  • device (str | torch.device)

  • random_state (int)

  • verbose (bool)

Notes

Every parameter accepted by BaseSpectralClassifier (e.g. learning_rate, batch_size, epochs, warping, calibrate_temperature, device, random_state, …) is forwarded to the base class. The ResNet defaults pre-set weight_decay=1e-4, grad_clip_norm=1.0, warmup_epochs=5, and input_transform="log1p"; override any of them at construction time.

Defaults deviate from literal ResNet-18 (He et al., 2016) in three ways for MALDI-TOF: stem_stride=1 (was 2), block_kernel_size=7 (was 3), and use_stem_pool=False (was True). The literal backbone is reproducible via stem_stride=2, block_kernel_size=3, use_stem_pool=True.

The final head is a Linear(stage_channels[-1], n_classes) after global average pooling, so the parameter count is independent of ``input_dim``.

Examples

>>> import numpy as np
>>> from maldideepkit import MaldiResNetClassifier
>>> rng = np.random.default_rng(0)
>>> X = rng.standard_normal((32, 512)).astype("float32")
>>> y = rng.integers(0, 2, size=32)
>>> clf = MaldiResNetClassifier(
...     epochs=2, batch_size=8, stage_channels=(16, 32),
...     blocks_per_stage=(1, 1), random_state=0
... ).fit(X, y)
>>> clf.predict(X).shape
(32,)
Parameters:
__init__(input_dim=None, n_classes=2, stem_channels=32, stage_channels=(64, 128, 256, 512), blocks_per_stage=(2, 2, 2, 2), stem_kernel_size=7, stem_stride=1, block_kernel_size=7, use_stem_pool=False, dropout=0.2, learning_rate=0.001, weight_decay=0.0001, grad_clip_norm=1.0, label_smoothing=0.0, loss='cross_entropy', focal_gamma=2.0, use_amp=False, swa_start_epoch=None, tune_threshold=False, threshold_metric='balanced_accuracy', calibrate_temperature=False, min_val_auroc_for_threshold_tune=0.6, use_sam=False, sam_rho=0.05, batch_size=32, epochs=100, early_stopping_patience=10, val_fraction=0.1, warmup_epochs=5, standardize=False, input_transform='log1p', warping=None, metrics_log_path=None, track_train_metrics=False, augment=None, mixup_alpha=0.0, cutmix_alpha=0.0, ema_decay=None, retry_on_val_auroc_below=None, max_retries=2, class_weight=None, device='auto', random_state=0, verbose=False)[source]#
Parameters:
Return type:

None

classmethod from_spectrum(bin_width, input_dim, **overrides)[source]#

Construct a peak-friendly ResNet for a given spectrum layout.

Scales stem_kernel_size inversely with bin_width relative to the package reference (bin_width=3, stem_kernel_size=7). Also sets stem_stride=1 and use_stem_pool=False (the class defaults). Any keyword in **overrides wins over the auto-selected values.

Parameters:
  • bin_width (int)

  • input_dim (int)

Return type:

MaldiResNetClassifier

set_fit_request(*, warm_start='$UNCHANGED$')#

Configure whether metadata should be requested to be passed to the fit method.

Note that this method is only relevant when this estimator is used as a sub-estimator within a meta-estimator and metadata routing is enabled with enable_metadata_routing=True (see sklearn.set_config()). Please check the User Guide on how the routing mechanism works.

The options for each parameter are:

  • True: metadata is requested, and passed to fit if provided. The request is ignored if metadata is not provided.

  • False: metadata is not requested and the meta-estimator will not pass it to fit.

  • None: metadata is not requested, and the meta-estimator will raise an error if the user provides it.

  • str: metadata should be passed to the meta-estimator with this given alias instead of the original name.

The default (sklearn.utils.metadata_routing.UNCHANGED) retains the existing request. This allows you to change the request for some parameters and not others.

Added in version 1.3.

Parameters:
  • warm_start (str, True, False, or None, default=sklearn.utils.metadata_routing.UNCHANGED) – Metadata routing for warm_start parameter in fit.

  • self (MaldiResNetClassifier)

Returns:

self – The updated object.

Return type:

object

SpectralResNet1D#

class maldideepkit.resnet.resnet.SpectralResNet1D(input_dim, n_classes=2, stem_channels=32, stage_channels=(64, 128, 256, 512), blocks_per_stage=(2, 2, 2, 2), stem_kernel_size=7, stem_stride=1, block_kernel_size=7, use_stem_pool=False, dropout=0.2)[source]#

Bases: Module

1-D ResNet-18 style backbone with a linear classification head.

Parameters:
  • input_dim (int) – Number of input bins.

  • n_classes (int) – Number of output logits.

  • stem_channels (int) – Output channels of the initial Conv1d + pool stem.

  • stage_channels (tuple[int, ...]) – Output channels of each stage. The first stage keeps the stem resolution; later stages downsample by 2.

  • blocks_per_stage (tuple[int, ...]) – Number of BasicBlock1D pairs per stage.

  • stem_kernel_size (int) – Kernel size of the stem Conv1D.

  • stem_stride (int) – Stride of the stem Conv1D. Defaults to 1 (vs literal ResNet-18’s 2) to preserve peak-scale features through the first stage on ~6000-bin spectra.

  • block_kernel_size (int) – Kernel size inside every BasicBlock1D. Widened from ResNet-18’s 3 to give each block enough local context for peak-scale features.

  • use_stem_pool (bool) – If True, append the literal ResNet-18 MaxPool1d(kernel=3, stride=2) after the stem Conv. Defaults to False because the combined stem-Conv(stride=2) + MaxPool(stride=2) initial 4x downsampling collapses peak-scale features. Set to True to reproduce the literal ResNet-18 backbone.

  • dropout (float) – Dropout applied after global average pooling.

__init__(input_dim, n_classes=2, stem_channels=32, stage_channels=(64, 128, 256, 512), blocks_per_stage=(2, 2, 2, 2), stem_kernel_size=7, stem_stride=1, block_kernel_size=7, use_stem_pool=False, dropout=0.2)[source]#

Initialize internal Module state, shared by both nn.Module and ScriptModule.

Parameters:
Return type:

None

forward(x)[source]#

Map (batch, input_dim) to (batch, n_classes) logits.

Parameters:

x (Tensor)

Return type:

Tensor

BasicBlock1D#

class maldideepkit.resnet.resnet.BasicBlock1D(in_channels, out_channels, stride=1, kernel_size=3)[source]#

Bases: Module

Two Conv1D layers with a residual shortcut.

Parameters:
  • in_channels (int) – Number of input channels.

  • out_channels (int) – Number of output channels.

  • stride (int) – Stride of the first Conv1D. A stride != 1 (or a channel mismatch) triggers a 1x1 projection on the shortcut path.

  • kernel_size (int) – Kernel size of both Conv1D layers.

__init__(in_channels, out_channels, stride=1, kernel_size=3)[source]#

Initialize internal Module state, shared by both nn.Module and ScriptModule.

Parameters:
  • in_channels (int)

  • out_channels (int)

  • stride (int)

  • kernel_size (int)

Return type:

None

forward(x)[source]#

Apply the residual block to a (N, C, L) activation tensor.

Parameters:

x (Tensor)

Return type:

Tensor

Examples#

Peak-friendly defaults (recommended for MALDI-TOF):

import numpy as np
from maldideepkit import MaldiResNetClassifier

rng = np.random.default_rng(0)
X = rng.standard_normal((400, 6000)).astype("float32")
y = rng.integers(0, 2, size=400)

# Defaults: stem_stride=1, block_kernel_size=7, use_stem_pool=False
clf = MaldiResNetClassifier(random_state=0).fit(X, y)

Literal ResNet-18 backbone (for literature reproducibility):

clf = MaldiResNetClassifier(
    stem_kernel_size=7,
    stem_stride=2,
    block_kernel_size=3,
    use_stem_pool=True,
    random_state=0,
)

Auto-scale the stem for a different spectrum layout:

clf = MaldiResNetClassifier.from_spectrum(
    bin_width=6, input_dim=3000, random_state=0,
)
# stem_kernel_size=5 (scaled from 7 at bin_width=3), stem_stride=1,
# use_stem_pool=False (peak-friendly stem preserved regardless of
# bin width; pass use_stem_pool=True as an override to reproduce
# the literal ResNet-18 stem at any bin width).