{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "\n\n# Decoding (MVPA)\n\n.. include:: ../../links.inc\n\n## Design philosophy\nDecoding (a.k.a. MVPA) in MNE largely follows the machine learning API of the\nscikit-learn package.\nEach estimator implements ``fit``, ``transform``, ``fit_transform``, and\n(optionally) ``inverse_transform`` methods. For more details on this design,\nvisit scikit-learn_. For additional theoretical insights into the decoding\nframework in MNE :footcite:`KingEtAl2018`.\n\nFor ease of comprehension, we will denote instantiations of the class using\nthe same name as the class but in small caps instead of camel cases.\n\nLet's start by loading data for a simple two-class problem:\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "import matplotlib.pyplot as plt\nimport numpy as np\nfrom sklearn.linear_model import LogisticRegression\nfrom sklearn.pipeline import make_pipeline\nfrom sklearn.preprocessing import StandardScaler\n\nimport mne\nfrom mne.datasets import sample\nfrom mne.decoding import (\n CSP,\n GeneralizingEstimator,\n LinearModel,\n Scaler,\n SlidingEstimator,\n Vectorizer,\n cross_val_multiscore,\n get_coef,\n)\n\ndata_path = sample.data_path()\n\nsubjects_dir = data_path / \"subjects\"\nmeg_path = data_path / \"MEG\" / \"sample\"\nraw_fname = meg_path / \"sample_audvis_filt-0-40_raw.fif\"\ntmin, tmax = -0.200, 0.500\nevent_id = {\"Auditory/Left\": 1, \"Visual/Left\": 3} # just use two\nraw = mne.io.read_raw_fif(raw_fname)\nraw.pick(picks=[\"grad\", \"stim\", \"eog\"])\n\n# The subsequent decoding analyses only capture evoked responses, so we can\n# low-pass the MEG data. Usually a value more like 40 Hz would be used,\n# but here low-pass at 20 so we can more heavily decimate, and allow\n# the example to run faster. The 2 Hz high-pass helps improve CSP.\nraw.load_data().filter(2, 20)\nevents = mne.find_events(raw, \"STI 014\")\n\n# Set up bad channels (modify to your needs)\nraw.info[\"bads\"] += [\"MEG 2443\"] # bads + 2 more\n\n# Read epochs\nepochs = mne.Epochs(\n raw,\n events,\n event_id,\n tmin,\n tmax,\n proj=True,\n picks=(\"grad\", \"eog\"),\n baseline=(None, 0.0),\n preload=True,\n reject=dict(grad=4000e-13, eog=150e-6),\n decim=3,\n verbose=\"error\",\n)\nepochs.pick(picks=\"meg\", exclude=\"bads\") # remove stim and EOG\ndel raw\n\nX = epochs.get_data(copy=False) # MEG signals: n_epochs, n_meg_channels, n_times\ny = epochs.events[:, 2] # target: auditory left vs visual left" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Transformation classes\n\n### Scaler\nThe :class:`mne.decoding.Scaler` will standardize the data based on channel\nscales. In the simplest modes ``scalings=None`` or ``scalings=dict(...)``,\neach data channel type (e.g., mag, grad, eeg) is treated separately and\nscaled by a constant. This is the approach used by e.g.,\n:func:`mne.compute_covariance` to standardize channel scales.\n\nIf ``scalings='mean'`` or ``scalings='median'``, each channel is scaled using\nempirical measures. Each channel is scaled independently by the mean and\nstandand deviation, or median and interquartile range, respectively, across\nall epochs and time points during :class:`~mne.decoding.Scaler.fit`\n(during training). The :meth:`~mne.decoding.Scaler.transform` method is\ncalled to transform data (training or test set) by scaling all time points\nand epochs on a channel-by-channel basis. To perform both the ``fit`` and\n``transform`` operations in a single call, the\n:meth:`~mne.decoding.Scaler.fit_transform` method may be used. To invert the\ntransform, :meth:`~mne.decoding.Scaler.inverse_transform` can be used. For\n``scalings='median'``, scikit-learn_ version 0.17+ is required.\n\n
Using this class is different from directly applying\n :class:`sklearn.preprocessing.StandardScaler` or\n :class:`sklearn.preprocessing.RobustScaler` offered by\n scikit-learn_. These scale each *classification feature*, e.g.\n each time point for each channel, with mean and standard\n deviation computed across epochs, whereas\n :class:`mne.decoding.Scaler` scales each *channel* using mean and\n standard deviation computed across all of its time points\n and epochs.
The winning entry of the Grasp-and-lift EEG competition in Kaggle used\n the :class:`~mne.decoding.CSP` implementation in MNE and was featured as\n a [script of the week](sotw_).