<jupyter_start><jupyter_text>MVPA/decoding Can we predict trial type from EEG activity?<jupyter_code>from sklearn.svm import LinearSVC
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import make_pipeline
from sklearn.model_selection import cross_val_score
epochs.pick_types(eeg=True)
X = epochs.get_data()  # features
y = epochs.events[:, -1] == event_ids["target/stimulus"]  # targets
X.shape, y.shape
y[:9]<jupyter_output><empty_output><jupyter_text>X has the wrong shape - `samples`, `channels`, `times`, should be `samples`, `features`.We can use `mne.decoding.Vectorizer` to correctly shape the data. It fits right into a scikit-learn pipeline.<jupyter_code>from mne.decoding import Vectorizer
clf = make_pipeline(Vectorizer(), StandardScaler(),
                    LinearSVC(class_weight="balanced")
                   )<jupyter_output><empty_output><jupyter_text>The resulting object behaves exactly as any other scikit-learn classifier:<jupyter_code>clf.fit(X, y)
clf.predict(X[:9])<jupyter_output><empty_output><jupyter_text>Of course, usually we care about cross-validated scores.<jupyter_code>cross_val_score(clf, X, y)  # accuracy<jupyter_output><empty_output><jupyter_text>So there is some decodable information in the brain data. Can we investigate this in a bit more detail?For example: at which time points in the trial is there information about trial category?We need two more tools for this: one to train and score at each time point, and one to handle the cross-validated scoring for the former.<jupyter_code>from mne.decoding import SlidingEstimator, cross_val_multiscore
sl = SlidingEstimator(clf)
scores_time_decoding = cross_val_multiscore(sl, X, y)
scores_time_decoding.shape
fig, ax = plt.subplots()
ax.plot(epochs.times, scores_time_decoding.T)
plt.show()
fig, ax = plt.subplots()
ax.plot(epochs.times, scores_time_decoding.mean(0))
plt.show()<jupyter_output><empty_output><jupyter_text>But is the same thing happening at each time point? We can investigate that with generalization across time decoding.<jupyter_code>from mne.decoding import GeneralizingEstimator
gen = GeneralizingEstimator(clf)
scores_gat = cross_val_multiscore(gen, X, y)
scores_gat.shape
import numpy as np
data = scores_gat.mean(0)
vmax = np.abs(data).max()
tmin, tmax = epochs.times[[0, -1]]

fig, ax = plt.subplots()
im = ax.imshow(
    data,
    origin="lower", cmap="RdBu_r",
    extent=(tmin, tmax, tmin, tmax),
    vmax=vmax, vmin=1-vmax);

plt.colorbar(im)<jupyter_output><empty_output><jupyter_text>We can easily attempt more complex decoding pipelines.<jupyter_code>from mne.decoding import UnsupervisedSpatialFilter
from sklearn.decomposition import PCA
pca = UnsupervisedSpatialFilter(PCA(.85))
pca_clf = make_pipeline(pca, Vectorizer(), StandardScaler(), LinearSVC())
cross_val_score(pca_clf, X, y)<jupyter_output><empty_output><jupyter_text>What do the learned patterns actually look like?<jupyter_code>svc = LinearSVC(class_weight="balanced")
topos = np.array([svc.fit(time_point.T, y).coef_ * time_point.std(1)
                  for time_point in X.T])[:, 0, :]
topo_ev = mne.EvokedArray(topos.T, info=epochs.info, tmin=-.2, nave=len(y))
topo_ev.plot_joint(times=[.22, .3, .375, .45]);<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.11035966799877037, 'fraction_numerical': 0.00645557946510913, 'mean_word_length': 6.199115044247788, 'pattern_counts': {'":': 0, '<': 33, '<?xml version=': 0, '>': 33, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '8', 'dir': 'jupyter-structured-clean-dedup', 'id': '615737', 'license': 'BSD-3-Clause', 'n_tokens_mistral': 1161, 'n_tokens_neox': 1124, 'n_words': 276, 'path': '2018_06_Amsterdam/mne_notebook_3_mvpa.ipynb', 'repo_name': 'mne-tools/mne-workshops', 'size': '3253'}