Import some libraries that we will need


In [ ]:
%matplotlib inline
import scipy.io
from scipy.stats import stats
from sklearn.metrics import confusion_matrix
from sklearn.svm import NuSVC
import numpy as np

Run SRM with the movie data


In [ ]:
import brainiak.funcalign.srm
help(brainiak.funcalign.srm.SRM)

Load the input data that contains the movie stimuli for unsupervised training with SRM


In [ ]:
movie_file = scipy.io.loadmat('data/movie_data.mat')

Convert data to a list of arrays matching SRM input. Each element is a matrix of voxels by TRs. Also, concatenate data from both hemispheres in the brain.


In [ ]:
movie_data_left = movie_file['movie_data_lh']
movie_data_right = movie_file['movie_data_rh']
subjects = movie_data_left.shape[2]
movie_data = []
for s in range(subjects):
    movie_data.append(np.concatenate([movie_data_left[:, :, s], movie_data_right[:, :, s]], axis=0))

Z-score the data


In [ ]:
for subject in range(subjects):
    movie_data[subject] = stats.zscore(movie_data[subject],axis=1,ddof=1)

Run SRM


In [ ]:
srm = brainiak.funcalign.srm.SRM(n_iter=10, features=50)
srm.fit(movie_data)

Load the input data that contains the image stimuli and its labels for training a classifier


In [ ]:
image_file = scipy.io.loadmat('data/image_data.mat')
image_data_left = image_file['image_data_lh']
image_data_right = image_file['image_data_rh']

Convert data to a list of arrays matching SRM input. Each element is a matrix of voxels by TRs. Also, concatenate data from both hemispheres in the brain.


In [ ]:
image_data = []
for s in range(subjects):
    image_data.append(np.concatenate([image_data_left[:, :, s], image_data_right[:, :, s]], axis=0))

Z-score the image data


In [ ]:
for subject in range(subjects):
    image_data[subject] = stats.zscore(image_data[subject],axis=1,ddof=1)

Z-score the Shared Response data


In [ ]:
image_data_shared = srm.transform(image_data)
for subject in range(subjects):
    image_data_shared[subject] = stats.zscore(image_data_shared[subject], axis=1, ddof=1)

Read the labels of the image data


In [ ]:
labels = scipy.io.loadmat('data/label.mat')
labels = np.squeeze(labels['label'])

Run a leave-one-out cross validation with the subjects. We use a $\nu$-SVM classifier.


In [ ]:
train_labels = np.tile(labels, subjects-1)
test_labels = labels
accuracy = np.zeros((subjects))
cm = [None] * subjects
for subject in range(subjects):
    # Concatenate the subjects' data for training into one matrix
    train_subjects = list(range(subjects))
    train_subjects.remove(subject)
    TRs = image_data_shared[0].shape[1]
    train_data = np.zeros((image_data_shared[0].shape[0], len(train_labels)))
    for train_subject in range(len(train_subjects)):
        start_index = train_subject*TRs
        end_index = start_index+TRs
        train_data[:, start_index:end_index] = image_data_shared[train_subjects[train_subject]]

    # Train a Nu-SVM classifier using scikit learn
    classifier = NuSVC(nu=0.5, kernel='linear', gamma='auto')
    classifier = classifier.fit(train_data.T, train_labels)

    # Predict on the test data
    predicted_labels = classifier.predict(image_data_shared[subject].T)
    accuracy[subject] = sum(predicted_labels == test_labels)/float(len(predicted_labels))

    # Create a confusion matrix to see the accuracy of each class
    cm[subject] = confusion_matrix(test_labels, predicted_labels)

    # Normalize the confusion matrix
    cm[subject] = cm[subject].astype('float') / cm[subject].sum(axis=1)[:, np.newaxis]

Define a function that presents the output of the experiment in a plot


In [ ]:
def plot_confusion_matrix(cm, title="Confusion Matrix"):
    """Plots a confusion matrix for each subject"""
    import matplotlib.pyplot as plt
    import math
    plt.figure()
    subjects = len(cm)
    root_subjects = math.sqrt(subjects)
    cols = math.ceil(root_subjects)
    rows = math.ceil(subjects/cols)
    classes = cm[0].shape[0]
    for subject in range(subjects):
        plt.subplot(rows, cols, subject+1)
        plt.imshow(cm[subject], interpolation='nearest', cmap=plt.cm.bone)
        plt.xticks(np.arange(classes), range(1,classes+1))
        plt.yticks(np.arange(classes), range(1,classes+1))
        cbar = plt.colorbar(ticks=[0.0,1.0], shrink=0.6)
        cbar.set_clim(0.0, 1.0)
        plt.xlabel("Predicted")
        plt.ylabel("True label")
        plt.title("{0:d}".format(subject + 1))
    plt.suptitle(title)
    plt.tight_layout()
    plt.show()

Plot the confusion matrices and print the accuracy results


In [ ]:
plot_confusion_matrix(cm, title="Confusion matrices for different test subjects")
print("The average accuracy among all subjects is {0:f} +/- {1:f}".format(np.mean(accuracy), np.std(accuracy)))

Now we repeat the experiment with the Deterministic SRM


In [ ]:
srm = brainiak.funcalign.srm.DetSRM(n_iter=10, features=50)
srm.fit(movie_data)

Transform the image stimuli data


In [ ]:
image_data_shared = srm.transform(image_data)
for subject in range(subjects):
    image_data_shared[subject] = stats.zscore(image_data_shared[subject], axis=1, ddof=1)

Run a leave-one-out cross validation with the subjects


In [ ]:
accuracy = np.zeros((subjects,))
cm = [None] * subjects
for subject in range(subjects):
    # Concatenate the subjects' data for training into one matrix
    train_subjects = list(range(subjects))
    train_subjects.remove(subject)
    TRs = image_data_shared[0].shape[1]
    train_data = np.zeros((image_data_shared[0].shape[0], len(train_labels)))
    for train_subject in range(len(train_subjects)):
        start_index = train_subject*TRs
        end_index = start_index+TRs
        train_data[:, start_index:end_index] = image_data_shared[train_subjects[train_subject]]

    # Train a Nu-SVM classifier using scikit learn
    classifier = NuSVC(nu=0.5, kernel='linear', gamma='auto')
    classifier = classifier.fit(train_data.T, train_labels)

    # Predict on the test data
    predicted_labels = classifier.predict(image_data_shared[subject].T)
    accuracy[subject] = sum(predicted_labels == test_labels)/float(len(predicted_labels))

    # Create a confusion matrix to see the accuracy of each class
    cm[subject] = confusion_matrix(test_labels, predicted_labels)

    # Normalize the confusion matrix
    cm[subject] = cm[subject].astype('float') / cm[subject].sum(axis=1)[:, np.newaxis]

Plot and print the results


In [ ]:
plot_confusion_matrix(cm, title="Confusion matrices for different test subjects with Deterministic SRM")
print("Det. SRM: The average accuracy among all subjects is {0:f} +/- {1:f}".format(np.mean(accuracy), np.std(accuracy)))