-
-
Notifications
You must be signed in to change notification settings - Fork 10.8k
API: Add matrix_norm
, vector_norm
, vecdot
and matrix_transpose
[Array API]
#25155
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
Conversation
4f392bf
to
0f6b8b1
Compare
0f6b8b1
to
32526b4
Compare
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.
Overall looks good, tests just need to be cleaned up. I see that the implementations are copy/pasted from the existing array API wrappers. This is probably fine as a first pass but I suspect there are more performant implementations we could use.
|
||
* `numpy.vecdot` and `numpy.linalg.vecdot` | ||
|
||
* `numpy.matrix_transpose` and `numpy.linalg.matrix_transpose` |
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.
Can you add a sentence or two describing what these functions do?
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.
Sure! I added one sentence descriptions from Array API definitions.
8102ddb
to
665d6c6
Compare
matrix_norm
, vector_norm
, vecdot
and matrix_transpose
[Array API]matrix_norm
, vector_norm
, vecdot
and matrix_transpose
[Array API]
numpy/_core/fromnumeric.py
Outdated
transpose : Generic transpose method. | ||
|
||
""" | ||
x = asarray(x) |
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.
Similar to the discussion in the other PR - should this be asanyarray
?
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 think there was roughly an agreement in #25101 (comment) that asanyarray
can be used in place of asarray
.
I replaced it for functions added here and outer
that has been merged.
b3011a7
to
daa0350
Compare
x1_ = np.moveaxis(x1_, axis, -1) | ||
x2_ = np.moveaxis(x2_, axis, -1) | ||
|
||
res = x1_[..., None, :] @ x2_[..., None] |
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.
@seberg mentioned on the triage call today that this is supposed to do the hermitian conjugate according to the array API standard - does the matmul operator do that?
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.
And if so, probably worth adding a test that has complex vectors.
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.
Right, a conjugate was missing - I added it (and a test) according to Array API.
Note: np.vdot
does conjugate on the first parameter (if it's complex), where np.vecdot
does it on the second one (I mentioned it in the vecdot
's docs).
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.
no, the numpy way is correct, the array-api way is just a bug.
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.
Ah, right (I see that pytorch also performs conjugate on the first argument). Let me change that here and fix it in the Array API.
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.
Can you open an issue that this should have a dedicated ufunc? BLAS should have kernels which perform the complex conjugation on the fly, so at least for the complex conjugating case, this is really not ideal.
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.
Note that wikipedia disagrees: the conjugate of the second argument is taken: https://en.wikipedia.org/wiki/Dot_product#Complex_vectors
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.
Mathematicians and physicists have opposite conventions. Mathematicians use sesquilinear forms, physicists follow the Dirac bracket convention (I don't know who actually started the convention). It can make teaching awkward ...
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.
But then BLAS agrees with what you have, so I guess wikipedia is confused too... https://netlib.org/lapack/explore-html/d1/dcc/group__dot_ga5c189335a4e6130a2206c190579b1571.html#ga5c189335a4e6130a2206c190579b1571
daa0350
to
f7b5640
Compare
f7b5640
to
dd913aa
Compare
Alright, let's pull this one in. Thanks @mtsokol! One note: in the release notes the code literals should be wrapped in double backticks, not single backticks. Can you go through all the release notes you've added and make sure they're all formatted correctly? Merging this anyway since that's a minor issue that can be fixed separately. |
@ngoldbaum I did this formatting on purpose. Double backticks give code format, where single backticks create a link to NumPy member's documentation. For example see: https://github.com/numpy/numpy/blob/4b5ae68c78a222eba2e07cc1e34bd29d5cfeb30d/doc/release/upcoming_changes/22539.deprecation.rst?plain=1 from a PR shipped with 1.25.0 release. which resulted in: ![]() |
Ah, thanks for the explanation! Gotta love sphinx/rst trivia like that. |
f"but they are: {x1_shape[axis]} and {x2_shape[axis]}." | ||
) | ||
|
||
x1_, x2_ = np.broadcast_arrays(x1, x2) |
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.
Darn, another one. Would it still be possible to add subok=True
here to allow subclasses to "just work"?
ndim = builtins.max(x1.ndim, x2.ndim) | ||
x1_shape = (1,)*(ndim - x1.ndim) + tuple(x1.shape) | ||
x2_shape = (1,)*(ndim - x2.ndim) + tuple(x2.shape) | ||
if x1_shape[axis] != x2_shape[axis]: |
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.
Note that this use of axis
is contrary to how a gufunc
would interpret it: there axis
is taken for every element separately before broadcasting, i.e., for vectors with shapes (3, 4) and (3, 2, 4) and axis=0
, the output would have shape (2, 4). You can see this from
from numpy._core.umath_tests import inner1d
a = np.arange(12).reshape(3, 4)
b = np.arange(24).reshape(3, 2, 4)
inner1d(a, b, axis=0).shape
# (2, 4)
I think we should stick with this, otherwise this is going to be very confusing in the future (alternatively, one would need to change how axis
and axes
are interpreted in gufuncs...)
Hi @rgommers @ngoldbaum,
This PR contains the last Array API compatibility update for
numpy.linalg
. It adds:numpy.linalg.matrix_norm
numpy.linalg.vector_norm
numpy.vecdot
andnumpy.linalg.vecdot
numpy.matrix_transpose
andnumpy.linalg.matrix_transpose