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)))