Giving credit

Previous topic

8.3.8. Setting a parameter by cross-validation

Next topic

8.3.10. Example of pattern recognition on simulated data

8.3.9. ROI-based decoding analysis in Haxby et al. datasetΒΆ

In this script we reproduce the data analysis conducted by Haxby et al. in “Distributed and Overlapping Representations of Faces and Objects in Ventral Temporal Cortex”.

Specifically, we look at decoding accuracy for different objects in three different masks: the full ventral stream (mask_vt), the house selective areas (mask_house) and the face selective areas (mask_face), that have been defined via a standard GLM-based analysis.

First we load and prepare the data

# Fetch data using nilearn dataset fetcher
from nilearn import datasets
# by default we fetch 2nd subject data for analysis
haxby_dataset = datasets.fetch_haxby()
func_filename = haxby_dataset.func[0]

# Print basic information on the dataset
print('First subject anatomical nifti image (3D) located is at: %s' %
      haxby_dataset.anat[0])
print('First subject functional nifti image (4D) is located at: %s' %
      func_filename)

# Load nilearn NiftiMasker, the practical masking and unmasking tool
from nilearn.input_data import NiftiMasker

# load labels
import numpy as np
labels = np.recfromcsv(haxby_dataset.session_target[0], delimiter=" ")
stimuli = labels['labels']

# identify resting state labels in order to be able to remove them
resting_state = stimuli == b"rest"

# find names of remaining active labels
categories = np.unique(stimuli[np.logical_not(resting_state)])

# extract tags indicating to which acquisition run a tag belongs
session_labels = labels["chunks"][np.logical_not(resting_state)]

Out:

First subject anatomical nifti image (3D) located is at: /home/parietal/gvaroqua/nilearn_data/haxby2001/subj2/anat.nii.gz
First subject functional nifti image (4D) is located at: /home/parietal/gvaroqua/nilearn_data/haxby2001/subj2/bold.nii.gz

Then we use scikit-learn for decoding on the different masks

# The classifier: a support vector classifier
from sklearn.svm import SVC
classifier = SVC(C=1., kernel="linear")

# A classifier to set the chance level
from sklearn.dummy import DummyClassifier
dummy_classifier = DummyClassifier()

# Make a data splitting object for cross validation
from sklearn.cross_validation import LeaveOneLabelOut, cross_val_score
cv = LeaveOneLabelOut(session_labels)

mask_names = ['mask_vt', 'mask_face', 'mask_house']

mask_scores = {}
mask_chance_scores = {}

for mask_name in mask_names:
    print("Working on mask %s" % mask_name)
    # For decoding, standardizing is often very important
    mask_filename = haxby_dataset[mask_name][0]
    masker = NiftiMasker(mask_img=mask_filename, standardize=True)
    masked_timecourses = masker.fit_transform(
        func_filename)[np.logical_not(resting_state)]

    mask_scores[mask_name] = {}
    mask_chance_scores[mask_name] = {}

    for category in categories:
        print("Processing %s %s" % (mask_name, category))
        task_mask = np.logical_not(resting_state)
        classification_target = (stimuli[task_mask] == category)
        mask_scores[mask_name][category] = cross_val_score(
            classifier,
            masked_timecourses,
            classification_target,
            cv=cv, scoring="f1")

        mask_chance_scores[mask_name][category] = cross_val_score(
            dummy_classifier,
            masked_timecourses,
            classification_target,
            cv=cv, scoring="f1")

        print("Scores: %1.2f +- %1.2f" % (
            mask_scores[mask_name][category].mean(),
            mask_scores[mask_name][category].std()))

Out:

Working on mask mask_vt
Processing mask_vt bottle
Scores: 0.53 +- 0.21
Processing mask_vt cat
Scores: 0.60 +- 0.25
Processing mask_vt chair
Scores: 0.42 +- 0.25
Processing mask_vt face
Scores: 0.58 +- 0.24
Processing mask_vt house
Scores: 0.81 +- 0.28
Processing mask_vt scissors
Scores: 0.41 +- 0.31
Processing mask_vt scrambledpix
Scores: 0.79 +- 0.17
Processing mask_vt shoe
Scores: 0.56 +- 0.23
Working on mask mask_face
Processing mask_face bottle
Scores: 0.00 +- 0.00
Processing mask_face cat
Scores: 0.00 +- 0.00
Processing mask_face chair
Scores: 0.00 +- 0.00
Processing mask_face face
Scores: 0.44 +- 0.23
Processing mask_face house
Scores: 0.00 +- 0.00
Processing mask_face scissors
Scores: 0.00 +- 0.00
Processing mask_face scrambledpix
Scores: 0.40 +- 0.30
Processing mask_face shoe
Scores: 0.00 +- 0.00
Working on mask mask_house
Processing mask_house bottle
Scores: 0.37 +- 0.21
Processing mask_house cat
Scores: 0.32 +- 0.22
Processing mask_house chair
Scores: 0.44 +- 0.16
Processing mask_house face
Scores: 0.40 +- 0.24
Processing mask_house house
Scores: 0.76 +- 0.23
Processing mask_house scissors
Scores: 0.38 +- 0.17
Processing mask_house scrambledpix
Scores: 0.54 +- 0.22
Processing mask_house shoe
Scores: 0.29 +- 0.22

We make a simple bar plot to summarize the results

import matplotlib.pyplot as plt
plt.figure()

tick_position = np.arange(len(categories))
plt.xticks(tick_position, categories, rotation=45)

for color, mask_name in zip('rgb', mask_names):
    score_means = [mask_scores[mask_name][category].mean()
                   for category in categories]
    plt.bar(tick_position, score_means, label=mask_name,
            width=.25, color=color)

    score_chance = [mask_chance_scores[mask_name][category].mean()
                    for category in categories]
    plt.bar(tick_position, score_chance,
            width=.25, edgecolor='k', facecolor='none')

    tick_position = tick_position + .2

plt.ylabel('Classification accurancy (f1 score)')
plt.xlabel('Visual stimuli category')
plt.legend(loc='best')
plt.title('Category-specific classification accuracy for different masks')
plt.tight_layout()


plt.show()
../../_images/sphx_glr_plot_haxby_full_analysis_001.png

Total running time of the script: ( 1 minutes 57.483 seconds)

Generated by Sphinx-Gallery