Voxel-Based Morphometry on Oasis dataset 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.

See also

The documentation: SpaceNet: decoding with spatial structure for better maps.

For more information see the dataset description.

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 found in /home/runner/nilearn_data/oasis1

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/.tox/doc/lib/python3.10/site-packages/nilearn/maskers/base_masker.py:135: UserWarning:

Persisting input arguments took 1.29s to run.
If this happens often in your code, it can cause performance problems
(results will be correct in all cases).
The reason for this is probably some large input arguments for a wrapped
 function (e.g. large strings).
THIS IS A JOBLIB ISSUE. If you can, kindly provide the joblib's team with an
 example so that they can fix the problem.

/home/runner/work/nilearn/nilearn/.tox/doc/lib/python3.10/site-packages/nilearn/maskers/base_masker.py:152: UserWarning:

Persisting input arguments took 0.65s to run.
If this happens often in your code, it can cause performance problems
(results will be correct in all cases).
The reason for this is probably some large input arguments for a wrapped
 function (e.g. large strings).
THIS IS A JOBLIB ISSUE. If you can, kindly provide the joblib's team with an
 example so that they can fix the problem.

/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
/home/runner/work/nilearn/nilearn/.tox/doc/lib/python3.10/site-packages/joblib/externals/loky/process_executor.py:700: UserWarning:

A worker stopped while some jobs were given to the executor. This can be caused by a too short worker timeout or by a memory leak.

\[SpaceNetRegressor.fit] Time Elapsed: 111.915 seconds.
/home/runner/work/nilearn/nilearn/.tox/doc/lib/python3.10/site-packages/nilearn/maskers/base_masker.py:135: JobLibCollisionWarning:

Cannot detect name collisions for function 'nifti_masker_extractor'

/home/runner/work/nilearn/nilearn/.tox/doc/lib/python3.10/site-packages/nilearn/maskers/base_masker.py:135: UserWarning:

Persisting input arguments took 0.86s to run.
If this happens often in your code, it can cause performance problems
(results will be correct in all cases).
The reason for this is probably some large input arguments for a wrapped
 function (e.g. large strings).
THIS IS A JOBLIB ISSUE. If you can, kindly provide the joblib's team with an
 example so that they can fix the problem.

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: (1 minutes 59.959 seconds)

Estimated memory usage: 2525 MB

Gallery generated by Sphinx-Gallery