The encoding function predicts the BOLD response
The encoding function predicts the BOLD response as the dot product of the PRF and stimulus drive
where
Encoding models, like the visuospatial PRF model lend themselve extremely well for fitting usin computational graphs/GPUs.
7T data consists of ~ 300,000 voxels
Every time series ~250 time points
Simplest PRF model has 5 parameters
~ 400 million variables
Without GPUs I couldn't do the research I do the way I do it.
Implement a simple visuospatial PRF model using Tensorflow/Jax/Pytorch.
notebooks/3_implement_prf.ipynb
Do not use for loops in plain Python
predictions = []
for i in S.shape[0]: # loop over time
pred = (S[i] * prf).sum(axis=[1, 2])
Use matrices (which can be heavily optimized, potentially on GPU):
predictions = (S * prf).sum(axis=[1, 2])
Use comments to remember which dimension is which
prf = get_prf(...) # (n_prfs, n_x_coordinates, n_y_coordinates)
# Inputs:
# S: (n_timepoints, n_x, n_y) = (238, 30, 30)
# prf: (n_prfs, n_x, n_y) = (1000, 30, 30)
# Reshape for broadcasting:
S_expanded = S[:, tf.newaxis, :, :] # Shape: (238, 1, 30, 30)
prf_expanded = prf[tf.newaxis, :, :, :] # Shape: (1, 1000, 30, 30)
# Vectorized operation (e.g., element-wise multiply):
output = (S_expanded * prf_expanded).sum(axis=[2,3]) # Shape: (238, 1000)
Memory savings: 214M (
Key Idea
repmat
: Use tf.newaxis
to add singleton dimensions.S_expanded
and prf_expanded
align via broadcasting rules.Select one voxel to prototype
good_voxels = [82, 229, 538]
voxel_ts = v1_ts[82] # maybe do not do this
voxel_ts.shape
(258,)
voxel_ts = v1_ts[[82]] # do this
voxel_ts.shape
(258, 1)
Plot, plot, plot
good_voxels = [82, 229, 538]
v1_ts[good_voxels].plot()
sns.despine()