-
Notifications
You must be signed in to change notification settings - Fork 74
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
randomized svd draft #3008
base: main
Are you sure you want to change the base?
randomized svd draft #3008
Conversation
@petrelharp Here's the code. |
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## main #3008 +/- ##
==========================================
- Coverage 89.82% 87.07% -2.75%
==========================================
Files 29 11 -18
Lines 31986 24666 -7320
Branches 6192 4556 -1636
==========================================
- Hits 28730 21478 -7252
+ Misses 1859 1824 -35
+ Partials 1397 1364 -33
Flags with carried forward coverage won't be shown. Click here to find out more. |
This looks great! Very elegant. I think probably we ought to include a So, how about the signature is like
and:
Note that we could be getting PCs for non-sample nodes (since individual's nodes need not be samples); I haven't thought through whether the values you get are correct or informative. My guess is that maybe they are? But we need a "user beware" note for this? |
Ah, sorry - one more thing - does this work with I think the way to do the windows would be something like
Basically - get it to work in the case where |
A simple test case for the
Because of the randomness of the algo, the correlation is not exactly 1, although it's nearly 1 like 0.99995623-ish. |
I just noticed that |
Check results for two windows.
|
…tion, it omits return in the end of the function
Re the result object, I'd imagined something like @dataclasses.dataclass
class PcaResult:
descriptive_name1: np.ndarray # Or whatever type hints we can get to work
descriptive_name2... |
Now,
A user can continuously improve their estimate through Q.
If the first round did |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks great, but I would suggest we break the nested functions out to the module level rather than embedding them in the TreeSequence class. The function is currently too long, and it's not clear what needs to be embedded within the function because it's using the namespace, vs what's in there just because. It would be nice to be able to test the bits of this individually, and putting them at the module level will make that possible.
Certainly the return class should be defined at the module level and added to the Sphinx documentation so that it can be linked to.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor nitpick about code organisation!
It now has a time-resolved feature. You can select branches within the lower and the upper time limits. It is based on decapitate. |
NICE! |
I made a pass through the docs. We need to add |
Co-authored-by: Peter Ralph <petrel.harp@gmail.com>
Co-authored-by: Peter Ralph <petrel.harp@gmail.com>
Co-authored-by: Peter Ralph <petrel.harp@gmail.com>
Co-authored-by: Peter Ralph <petrel.harp@gmail.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me. I think we need to tidy up the lint and get tests passing next so we can see how coverage is doing?
python/tskit/trees.py
Outdated
samples, sample_individuals = ( | ||
ij[:, 0], | ||
ij[:, 1], | ||
) # sample node index, individual of those nodes |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Putting comments at the end of lines is causing them to get broken by Black. Better to put the comments on the line immediately above.
python/tskit/trees.py
Outdated
The principal component factors. Columns are orthogonal, with one entry per sample | ||
or individual (see :meth:`pca <.TreeSequence.pca>`). | ||
""" | ||
eigen_values: np.ndarray |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
eigenvalues is one word, isn't it?
ploidy=2, | ||
sequence_length=10, | ||
random_seed=123, | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe a test for n_components=0
and -1
also?
if np.allclose(x, 0): | ||
r = 1.0 | ||
else: | ||
r = np.mean(x / y) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not right, as here we want r
to be +/-1, I think?
It looks like the things to do here are:
|
Description
A draft of randomized principal component analysis (PCA) using the
TreeSequence.genetic_relatedness_vector
. The implementation containsspicy.sparse
which should eventually be removed.This part of the code is only used when collapsing a
#sample * #sample
GRM into a#individual * #individual
matrix.Therefore, it will not be difficult to replace with pure numpy.
The API was partially taken from scikit-learn.
To add some details,
iterated_power
is the number of power iterations in the range finder in the randomized algorithm. The error of SVD decreases exponentially as a function of this number.The effect of power iteration is profound when the eigen spectrum of the matrix decays slowly, which seems to be the case of tree sequence GRMs in my experience.
indices
specifies the individuals to be included in the PCA, although decreasing the number of individuals does not meaningfully reduce the amount of computation.