-
-
Notifications
You must be signed in to change notification settings - Fork 25.4k
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
ENH Array API support for PCA #26315
ENH Array API support for PCA #26315
Conversation
44d5d75
to
ceb10e3
Compare
One more question regarding I used Should I use |
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.
Thanks for the PR, here is a first batch of feedback.
Out of curiosity did you run some benchmarks both on a CPU and on a GPU?
Also please avoid assuming that get_namespace
will only be used to add torch support but let's strive to add generic Array API support as much as possible by default. In particular, it would be great to make this PR generic enough to also work with CuPy (and tested accordingly).
I used xp.reshape, as it conforms to both libraries to access the diagonal, but it might cause array copying (stated explicitly in docs).
Should I use np.flat and torch.view and check array type backend explicitly in code? (But it's not desired approach). Or do you know another way for accessing array's diagonal?
It's probably acceptable to have namespace specific code paths for performance reasons with a fallback to the default xp.reshape
. However we should try to factorize those namespace specific hacks in a common private module reused by all scikit-learn estimators that may need it.
/cc @thomasjpfan who might be able to provide more precise guidance. |
Also @mtsokol be aware that there are related concurrent discussions in other issues that might be of interest for this PR. I tried to label all those issues and PRs with the "Array API" label: Since Array API support is still quite new and experimental we should try to coordinate between the work of different PRs to make consistent design decisions across estimators. |
Hi @ogrisel, Thank you for your feedback! I think all comments are clear to me, let me follow-up on connected PRs/work to avoid repeating changes, then I will continue this PR. I think a separate module to store all tensor-library specific hacks should help here. Unfortunately, I don't have access to GPU, but I will perform CPU benchmark comparison across libraries. |
About the |
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.
Thank you for the PR @mtsokol !
I recommend testing with numpy.array_api
to catch places where the Array API specification is not being followed. Here is an example:
scikit-learn/sklearn/tests/test_discriminant_analysis.py
Lines 680 to 684 in fa5f43f
@skip_if_array_api_compat_not_configured | |
@pytest.mark.parametrize("array_namespace", ["numpy.array_api", "cupy.array_api"]) | |
def test_lda_array_api(array_namespace): | |
"""Check that the array_api Array gives the same results as ndarrays.""" | |
xp = pytest.importorskip(array_namespace) |
I created #26348 to discuss the topic of common tests for Array API suport, hopefully we can converge on something and make a separate PR for this topic. |
@mtsokol #26372 was merged in Also let us know if you want someone else to takeover the PR to address all the comments in the above discussion if you don't have the time to do it yourself. |
For reference, I commented on an older thread about the randomized svd case here: #26315 (comment) |
Hi @ogrisel, If it's Ok, maybe someone can take this PR from here? I'm sorry for not communicating that earlier. |
I tried to push a fix in the previous commit but apparently it's wrong (it broke many other tests). I will investigate later. EDIT: should now be fixed in c84e4ef. |
Co-authored-by: Thomas J. Fan <thomasjpfan@gmail.com>
…h raw numpy arrays without device attribute
…h raw numpy arrays without device attribute
@thomasjpfan actually I still need to protect against missing I realized that we did not have tests for this case. So I enabled this case in e30bfa8 (and updated the code accordingly). I now have all 92 tests pass (for |
Note that |
Can't we use |
We would cannot import from |
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.
I'm trying to push for us to not need to_device
and use xp.asarray
for device transfer. The rest of the PR looks good to go.
I ran the array_api
test locally with all the dependencies and everything passes.
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.
LGTM, thank you everyone for working on this!
Whoop whoop! Nice work everyone on yet another PR that turns out to involve a lot more work than you originally thought :D |
Co-authored-by: Olivier Grisel <olivier.grisel@ensta.org> Co-authored-by: Tim Head <betatim@gmail.com> Co-authored-by: Thomas J. Fan <thomasjpfan@gmail.com>
Co-authored-by: Olivier Grisel <olivier.grisel@ensta.org> Co-authored-by: Tim Head <betatim@gmail.com> Co-authored-by: Thomas J. Fan <thomasjpfan@gmail.com>
Reference Issues/PRs
Based on #25956
What does this implement/fix? Explain your changes.
This PR adds PyTorch support (via
array_api_compat
) for PCA. It changes heavy operations (i.e.svd
) to use proper backend, based on passed array type. Also a unit test is added to assert that PyTorch output is the same as NumPy one.Solvers support:
randomized
to array_apiThe
arpack
solver usessvds
which is not supported by PyTorch (the closest method that I found wastorch.svd_lowrank
that is meant to be used for sparse matrices, but it only computes an approximation). Should I just throw an exception with proper description? (thatarpack
for PyTorch tensors is not supported)Similar case occurs for
randomized
solver. Therandomized_svd
is usinglu
method for decomposition, whose API differs between SciPy and PyTorch (here, the implementation usespermute_l=True
parameter that returnsPL, U
instead ofP, L, U
. The PyTorch implementation doesn't support this parameter. Moreover Numpy.linalg does not providelu
). Therefore supportingrandomized
would require explicitly checking if PyTorch backend is present.Any other comments?
Please share your feedback!
TODO
get_covariance
/get_precision
methods)Benchmark results
=> numpy with MKL has a thread-related performance problem with
float32
data!EDIT: I tried with OpenBLAS and the numpy code runs in 6 to 8s (not exactly the same machine though). So there is definitely a problem between numpy and MKL on float32 data for this workload.
Environment:
This machine has a 48 physical core CPU and a NVIDIA A100 GPU.
Benchmark script: