Channel strategies: any montage in#

The 19 pretrained EEG models take channel_strategy= to map your montage onto the channels their backbone was trained on. SleepFM and SleepFMStager take polysomnography grouped by modality, not an EEG montage, so they accept only "native":

from braindecode.models import EEGPT

model = EEGPT.from_pretrained(
    "braindecode/eegpt-pretrained",
    chs_info=raw.info["chs"],  # your montage
    channel_strategy="spline",  # how to map it
)
y = model(x)  # x: (batch, len(chs_info), n_times)
y = model(x_other, chs_info=other_chs)  # another montage, per call

"native" (the default) leaves the model as it is: the released checkpoints give the same outputs (max-abs difference 0.0) with the same state_dict. Any other strategy puts a ChannelLayer in front of the backbone, which is then built on its pre-training montage (LaBraM, EEGPT, BENDR, BIOT, CodeBrain, EEG-DINO, MIRepNet) or on the montage given at construction (the others). channel_strategy and channel_strategy_kwargs are saved in the config.

The layer is one matrix per montage. Channels found in the input are copied: same name (case-insensitive), a legacy name (T3 = T7), or a channel whose name MNE does not know within 15 mm. The strategy fills the other targets:

  • exact: nothing; a missing channel is a ValueError.

  • zero, nearest, idw: zeros, nearest electrode, inverse-distance mean (p=2).

  • spline: MNE spherical spline (reg=1e-3). field: MNE field mapping.

  • source: minimum-norm inverse on a template sphere head (n_parcels=64), projected back; scalp EEG only. trainable=True adds a parcel mixing initialised at zero, so training starts from the physics.

  • region: mean of the inputs within radius (default 1.5 x the median spacing of the input montage); none in range gives a zero row.

  • wiener: linear MMSE from a spatial covariance fitted on dense recordings with model.channel_layer.fit(X, chs_info_dense) (X: samples x dense channels, matched by position within 15 mm; noise=0.01). The fit is saved in the state_dict; an unfitted map raises.

  • latent: learned (POYO-style) cross-attention: each missing target’s position queries the inputs’ positions and signal statistics. Its weights live under channel_layer.*, so a backbone checkpoint still loads.

Positions come from loc, else from standard_1005 by name. spline, field and source need at least four positioned channels; a map whose row gain exceeds 2 warns. A target without a position (BENDR’s SCALE) is zero unless the input has it; a target named A-B (BIOT) is V(A) - V(B). Non-EEG channels raise unless channel_strategy_kwargs={"drop_non_eeg": True}. The layer runs in eager mode; TorchScript works under native only.

The tutorial Running a Pretrained Model on Any Channel Set with the Channel Layer compares strategies on a recording.