CBraMod-CoreML-Apple

CBraMod as a native Core ML embedding extractor for Apple platforms (macOS / iOS / visionOS), fp32, validated to rel-L2 1.3e-5 against the PyTorch reference.

This repository packages the pretrained CBraMod EEG foundation model (Wang et al., ICLR 2025) β€” via the braindecode re-hosted checkpoint braindecode/cbramod-pretrained β€” as a single .mlpackage that maps a 14-channel EEG window to a 14,000-dimensional embedding, entirely on-device via CoreML.framework.

It is published as a companion to the ZUNA Core ML profiles: in our 109-subject motor-imagery evaluation, CBraMod embeddings were the strongest foundation-model feature for sustained motor-imagery decoding, so this artifact is the MI engine of an on-device BCI stack.

What is in the package

Item Value
Model CBraModEmbedder.mlpackage (fp32 mlprogram)
Backbone CBraMod criss-cross transformer, pretrained weights, classification head removed (Identity)
Input eeg β€” float32 [1, 14, 1000] (14 channels Γ— 5 s @ 200 Hz)
Output embedding β€” float32 [1, 14000] (flattened patch embeddings: 14 ch Γ— 5 patches Γ— 200 dims)
Size ~20 MB weights
Conversion coremltools 9.0, torch.export frontend (TorchExport::ATEN dialect)

The channel count (14) matches the Emotiv EPOC X montage (AF3, F7, F3, FC5, T7, P7, O1, O2, P8, T8, FC6, F4, F8, AF4), but nothing in the backbone is montage-specific beyond the fixed input shape: CBraMod treats channels symmetrically at the patch level, so any 14-channel montage at 200 Hz can use this package. For other channel counts, re-export from source (script linked below).

Expected preprocessing

The parity and task-level validation below used this exact chain (matching the upstream evaluation convention of z-scored inputs):

  1. Window the raw EEG to 5 s.
  2. Average-reference across the available channels.
  3. Global z-score the window (single mean/std over all channels and samples).
  4. Resample to 200 Hz (polyphase), crop/zero-pad to exactly 1000 samples.

Validation

All gates were run against the original PyTorch checkpoint on real EEG (PhysioNet EEGBCI motor-imagery recordings mapped to the 14-channel montage), not random tensors.

Check Result
Numerical parity (worst rel-L2 over 36 real windows, two window regimes, CPU_ONLY) 1.3e-5 (gate 1e-4) β€” see parity.json
Export fidelity (torch.export module vs eager PyTorch) bit-exact
Task-level equivalence (held-out-run MI accuracy, subjects 1–5, Core ML vs PyTorch embeddings) identical (max accuracy diff 0.000)
Native Swift / CoreML.framework smoke (compile, load, predict, finite outputs) PASS (0.44 s load, 1.27 s cold first prediction on an M3 Max)

Downstream context (not a property of this artifact, but of the underlying checkpoint): on 109 PhysioNet EEGBCI subjects with held-out-run evaluation, CBraMod embeddings + logistic regression reached 63.7% Β± 13.8% left/right-hand sustained motor-imagery accuracy on cue-offset windows (a control that excludes visual-cue-evoked confounds), significantly above every classical and FM baseline we tested (paired test vs best prior, p β‰ˆ 2e-6).

Conversion notes (for reproducers)

Two standard approaches fail on this architecture; both failures are worth knowing:

  • torch.jit.trace is non-deterministic here unless torch.backends.mha.set_fastpath_enabled(False) is set (nn.MultiheadAttention's fastpath produces divergent traces), and even then Core ML const-folding fails on ~349 symbolic-int (aten::Int) nodes arising from CBraMod's criss-cross reshape arithmetic.
  • torch.export.export(...).run_decompositions({}) converts cleanly: the modern frontend specializes static shapes to constants, eliminating the symbolic-int nodes. This is the recommended path for reshape-heavy transformers.

The export script (including the parity and task-equivalence gates) is open source: scripts/port_cbramod_coreml.py.

Usage

Python (coremltools)

import numpy as np
import coremltools as ct
from huggingface_hub import snapshot_download

# NOTE: use local_dir β€” the default symlinked HF cache breaks the Core ML
# compiler, which cannot resolve a symlinked weight.bin inside an .mlpackage.
repo = snapshot_download("oraculumai/CBraMod-CoreML-Apple", local_dir="CBraMod-CoreML-Apple")
model = ct.models.MLModel(f"{repo}/CBraModEmbedder.mlpackage")

eeg = np.random.randn(1, 14, 1000).astype(np.float32)  # preprocessed as above
embedding = model.predict({"eeg": eeg})["embedding"]   # (1, 14000)

Swift (CoreML.framework)

import CoreML

// Compile once: xcrun coremlcompiler compile CBraModEmbedder.mlpackage <outdir>
let model = try MLModel(contentsOf: compiledURL)
let input = try MLMultiArray(shape: [1, 14, 1000], dataType: .float32)
// ... fill input with the preprocessed window ...
let out = try model.prediction(from: MLDictionaryFeatureProvider(dictionary: ["eeg": input]))
let embedding = out.featureValue(for: "embedding")!.multiArrayValue!  // [1, 14000]

A typical decoder is a small linear head (e.g. logistic regression) trained on these embeddings; the 63.7% MI result above is exactly that.

Limitations

  • Fixed input shape [1, 14, 1000]. Other montages/window lengths require re-export.
  • fp32 only. We have not published a compressed variant; palettization/int8 were not validated for this model.
  • Research artifact. Not validated for medical diagnosis, treatment, or clinical decision-making. Use at your own risk and follow the base model's license (BSD-3-Clause).

Provenance & credit

If you use this model, please cite the original CBraMod paper and credit braindecode for the checkpoint distribution.

Downloads last month
10
Inference Providers NEW
This model isn't deployed by any Inference Provider. πŸ™‹ Ask for provider support

Model tree for oraculumai/CBraMod-CoreML-Apple

Quantized
(2)
this model