-
Notifications
You must be signed in to change notification settings - Fork 134
Closed
Description
Description
Newer numpy versions introduced the vecmat and matvec (and they had vecdot for a while), which we have internally as different Blockwise versions of Dot
, just like matmul
. We should expose those as we do with matmul
:
pytensor/pytensor/tensor/math.py
Lines 2760 to 2841 in 5d4e9e0
# Predefine all batched variations of Dot | |
_inner_prod = Blockwise( | |
_dot, | |
signature="(n),(n)->()", | |
) | |
_matrix_vec_prod = Blockwise( | |
_dot, | |
signature="(m,k),(k)->(m)", | |
) | |
_vec_matrix_prod = Blockwise( | |
_dot, | |
signature="(k),(k,n)->(n)", | |
) | |
_matrix_matrix_matmul = Blockwise( | |
_dot, | |
signature="(m,k),(k,n)->(m,n)", | |
gufunc_spec=("numpy.matmul", 2, 1), | |
) | |
def matmul(x1: "ArrayLike", x2: "ArrayLike", dtype: Optional["DTypeLike"] = None): | |
"""Compute the matrix product of two tensor variables. | |
Parameters | |
---------- | |
x1, x2 | |
Input arrays, scalars not allowed. | |
dtype | |
The desired data-type for the array. If not given, then the type will | |
be determined as the minimum type required to hold the objects in the | |
sequence. | |
Returns | |
------- | |
out : ndarray | |
The matrix product of the inputs. This is a scalar only when both | |
`x1`, `x2` are 1-d vectors. | |
Raises | |
------ | |
ValueError | |
If the last dimension of `x1` is not the same size as the second-to-last | |
dimension of `x2`. If a scalar value is passed in. | |
Notes | |
----- | |
The behavior depends on the arguments in the following way. | |
- If both arguments are 2-D they are multiplied like conventional matrices. | |
- If either argument is N-D, N > 2, it is treated as a stack of matrices | |
residing in the last two indexes and broadcast accordingly. | |
- If the first argument is 1-D, it is promoted to a matrix by prepending a | |
1 to its dimensions. After matrix multiplication the prepended 1 is removed. | |
- If the second argument is 1-D, it is promoted to a matrix by appending a | |
1 to its dimensions. After matrix multiplication the appended 1 is removed. | |
`matmul` differs from `dot` in two important ways: | |
- Multiplication by scalars is not allowed, use `mul` instead. | |
- Stacks of matrices are broadcast together as if the matrices were elements, | |
respecting the signature ``(n, k), (k, m) -> (n, m)``: | |
""" | |
x1 = as_tensor_variable(x1) | |
x2 = as_tensor_variable(x2) | |
if x1.type.ndim == 0 or x2.type.ndim == 0: | |
raise ValueError("matmul operand cannot be scalar") | |
if x1.type.ndim == 1 and x2.type.ndim == 1: | |
out = _dot(x1, x2) | |
elif x1.type.ndim == 1: | |
out = _matrix_matrix_matmul(x1[None], x2).squeeze(-2) | |
elif x2.type.ndim == 1: | |
out = _matrix_matrix_matmul(x1, x2[:, None]).squeeze(-1) | |
else: | |
out = _matrix_matrix_matmul(x1, x2) | |
if dtype is not None: | |
out = out.astype(dtype) | |
return out |
https://numpy.org/doc/stable/reference/generated/numpy.matvec.html#numpy.matvec
https://numpy.org/doc/stable/reference/generated/numpy.vecmat.html
https://numpy.org/doc/stable/reference/generated/numpy.vecdot.html#numpy.vecdot