Skip to content

Total Perspective Vortex

A brain-computer interface that classifies EEG motor-imagery signals: a from-scratch CSP spatial filter feeds logistic regression, wired as a scikit-learn pipeline.

TL;DR
  • 109 subjects
  • 8–30 Hz band-pass

My partImplemented Common Spatial Patterns from scratch — trace-normalised per-class covariances, a generalised eigenvalue decomposition and log-variance features — as a scikit-learn transformer.

ROLE
Solo
CONTEXT
École 42 · AI projects
STATUS
Done
RESULT
The pipeline runs end to end; on the single logged run (subject 4) it reaches 0.53 cross-validated accuracy, near the two-class chance level. The from-scratch CSP and the scikit-learn integration are the work, not the score.
LAST UPDATED
26 Sep 2026
EEGPhysioNet · .edfband-pass8-30 Hz · MNEepochs-0.5 s to 4 sCSPfrom scratchlogistic reg.sklearn pipelinepredicttwo-class task
Fig. — how it works
1

Data

PhysioNet EEG Motor Movement/Imagery: 109 subjects, 64-channel EEG at 160 Hz; runs 3–14, left/right fist and both fists/both feet.

2

What I built

Solo

  1. Implemented Common Spatial Patterns from scratch — trace-normalised per-class covariances, a generalised eigenvalue decomposition and log-variance features — as a scikit-learn transformer.
  2. Built the pipeline: the custom CSP feeding logistic regression, with k-fold cross-validation and model save and load.
  3. Wrote the MNE preprocessing layer: EDF loading, an 8–30 Hz band-pass, event extraction and epoching.
  4. Built the command-line tool (train, predict, stream) and a batch loop over all 109 subjects.
3

Key choices

CSP written from scratch, not the library one
The subject requires a hand-implemented dimensionality reduction, so the covariances, the generalised eigenvalue problem and the projection matrix are computed directly; MNE's CSP is kept only as a reference to check against.
A scikit-learn-compatible transformer
The CSP subclasses BaseEstimator and TransformerMixin, so it composes with logistic regression in one pipeline and runs through cross-validation unchanged.
An 8–30 Hz band and a sensorimotor focus
Filtering is restricted to the mu and beta bands where motor-imagery activity lives, with epochs cut from −0.5 s to 4 s around each event.
4

Results

The pipeline runs end to end; on the single logged run (subject 4) it reaches 0.53 cross-validated accuracy, near the two-class chance level. The from-scratch CSP and the scikit-learn integration are the work, not the score.

5

Limits

  • Stream mode is offline replay, not live acquisition: it loops over pre-computed epochs one at a time and prints the processing time.
  • One global model per task type, overwritten on each training run; there are no per-subject saved models.
  • The evaluation is optimistic: cross-validation is measured on a single run, with no held-out subject and no separate validation set.
  • On the one logged run, classification stays near the two-class chance level — the from-scratch CSP and the scikit-learn integration are the substance, not the score.

Questions about this project? → Email me