Spatial filters for decoding
Common spatial patterns, filters versus patterns and why only patterns are interpretable, xDAWN, and the bridge to decoding.
Prerequisites: L4.4 · Baseline normalization and ERD/ERS
3 claims on this page are unverified. TODO(confirm) marks a specific statement the author has not yet checked against a
primary source. Everything else on this page has been reviewed. Treat a marked claim as
provisional and go to the cited source rather than quoting the sentence.
Objectives
- Derive common spatial patterns
- Distinguish filters from patterns and interpret only patterns
- Recognize xDAWN
- Connect spatial filtering to Level 7 decoding
Why this matters
Volume conduction is a problem for interpretation and an opportunity for prediction. If every sensor is a mixture of every source, then some weighted combination of sensors is a much better view of one source than any single electrode — and you can find that combination from the data. Common spatial patterns does exactly that, it works, and it comes with one trap that has produced a long literature of wrong neuroanatomical claims: the weights you learn are not a picture of where the signal came from.
Concepts
The idea: find the combination, not the electrode
Motor imagery changes band power over sensorimotor cortex — the mu and beta desynchronization of L4.4 — and the change is lateralized. The naive decoder reads band power at C3 and C4. It works, a bit. It also throws away the other sixty-two electrodes, each of which sees some of the same sources.
CSP looks instead for a spatial filter w — a weight per channel — such that the filtered signal wᵀx(t) has maximally different variance between the two classes. Written as a ratio and solved as a generalized eigenvalue problem:
Σ₁ w = λ (Σ₁ + Σ₂) w
with Σ₁ and Σ₂ the class-mean covariance matrices over the analysis window. The eigenvalue has a direct reading: λ near 1 means all of that component’s variance sits in class 1, near 0 means all of it sits in class 2, and 0.5 means the component does not separate the classes at all, whatever its map looks like. Components are taken from both ends of the spectrum — the most class-1 and the most class-2 — and the middle is discarded.
Features are then the log variance of each filtered signal per trial, fed to an ordinary classifier (linear discriminant analysis, here). That is the whole method: a variance-ratio eigenproblem and a linear classifier.
Filters and patterns are different objects
Collect the filters as the columns of W. The patterns are then
A = (Wᵀ)⁻¹
and the two matrices answer different questions:
- A filter says how to weight the sensors to recover the component. It is a recipe for extraction.
- A pattern says how the component appears on the scalp — the topography a unit of that component produces at the electrodes. It is a forward quantity, of the same kind as a column of the leadfield in L5.4.
Only the pattern may be read as a topography. The reason is short and worth memorising: a filter has to cancel everything it is not extracting. If a strong occipital alpha source and a strong frontal muscle source are present in both classes, the filter that extracts sensorimotor mu must subtract them, so it carries large weights at occipital and frontal sites — sites where the component of interest has no activity at all. A large filter weight can mean “signal here” or “interference I am removing here”, and the map cannot tell you which. (Haufe et al., 2014) is the treatment of this for linear models generally; it applies to ICA unmixing matrices, to regression weights and to every linear decoder, not only to CSP.
What the two maps actually look like on real data
The shipped asset is one EEGMMIDB subject’s left-versus-right hand motor imagery: subject S002, runs R04, R08 and R12, 8–30 Hz, 0.5 to 2.5 s after the cue, 64 channels, 45 epochs, six components, mne.decoding.CSP into LDA. For each component the widget measures the angle between its filter and its pattern (folded to 0–90°, because a component’s overall sign is arbitrary), their correlation across sensors, their rank agreement on abs(weight), and each map’s peak electrode:
| Component | λ | Angle | r | Rank agreement | Peak: filter / pattern |
|---|---|---|---|---|---|
| 1 | 0.177 | 57.3° | 0.631 | 0.396 | FC3 / FC5 |
| 2 | 0.246 | 58.0° | 0.564 | 0.208 | CP5 / CP5 |
| 3 | 0.263 | 82.0° | 0.141 | 0.256 | C4 / P6 |
| 4 | 0.681 | 73.8° | 0.291 | 0.185 | C3 / CP3 |
| 5 | 0.319 | 82.2° | 0.158 | 0.330 | Iz / O2 |
| 6 | 0.321 | 73.4° | 0.292 | 0.361 | Iz / O2 |
Two rows carry the lesson.
Component 4 is the one that leans toward left-hand imagery (λ = 0.68, the furthest from 0.5 in the set). Its filter and its pattern are 73.8° apart, correlate at 0.29, and peak on different electrodes — C3 for the filter, CP3 for the pattern. Read the filter map as a topography and you have located the component one electrode off, with a scalp distribution that is mostly cancellation.
Component 2 is the more instructive case, because it is the one that would fool you. Both maps peak at the same electrode, CP5. A reader glancing at the two pictures would conclude they agree. Their rank agreement across the other sixty-three sensors is 0.21. Agreeing about one electrode is not agreeing about a topography.
More components is not monotonically better
The same data, the same cross-validation, different feature sets — every one of these with the spatial filter refitted inside each training fold:
| Feature set | Cross-validated accuracy |
|---|---|
| Log band power at C3 and C4 only, no spatial filter | 73.3 % ± 15.1 |
| CSP, 2 components | 51.1 % ± 18.1 |
| CSP, 4 components | 86.7 % ± 13.0 |
| CSP, 6 components | 86.7 % ± 13.0 |
| CSP, 8 components | 88.9 % ± 7.0 |
Two components scored 51.1 %, worse than using no spatial filter at all. That is a real result on real data and it is worth sitting with, because the usual intuition — CSP is a strictly better front end, and two components is the classic choice — predicts the opposite. With two components the method keeps only the single most extreme filter from each end of the eigenvalue spectrum, and on 45 epochs those two estimates are themselves noisy; four and six recover, and eight is marginally better still with a much smaller fold-to-fold spread. The spreads say the rest: at ±13 to ±18 points across five folds, most of the differences in this table are within the noise of each other, and the only one that is clearly outside it is CSP-2 falling below the no-filter baseline.
The number, and how the subject was chosen
The shipped pipeline’s cross-validated accuracy is 86.7 %, from folds of 88.9, 66.7, 100, 100 and 77.8 %. Chance is 50 % for two balanced classes — but with 45 epochs the 95 % binomial interval around chance runs from 35.4 % to 64.6 %, so a single subject’s accuracy anywhere inside that band is not evidence of anything.
And then the part that matters more than the number:
This subject was selected by accuracy. The rule was stated in advance and is recorded with the asset — the lowest-numbered subject whose mean cross-validated accuracy reaches 0.75 — but it is still a selection, and the same pipeline was run on all twelve candidates. Sorted, their accuracies are 44.4, 44.4, 46.7, 48.9, 51.1, 51.1, 60.0, 62.2, 66.7, 66.7, 86.7 and 95.6 %: a range of 44.4 % to 95.6 % with a median of 55.6 %. Eight of the twelve scored inside the chance band. The shipped subject is the second-highest of the twelve.
Quoting 86.7 % on its own — as an accuracy for this method, this dataset, or EEG motor imagery — teaches exactly the selection effect Level 6 exists to warn about. The honest sentence names all of it: “on a subject chosen by a pre-stated accuracy threshold from twelve candidates whose accuracies ranged 44.4 % to 95.6 % with a median of 55.6 %, the pipeline scored 86.7 % (45 epochs, chance band 35.4–64.6 %).” That sentence is longer and it is the one a reader can evaluate.
Where the fold boundary sits
CSP looks at the labels. Fit it once on all the epochs and then cross-validate only the classifier, and the spatial filters have already seen the test folds’ labels — so the test folds are not held out.
Same subject, same epochs, same folds, same seed; the only change is where CSP is fitted:
| Pipeline | Accuracy |
|---|---|
| Spatial filter refitted inside every training fold | 86.7 % |
| Spatial filter fitted once on every epoch, labels included | 97.8 % |
| The cost of the leak | +11.1 percentage points |
Across all twelve candidate subjects the same comparison inflates the median from 55.6 % to 96.7 %, a median inflation of +37.8 points, and every one of the twelve goes up. The claim rests on the sign being the same for every subject, not on any single number — with 45 epochs each, no one subject’s accuracy is precise.
The rule generalises well beyond CSP: anything that looks at labels belongs inside the fold. Spatial filtering, feature selection, channel or time-window choice, normalisation, hyper-parameter tuning, and the decision to exclude a subject. This is pf-decoding-leakage, and L6.5 is where it becomes an argument about inference rather than a pipeline rule.
xDAWN, and the family this belongs to
CSP separates classes by variance, which suits oscillatory contrasts such as motor imagery. It is the wrong tool for an evoked response, where the class difference lives in the phase-locked average rather than in band power.
xDAWN is the corresponding construction for ERPs: estimate spatial filters that maximise the ratio of evoked signal to total signal, so that the filtered channels emphasise the time-locked response. It is the standard front end for P300 spellers and the ERP counterpart of what CSP does for rhythms. TODO(confirm): xDAWN is named in §6’s concept list for this lesson but is not implemented in the widget and is not covered by an entry in this site’s reading list; its formulation must be attributed to a primary source before publication.
Both belong to one family — find a linear combination of sensors that optimises a class-related criterion — along with ICA (L2.6), the beamformer of L5.5, and the linear decoders of L7.1. Everything in this lesson about filters and patterns applies to all of them.
The data behind this lesson
ds-eegbci— EEG Motor Movement/Imagery Database (EEGMMIDB), PhysioNet v1.0.0, ODC-By 1.0, open access. BCI2000, 64-channel 10-10 cap, 160 Hz, 109 volunteers. The shipped asset is subject S002, runs R04, R08 and R12 (imagine opening and closing the left or the right fist), band 8–30 Hz, window 0.5 to 2.5 s after the cue, 45 epochs (23 left, 22 right), stratified 5-fold cross-validation with seed 20260918, MNE 1.10.2.- The candidate set excluded S038, S088, S089, S092, S100 and S104, which carry documented event-timestamp defects — an exclusion made on data-quality grounds before any accuracy was computed, which is the only kind of exclusion that does not need declaring as a researcher degree of freedom.
- Both weight matrices ship, filters and patterns, precisely because the lesson is about the difference. Each sidecar states which it holds and that only the patterns may be read as topographies.
- TODO(confirm): the lateralization direction of sensorimotor mu and beta desynchronization during hand motor imagery — which hemisphere for which hand — is not established anywhere on this site from a primary source, so no claim in this lesson depends on it. What the exercise below asks is whether a pattern is over sensorimotor cortex at all, which is a weaker and safer judgement.
Explore
What to look for
- Put the filter and the pattern for one component side by side and read the angle, not the colours. On component 4 it is 73.8° — these are not the same vector and not close to it.
- Go to component 2, where both maps peak at CP5. Then read the rank agreement across all sixty-four sensors: 0.21. This is the case that fools people, and the read-out is what catches it.
- Turn on “shape only”. Rescaling both maps to the same range removes the amplitude difference; if the two were one map at two scales, they would now coincide. They do not.
- Step through the components in eigenvalue order and watch
λ. The middle components sit near 0.5, which means they separate the classes hardly at all — however structured and convincing their maps look. - Switch to
pipelinemode and turn on “fit the spatial filter on all the trials”. The accuracy jumps 11 points with nothing about the decoder improved. That is one control, and it is the whole ofpf-decoding-leakage.
Practice
Spatial filters for decoding: CSP plus LDA on ds-eegbci motor imagery with cross-validation, filters against patterns, the component-count sweep, the eleven points a misplaced fold boundary buys, and the twelve-subject distribution the headline number came from nb-5-7-csp
Downloads from ds-eegbci.
The notebook fits CSP and LDA on ds-eegbci with cross-validation, reproduces the filter-versus-pattern comparison, sweeps the component count, and runs the honest and leaked variants side by side. Its subject survey is the part to read first: the shipped accuracy is one point in a distribution the notebook prints in full.
Exercises
Exercise ex-5-7-accuracy
NumericFor the shipped subject and pipeline — ds-eegbci S002, runs R04+R08+R12, 8–30 Hz, 0.5–2.5 s after the cue, 6 CSP components into LDA, stratified 5-fold, filters refitted inside every training fold — what is the cross-validated accuracy, as a percentage? (Before you write it down anywhere else: this subject was selected by accuracy from twelve candidates ranging 44.4 % to 95.6 % with a median of 55.6 %.)
Exercise ex-5-7-which-map
Multiple choiceYou want to make a statement about where a CSP component's activity appears on the scalp. Which map may you use, and why?
Exercise ex-5-7-component-count
Multiple choiceOn the shipped subject, log band power at C3 and C4 with no spatial filter scores 73.3 %; CSP with two components scores 51.1 %; CSP with four, six and eight components scores 86.7 %, 86.7 % and 88.9 %. What is the right reading?
Exercise ex-5-7-plausible-pattern
Multiple choiceFour CSP components from the left-versus-right hand motor imagery contrast, given as eigenvalue and pattern peak: (a) λ = 0.68, pattern peaks at CP3; (b) λ = 0.32, pattern peaks at O2; (c) λ = 0.25, pattern peaks at CP5; (d) λ = 0.26, pattern peaks at P6. Which one would you be willing to interpret physiologically, and what does that willingness rest on?
Pitfalls
Information leakage across CV folds
- Symptom
- Cross-validated accuracy collapses on a true held-out set.
- Cause
Cross-validation estimates performance on unseen data. The estimate is valid exactly to the extent that the held-out fold is unseen by the whole pipeline, not just by the classifier. Any step fitted on all the data before the split has already looked at the test fold, so the classifier is scored on data it has partly been fitted to.
- Detect
- Move the step inside the fold and re-run. The difference is the leak, measured in the units the paper reports. This is the only test that gives a number, and it takes minutes. - Permutation-test the entire pipeline. Shuffle the labels, re-run cross-validation, spatial filter and classifier together, a few hundred times. If the resulting null distribution is centred above chance, something in th…
- Fix
- Make the pipeline one object and fit it per fold. A Pipeline containing the spatial filter, the scaler and the classifier, passed to the cross-validator, leaks nothing by construction — the fix is structural rather than vigilant, which is what makes it reliable. - Nest the hyperparameter search. An inner cross-validation on the training folds chooses the parameters; the outer fold scores them.…
In other tools
In other toolsEEGLAB · FieldTrip — names only
The equivalents of what this lesson does, for a reader who works in another toolbox. Function names only: their own documentation is the place to learn how to call them.
EEGLAB
pop_cspCSP plugin (install separately)
FieldTrip
ft_componentanalysis(csp)FieldTrip
Names checked 2026-09-18 against EEGLAB 2026.0.0 (plugins at the versions in EEGLAB’s own plugin list) and FieldTrip 20251218.
Reading
- Blankertz et al. (2008). Optimizing spatial filters. unverified
- Haufe et al. (2014). Interpretation of weight vectors. unverified