Repository navigation
Refactoring across backends - #217
Conversation
|
Thanks @aarmey! I like the idea of the refactoring - SVD_FUNS was a hacky solution to a problem that appeared when introducing the backend system. So, how about adding a parameter (e.g. Regarding mxnet.np, indeed, I was waiting for it to be finalized to switched, we can open a separate PR for that! Regarding As a side note, I would like to enable dispatching tenalg calls directly to the backend in case they implement a particular function but I'm worried it can become a big mess, it's already not the most intuitive :/ |
|
|
||
| def truncated_svd(self, matrix, n_eigenvecs=None, **kwargs): | ||
| """Computes a truncated SVD on `matrix` using pytorch's SVD | ||
| def truncated_svd(self, matrix, n_eigenvecs=None): |
There was a problem hiding this comment.
we could add a parameter svd_fun="svd" and carefully document it? This could then accept "numpy_svd", and other when applicable. That would probably be cleaner than what we have now.
There was a problem hiding this comment.
I don't think it was actually used anywhere but we can add it back if it breaks things downstream.
|
|
||
| index = Index() | ||
|
|
||
| @property |
There was a problem hiding this comment.
If we go for that solution we could have a function available_svd_funs instead of this? What do you think?
d45beab to
2aa9834
Compare
1. A matrix was initialised using SVD, should be ones 2. Created Parafac2Tensor from tuple of factors not list of factors
Codecov Report
@@ Coverage Diff @@
## main #217 +/- ##
==========================================
+ Coverage 87.00% 87.02% +0.02%
==========================================
Files 82 86 +4
Lines 3825 4055 +230
==========================================
+ Hits 3328 3529 +201
- Misses 497 526 +29
Continue to review full report at Codecov.
|
|
Thanks a lot @aarmey, this is a large but necessary change to make the behaviour of SVD clearer to users. Overally looks good to me, the change from I'd really rather avoid converting to NumPy as much as possible as it breaks the computational graph in some backends and causes surprising issues (e.g. if running the method on GPU). On the API side, I'm wondering whether we want to provide a function def partial_svd(matrix, n_eigenvecs, implementation='truncate')where What do you think? |
|
I think this SVD interface looks great. Indeed, I partly wanted these changes to move more of the SVD methods to the proper backend as opposed to silently going back to NumPy. I like that your suggestion will make it clear whether the method is using the indicated backend or Scipy. Perhaps I can open an issue with your notes here? I expect that changing the SVD interface is going to be another large, complicated change. |
|
Yes, that's a good idea. There are some conversions to NumPy in the reconstruction errors, would be great to remove those before merging if possible! |
|
@JeanKossaifi removed. |
JeanKossaifi
left a comment
There was a problem hiding this comment.
Thanks @aarmey for the all great changes! 🥇
Merging.
| new_rec_error, new_tensor, new_norm_tensor = error_calc(tensor, norm_tensor, new_weights, new_factors, sparsity, mask) | ||
|
|
||
| if (new_rec_error / new_norm_tensor) < rec_errors[-1]: | ||
| if tl.to_numpy(new_rec_error / new_norm_tensor) < rec_errors[-1]: |
There was a problem hiding this comment.
Why convert to NumPy? I'd rather avoid doing this in the backends as this breaks the computational graph.
| from tensorly.testing import assert_ | ||
|
|
||
| skip_if_backend = pytest.mark.skipif(tl.get_backend() in ("tensorflow", "jax"), | ||
| skip_if_backend = pytest.mark.skipif(tl.get_backend() in ("tensorflow", "jax", "cupy"), |
There was a problem hiding this comment.
Why are we skipping with cupy too ?
| return torch.sum(tensor, dim=axis) | ||
|
|
||
| @staticmethod | ||
| def flip(tensor, axis=None): |
There was a problem hiding this comment.
Much better name than _reverse, thanks! :)
| rec_X.append(T.norm(X - D - E, 2)) | ||
| rec_D.append(np.max([T.norm(low_rank - D, 2) for low_rank in J])) | ||
| rec_X.append(T.to_numpy(T.norm(X - D - E, 2))) | ||
| rec_D.append(np.max([T.to_numpy(T.norm(low_rank - D, 2)) for low_rank in J])) |
There was a problem hiding this comment.
Why convert to NumPy here?
|
|
||
| rec_error = unnorml_rec_error / norm_tensor | ||
| rec_errors.append(rec_error) | ||
| rec_errors.append(tl.to_numpy(rec_error)) |
There was a problem hiding this comment.
Same here, I'd rather avoid this.
| def svd(self, X, full_matrices=True): | ||
| # The torch SVD has accuracy issues. Try again when torch.linalg is stable. | ||
| ctx = self.context(X) | ||
| X = self.to_numpy(X) |
There was a problem hiding this comment.
Pytorch 1.8 is now the stable release, should we consider replacing this with torch.linalg.svd?
As a side note, the linear algebra functions in torch will be deprecated in favour of their linalg counterparts with the release of 1.9. For example, torch.qr is already deprecated in 1.8 we should replace it with torch.linalg.qr.
There was a problem hiding this comment.
Yes, I was actually looking forward to switching torch.linalg.svd! Thanks @merajhashemi !
There was a problem hiding this comment.
Thanks for the note @merajhashemi. I'll open an issue to make sure this is done.
I know there's some discussion below about changing the SVD interface now that it can be handled as a frontend feature. Perhaps we can merge this as a first step?