Voxel-Based Morphometry with Space-Net prior

Predicting age from gray-matter concentration maps from OASIS dataset. Note that age is a continuous variable, we use the regressor here, and not the classification object.

dataset

This example uses the OASIS VBM dataset.

Load the Oasis VBM dataset

import numpy as np

from nilearn import datasets

n_subjects = 200
dataset_files = datasets.fetch_oasis_vbm(n_subjects=n_subjects)
age = dataset_files.ext_vars["age"].astype(float)
age = np.array(age)
gm_imgs = np.array(dataset_files.gray_matter_maps)


# Split data into training set and test set
from sklearn.model_selection import train_test_split
from sklearn.utils import check_random_state

rng = check_random_state(42)
gm_imgs_train, gm_imgs_test, age_train, age_test = train_test_split(
    gm_imgs, age, train_size=0.6, random_state=rng
)

# Sort test data for better visualization (trend, etc.)
perm = np.argsort(age_test)[::-1]
age_test = age_test[perm]
gm_imgs_test = gm_imgs_test[perm]
[fetch_oasis_vbm] Dataset directory found: /home/runner/work/nilearn/nilearn/nilearn_data/oasis_vbm

Fit the SpaceNet and predict with it

To save time (because these are anat images with many voxels), we include only the 5-percent voxels most correlated with the age variable to fit. Also, we set memory_level=2 so that more of the intermediate computations are cached. We used a graph-net penalty here but more beautiful results can be obtained using the TV-l1 penalty, at the expense of longer runtimes. Also, you may pass and n_jobs=<some_high_value> to the SpaceNetRegressor class, to take advantage of a multi-core system.

from nilearn.decoding import SpaceNetRegressor

decoder = SpaceNetRegressor(
    memory="nilearn_cache",
    penalty="graph-net",
    screening_percentile=5.0,
    memory_level=2,
    n_jobs=2,
    verbose=1,
)
decoder.fit(gm_imgs_train, age_train)  # fit
coef_img = decoder.coef_img_
y_pred = decoder.predict(gm_imgs_test).ravel()  # predict
mse = np.mean(np.abs(age_test - y_pred))
print(f"Mean square error (MSE) on the predicted age: {mse:.2f}")
/home/runner/work/nilearn/nilearn/examples/02_decoding/plot_oasis_vbm_space_net.py:68: MaskWarning:

Brain mask (7221031.999999998 mm^3) is bigger than the standard human brain (1882989.0 mm^3).This object is probably not tuned to be used on such data.

[SpaceNetRegressor.fit] Mask volume = 7.22103e+06mm^3 = 7221.03cm^3
[SpaceNetRegressor.fit] Standard brain volume = 1.88299e+06mm^3
[SpaceNetRegressor.fit] Original screening-percentile: 5
[SpaceNetRegressor.fit] Corrected screening-percentile: 1.30382
[SpaceNetRegressor.fit] Time Elapsed: 00 HR 02 MIN 04 SEC seconds.
/home/runner/work/nilearn/nilearn/.tox/doc/lib/python3.11/site-packages/joblib/memory.py:607: JobLibCollisionWarning:

Cannot detect name collisions for function 'nifti_masker_extractor'

Mean square error (MSE) on the predicted age: 12.39

Visualize the decoding maps and quality of predictions

import matplotlib.pyplot as plt

from nilearn.plotting import plot_stat_map, show

# weights map
background_img = gm_imgs[0]
plot_stat_map(
    coef_img,
    background_img,
    title="graph-net weights",
    display_mode="z",
    cut_coords=1,
)

# Plot the prediction errors.
plt.figure()
plt.suptitle(f"graph-net: Mean Absolute Error {mse:.2f} years")
linewidth = 3
ax1 = plt.subplot(211)
ax1.plot(age_test, label="True age", linewidth=linewidth)
ax1.plot(y_pred, "--", c="g", label="Predicted age", linewidth=linewidth)
ax1.set_ylabel("age")
plt.legend(loc="best")
ax2 = plt.subplot(212)
ax2.plot(
    age_test - y_pred, label="True age - predicted age", linewidth=linewidth
)
ax2.set_xlabel("subject")
plt.legend(loc="best")

show()
  • plot oasis vbm space net
  • graph-net: Mean Absolute Error 12.39 years

Total running time of the script: (2 minutes 10.930 seconds)

Estimated memory usage: 2734 MB

Gallery generated by Sphinx-Gallery