Repository navigation
Robust Shared Response Model - #302
Conversation
|
@CameronTEllis and @hejiaz, please do you mind reviewing this PR? Thank you and happy thanksgiving! |
CameronTEllis
left a comment
There was a problem hiding this comment.
Overall it is looking good, my comments are relatively minor and mainly just focused on fleshing details out
| """Robust Shared Response Model (RSRM) | ||
|
|
||
| The implementation is based on the following publications: | ||
|
|
There was a problem hiding this comment.
It would be good to provide a paragraph explaining what RSRM offers and how it compares to SRM, SSRM etc. You could copy and paste one of the paragraphs from manuscript. Also should mention the influence of RPCA
There was a problem hiding this comment.
I added an extended description of the method. However, I don't think that the relation to RPCA is relevant to the code/implementation. The idea is that people can understand the code and relate to the paper if there is something unclear.
|
|
||
| gamma : float, default: 1.0 | ||
| Regularization parameter for the sparseness of the individual | ||
| components. |
There was a problem hiding this comment.
Would be good to add direction to this description (Is high more or less sparse?)
| The shared response. | ||
|
|
||
| s_ : list of array, element i has shape=[voxels_i, samples] | ||
| The individual components with outlying data for each subject. |
There was a problem hiding this comment.
You use outlier here and elsewhere but sometimes refer to this as the individual component. It is important to be consistent so check that the same word is used everywehere
| ---- | ||
|
|
||
| The number of voxels may be different between subjects. However, the | ||
| number of samples for the alignment data must be the same across |
There was a problem hiding this comment.
'samples' is not a typical way of describing timepoints in fMRI data. Consider changing this to say that 'timepoints must be aligned across participants'
| X : list of 2D arrays, element i has shape=[voxels_i, samples] | ||
| Each element in the list contains the fMRI data of one subject. | ||
|
|
||
| y : not used |
There was a problem hiding this comment.
What is this for then?
| Parameters | ||
| ---------- | ||
|
|
||
| X : array, shape=[voxels, samples] |
There was a problem hiding this comment.
Maybe use a different letter, or lower case since this is no longer a list like it is in other functions. same with S below
| """ | ||
| A = X.dot(R.T) | ||
| A -= S.dot(R.T) | ||
| U, _, V = np.linalg.svd(A, full_matrices=False) |
There was a problem hiding this comment.
This is probably obvious but I am unsure why you are doing the SVD. A comment would help
| " \n", | ||
| "S = [None] * subjects\n", | ||
| "for s in range(subjects):\n", | ||
| " S[s] = (np.random.rand(data[s].shape[0], samples) < p) * ((np.random.rand(data[s].shape[0], samples) * amplitude - amplitude/2) )\n", |
There was a problem hiding this comment.
Why use uniform noise? I would have thought gaussian noise would be more reasonable?
There was a problem hiding this comment.
S is not the noise but the sparse individual component. If we use a Normal distribution, S will mix with the shared signal because sums of Normal distributions are also Normal distributions. In that case you will have a difficult time to identify what comes from where (Shared vs individual). This is also a common assumption for the RPCA.
| "features = 3\n", | ||
| "snr = 20 # in dB\n", | ||
| "amplitude = 8.0 # approximate amplitude used for the values in Si\n", | ||
| "p = 0.05 # probability of being non-zero in Si" |
There was a problem hiding this comment.
How does this relate to the gamma value used later? Why are they not the same?
There was a problem hiding this comment.
p is the probability of an element to be non-zero in the original Si (drawn from the model).
gamma is selected to approximately have the same number of non-zeros in the estimated Si.
However, there is no reason for them to have the same values. Ones is the probability and the other is a balancing value between regularization terms.
There was a problem hiding this comment.
I might still be misunderstanding but shouldn't the non-zero elements of the original Si be thought of as the individual component that RSRM is aiming to extract? Why would there be a different number in the input vs the output?
There was a problem hiding this comment.
The math is not translated 1:1. Remember that this is probability, and when you draw a signal there are not exactly 5% of non-zeros. There could be anywhere near the 0.05. Added to that this will be differently with all subjects. So every subject will have approximately that, but not exactly.
Therefore, even if you can obtain a 1:1 translation from p (range 0 to 1) to gamma (range 0 to +inf), still the signal itself will not necessarily behave in that way.
Also, this is a particular case of drawing Si's, and you can change it by other distributions as well. In such case, you will have parameters to generate the signals and still gamma to recover it. Dividing between gamma and p, it is a good idea.
There was a problem hiding this comment.
Okay fair enough I understand
| " n = noise_level * np.random.randn(voxels, samples)\n", | ||
| " data[s] += n\n", | ||
| " \n", | ||
| "S = [None] * subjects\n", |
There was a problem hiding this comment.
Might be good to make another example where there is no S variability and show that RSRM does as well as SRM
There was a problem hiding this comment.
The idea of the example is to show how to use it. I chose the synthetic example as it is easy to replicate and visually show the improvements. If you set gamma to "infinity", you will be solving exactly the (deterministic) SRM.
|
@CameronTEllis do you have any suggestion or comment for the newest version? |
|
@CameronTEllis do you think there are more changes to be done? If we are done, then don't forget to approve the review. Otherwise let me know. |
The code introduces the Robust SRM, tests and an example with synthetic data.