CNN Module#

Stacked 1-D convolutional blocks (Conv1d + BatchNorm1d + ReLU + MaxPool1d + Dropout) with a flatten + dense classification head. Engineering adaptation of the standard 1-D CNN template to binned MALDI-TOF spectra; not a novel architecture.

MaldiCNNClassifier#

class maldideepkit.MaldiCNNClassifier(input_dim=None, n_classes=2, channels=(32, 64, 128, 128), kernel_size=7, pool_size=2, head_dim=128, dropout=0.3, learning_rate=0.001, weight_decay=0.0, grad_clip_norm=None, 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=0, standardize=False, input_transform=None, 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 CNN classifier for MALDI-TOF spectra.

Parameters:
  • channels (tuple[int, ...]) – Output channels of each convolutional block. The effective spatial resolution is divided by the corresponding pool_size after every block.

  • kernel_size (Union[int, Sequence[int]]) – Kernel size per block. A scalar is broadcast; a sequence must match the length of channels. The default is calibrated for bin_width=3; from_spectrum() scales it for other bin widths.

  • pool_size (Union[int, Sequence[int]]) – Pool factor per block. Accepts scalar or per-block sequence.

  • head_dim (int) – Width of the hidden dense layer.

  • dropout (float) – Dropout applied inside every block and before the output 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. See its docstring for the full list.

The flat dense head scales linearly with input_dim; prefer MaldiResNetClassifier or MaldiTransformerClassifier if you want a head width that’s independent of the input resolution.

See from_spectrum() for a factory that auto-scales kernel_size for a given (bin_width, input_dim) layout.

Examples

>>> import numpy as np
>>> from maldideepkit import MaldiCNNClassifier
>>> rng = np.random.default_rng(0)
>>> X = rng.standard_normal((32, 256)).astype("float32")
>>> y = rng.integers(0, 2, size=32)
>>> clf = MaldiCNNClassifier(epochs=2, batch_size=8, random_state=0).fit(X, y)
>>> clf.predict(X).shape
(32,)

Per-block kernel progression:

>>> clf = MaldiCNNClassifier(
...     channels=(32, 64, 128, 128),
...     kernel_size=(11, 7, 5, 3),
... )
Parameters:
__init__(input_dim=None, n_classes=2, channels=(32, 64, 128, 128), kernel_size=7, pool_size=2, head_dim=128, dropout=0.3, learning_rate=0.001, weight_decay=0.0, grad_clip_norm=None, 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=0, standardize=False, input_transform=None, 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 classifier with kernel_size scaled for bin_width.

Scales kernel_size inversely with bin_width relative to the package reference (bin_width=3, kernel_size=7). Any keyword in **overrides wins over the auto-scaled value.

Parameters:
  • bin_width (int) – Bin width in Daltons (e.g. 3 for the MaldiAMRKit default, 6 for coarser binning).

  • input_dim (int) – Number of bins in the input. Stored on the classifier for shape validation.

  • **overrides – Any additional keyword arguments override the scaled defaults.

Returns:

An unfitted estimator with kernel_size scaled for the given bin_width.

Return type:

MaldiCNNClassifier

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 (MaldiCNNClassifier)

Returns:

self – The updated object.

Return type:

object

SpectralCNN1D#

class maldideepkit.cnn.cnn.SpectralCNN1D(input_dim, n_classes=2, channels=(32, 64, 128, 128), kernel_size=7, pool_size=2, head_dim=128, dropout=0.3)[source]#

Bases: Module

Stack of Conv1D blocks with a dense classification head.

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

  • n_classes (int) – Number of output logits.

  • channels (tuple[int, ...]) – Output channels of each convolutional block.

  • kernel_size (Union[int, Sequence[int]]) – Kernel size per block. A scalar is broadcast to every block; a sequence must have the same length as channels.

  • pool_size (Union[int, Sequence[int]]) – Pool factor per block. A scalar is broadcast to every block; a sequence must have the same length as channels.

  • head_dim (int) – Width of the single hidden dense layer.

  • dropout (float) – Dropout applied inside every block and before the output layer.

Notes

Input tensors have shape (batch, input_dim) and are unsqueezed to (batch, 1, input_dim) internally.

__init__(input_dim, n_classes=2, channels=(32, 64, 128, 128), kernel_size=7, pool_size=2, head_dim=128, dropout=0.3)[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

Examples#

import numpy as np
from maldideepkit import MaldiCNNClassifier

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

clf = MaldiCNNClassifier(
    channels=(32, 64, 128, 128),
    kernel_size=7,             # scalar broadcasts to every block
    pool_size=2,
    random_state=0,
).fit(X, y)

Per-block kernel / pool progression:

clf = MaldiCNNClassifier(
    channels=(32, 64, 128, 128),
    kernel_size=(11, 7, 5, 3),  # wider early, narrower late
    pool_size=(2, 2, 2, 4),     # more aggressive pooling on last block
)

Auto-scale for a different spectrum layout:

clf = MaldiCNNClassifier.from_spectrum(
    bin_width=6, input_dim=3000, random_state=0,
)  # picks kernel_size=5 (scaled from 7 at the bin_width=3 reference)