You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
"\n# Time-Resolved Decoding with SlidingEstimator\n\nThis example shows how to perform time-resolved decoding of EEG signals using\n:class:`mne.decoding.SlidingEstimator`. Instead of reducing the entire trial to\na single score, a SlidingEstimator fits an independent classifier at each time\npoint, revealing *when* during a trial the neural signal carries information\nabout the mental state.\n\nThis approach is a natural alternative to pseudo-online evaluation (using\noverlapping windows): rather than simulating an online scenario by slicing\nthe raw signal with a sliding window, we directly assess decoding accuracy\nat each sample of the already-epoched trial.\n\nWe use the BNCI2014-001 motor-imagery dataset (left- vs right-hand) and apply\na logistic-regression classifier wrapped in a SlidingEstimator. For each\nsubject the score is evaluated via stratified 5-fold cross-validation using\n:func:`mne.decoding.cross_val_multiscore`, and the results are averaged across\nsubjects and visualised as a time course.\n"
"## Loading the Dataset\n\nWe instantiate the BNCI2014-001 dataset and restrict the analysis to the\nfirst 9 subjects to keep the example reasonably fast.\n\n"
"## Choosing a Paradigm\n\nThe :class:`~moabb.paradigms.LeftRightImagery` paradigm extracts\nleft-hand and right-hand motor-imagery epochs, applies a band-pass filter\n(8\u201332 Hz by default), and returns the data as a 3-D NumPy array of shape\n``(n_trials, n_channels, n_times)``.\n\n"
44
+
]
45
+
},
46
+
{
47
+
"cell_type": "code",
48
+
"execution_count": null,
49
+
"metadata": {
50
+
"collapsed": false
51
+
},
52
+
"outputs": [],
53
+
"source": [
54
+
"paradigm = LeftRightImagery()"
55
+
]
56
+
},
57
+
{
58
+
"cell_type": "markdown",
59
+
"metadata": {},
60
+
"source": [
61
+
"## Building a Time-Resolved Pipeline\n\nA :class:`~mne.decoding.SlidingEstimator` wraps any scikit-learn compatible\nestimator and fits/scores it independently at every time point.\nHere we use a simple logistic-regression classifier with Z-score\nnormalisation. The ``scoring='roc_auc'`` argument tells the estimator to\nuse AUC as the evaluation metric.\n\n"
"## Evaluating Each Subject\n\nFor each subject we:\n\n1. Retrieve the preprocessed epochs via the paradigm.\n2. Run stratified 5-fold cross-validation with\n :func:`~mne.decoding.cross_val_multiscore`, which returns an array of\n shape ``(n_folds, n_times)``.\n3. Average over folds to obtain a single time course per subject.\n\nAll per-subject time courses are collected for later aggregation.\n\n"
80
+
]
81
+
},
82
+
{
83
+
"cell_type": "code",
84
+
"execution_count": null,
85
+
"metadata": {
86
+
"collapsed": false
87
+
},
88
+
"outputs": [],
89
+
"source": [
90
+
"all_scores = []\n\nfor subject in dataset.subject_list:\n X, y, meta = paradigm.get_data(dataset=dataset, subjects=[subject])\n\n # cross_val_multiscore returns (n_folds, n_times)\n scores = cross_val_multiscore(sliding, X, y, cv=5, n_jobs=1)\n all_scores.append(scores.mean(axis=0)) # average over folds\n\n# Stack into (n_subjects, n_times)\nall_scores = np.array(all_scores)"
91
+
]
92
+
},
93
+
{
94
+
"cell_type": "markdown",
95
+
"metadata": {},
96
+
"source": [
97
+
"## Building the Time Vector\n\nThe time axis of the decoded epochs starts at ``tmin`` (0 s relative to the\nmotor-imagery cue) and ends at the trial duration defined by the dataset\n(4 s for BNCI2014-001 at 250 Hz).\n\n"
"## Plotting Time-Resolved Decoding Accuracy\n\nWe plot the group-average AUC score together with the standard error of the\nmean (SEM) across subjects. A horizontal dashed line at 0.5 indicates\nchance level.\n\n"
116
+
]
117
+
},
118
+
{
119
+
"cell_type": "code",
120
+
"execution_count": null,
121
+
"metadata": {
122
+
"collapsed": false
123
+
},
124
+
"outputs": [],
125
+
"source": [
126
+
"mean_scores = all_scores.mean(axis=0)\nsem_scores = all_scores.std(axis=0) / np.sqrt(len(dataset.subject_list))\n\nfig, ax = plt.subplots(figsize=(8, 4))\nax.plot(times, mean_scores, label=\"Mean AUC across subjects\", color=\"steelblue\")\nax.fill_between(\n times,\n mean_scores - sem_scores,\n mean_scores + sem_scores,\n alpha=0.3,\n color=\"steelblue\",\n label=\"\u00b1SEM\",\n)\nax.axhline(0.5, linestyle=\"--\", color=\"k\", label=\"Chance level (AUC = 0.5)\")\nax.axvline(0, linestyle=\":\", color=\"gray\", label=\"Cue onset\")\nax.set_xlabel(\"Time (s)\")\nax.set_ylabel(\"AUC\")\nax.set_title(\"Time-Resolved Decoding \u2013 Left vs. Right Motor Imagery\\n(BNCI2014-001)\")\nax.legend(loc=\"upper left\")\nax.set_xlim(times[0], times[-1])\nax.set_ylim(0.4, 1.0)\nplt.tight_layout()\nplt.show()"
0 commit comments