You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mxnet.apache.org by zh...@apache.org on 2021/10/08 22:33:40 UTC
[incubator-mxnet] branch master updated: [API Standardization] Add
Linalg kernels: (diagonal, outer, tensordot, cross, trace,
matrix_transpose) (#20638)
This is an automated email from the ASF dual-hosted git repository.
zhenghuijin pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-mxnet.git
The following commit(s) were added to refs/heads/master by this push:
new 7be60ca [API Standardization] Add Linalg kernels: (diagonal, outer, tensordot, cross, trace, matrix_transpose) (#20638)
7be60ca is described below
commit 7be60caefcfdf2329a50f12d4ecad2daa92949bc
Author: mozga <ma...@intel.com>
AuthorDate: Sat Oct 9 00:31:23 2021 +0200
[API Standardization] Add Linalg kernels: (diagonal, outer, tensordot, cross, trace, matrix_transpose) (#20638)
* Linalg cross operator - initial commit
* Diagonal and outer linalg support
* Tensordot ->_mx_nd_np.tensordot
* Flake8 checker applied
* New ops: trace, tensordot
* Linalg tranpose support
---
python/mxnet/numpy/linalg.py | 335 +++++++++++++++++++++++++++++++++++++++++--
1 file changed, 323 insertions(+), 12 deletions(-)
diff --git a/python/mxnet/numpy/linalg.py b/python/mxnet/numpy/linalg.py
index 5713d7d..ea4c9d5 100644
--- a/python/mxnet/numpy/linalg.py
+++ b/python/mxnet/numpy/linalg.py
@@ -22,16 +22,24 @@ from .fallback_linalg import * # pylint: disable=wildcard-import,unused-wildcar
from . import fallback_linalg
__all__ = ['norm', 'svd', 'cholesky', 'qr', 'inv', 'det', 'slogdet', 'solve', 'tensorinv', 'tensorsolve',
- 'pinv', 'eigvals', 'eig', 'eigvalsh', 'eigh', 'lstsq', 'matrix_rank']
+ 'pinv', 'eigvals', 'eig', 'eigvalsh', 'eigh', 'lstsq', 'matrix_rank', 'cross', 'diagonal', 'outer',
+ 'tensordot', 'trace', 'matrix_transpose']
__all__ += fallback_linalg.__all__
def matrix_rank(M, tol=None, hermitian=False):
- r"""Return matrix rank of array using SVD method
+ r"""
+ Return matrix rank of array using SVD method
Rank of the array is the number of singular values of the array that are
greater than `tol`.
+ Notes
+ -----
+ `matrix_rank` is an alias for `matrix_rank`. It is a standard API in
+ https://data-apis.org/array-api/latest/extensions/linear_algebra_functions.html#linalg-matrix-rank-x-rtol-none
+ instead of an official NumPy operator.
+
Parameters
----------
M : {(M,), (..., M, N)} ndarray
@@ -44,7 +52,7 @@ def matrix_rank(M, tol=None, hermitian=False):
hermitian : bool, optional
If True, `M` is assumed to be Hermitian (symmetric if real-valued),
enabling a more efficient method for finding singular values.
- Defaults to False.
+ Default: False.
Returns
-------
@@ -54,19 +62,317 @@ def matrix_rank(M, tol=None, hermitian=False):
Examples
--------
>>> from mxnet import np
- >>> np.matrix_rank(np.eye(4)) # Full rank matrix
+ >>> np.linalg.matrix_rank(np.eye(4)) # Full rank matrix
4
>>> I=np.eye(4); I[-1,-1] = 0. # rank deficient matrix
- >>> np.matrix_rank(I)
+ >>> np.linalg.matrix_rank(I)
3
- >>> np.matrix_rank(np.ones((4,))) # 1 dimension - rank 1 unless all 0
+ >>> np.linalg.matrix_rank(np.ones((4,))) # 1 dimension - rank 1 unless all 0
1
- >>> np.matrix_rank(np.zeros((4,)))
+ >>> np.linalg.matrix_rank(np.zeros((4,)))
0
"""
return _mx_nd_np.linalg.matrix_rank(M, tol, hermitian)
+def matrix_transpose(a):
+ r"""
+ Transposes a matrix (or a stack of matrices) `a`.
+
+ Notes
+ -----
+ `matrix_transpose` is an alias for `transpose`. It is a standard API in
+ https://data-apis.org/array-api/latest/extensions/linear_algebra_functions.html#linalg-matrix-transpose-x
+ instead of an official NumPy operator.
+
+ Parameters
+ ----------
+ a : ndarray
+ Input array having shape (..., M, N) and whose innermost two dimensions form MxN matrices.
+
+ Returns
+ ----------
+ out : ndarray
+ An array containing the transpose for each matrix and having shape (..., N, M).
+ The returned array must have the same data type as `a`.
+
+ Examples
+ --------
+ >>> x = np.arange(4).reshape((2,2))
+ >>> x
+ array([[0., 1.],
+ [2., 3.]])
+ >>> np.transpose(x)
+ array([[0., 2.],
+ [1., 3.]])
+ >>> x = np.ones((1, 2, 3))
+ >>> np.transpose(x, (1, 0, 2)).shape
+ (2, 1, 3)
+ """
+ return _mx_nd_np.transpose(a, axes=None)
+
+
+def trace(a, offset=0):
+ r"""
+ Returns a tensor contraction of `a` and `b` over specific axes.
+
+ Notes
+ -----
+ `trace` is an alias for `trace`. It is a standard API in
+ https://data-apis.org/array-api/latest/extensions/linear_algebra_functions.html#linalg-trace-x-offset-0
+ instead of an official NumPy operator.
+
+ Parameters
+ ----------
+ a : ndarray
+ Input array having shape (..., M, N) and whose innermost two dimensions form MxN matrices.
+ Should have a numeric data type.
+ offset : int
+ Offset specifying the off-diagonal relative to the main diagonal.
+
+ offset = 0 : the main diagonal.
+ offset > 0 : off-diagonal above the main diagonal.
+ offset < 0 : off-diagonal below the main diagonal.
+
+ Default: 0.
+
+ Returns
+ ----------
+ out : ndarray
+ An array containing the traces and whose shape is determined by removing the last two dimensions and storing
+ the traces in the last array dimension. For example, if `a` has rank `k` and shape `(I, J, K, ..., L, M, N)`,
+ then an output array has rank `k-2` and shape `(I, J, K, ..., L)`
+ where: `out[i, j, k, ..., l] = trace(a[i, j, k, ..., l, :, :])`
+ The returned array must have the same data type as `a`.
+
+ Examples
+ --------
+ >>> x = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]])
+ >>> np.linalg.trace(x)
+ array(3.)
+ >>> x = np.arange(8).reshape((2, 2, 2))
+ >>> np.linalg.trace(x)
+ array([6., 8.])
+ >>> x = np.arange(24).reshape((2, 2, 2, 3))
+ >>> np.linalg.trace(x).shape
+ (2, 3)
+ >>> np.linalg.trace(x)
+ array([[18., 20., 22.],
+ [24., 26., 28.]])
+ """
+ # axis1, axis2: defaults are the first two axes of `a`.
+ return _mx_nd_np.trace(a, offset=offset, axis1=0, axis2=1, out=None)
+
+
+def tensordot(a, b, axes=2):
+ r"""
+ Returns a tensor contraction of `a` and `b` over specific axes.
+
+ Notes
+ -----
+ `tensordot` is an alias for `tensordot`. It is a standard API in
+ https://data-apis.org/array-api/latest/extensions/linear_algebra_functions.html#linalg-tensordot-x1-x2-axes-2
+ instead of an official NumPy operator.
+
+ Parameters
+ ----------
+ a : ndarray
+ First input array. Should have a numeric data type.
+ b : ndarray
+ Second input array. Must be compatible with `a` (see Broadcasting). Should have a numeric data type.
+ axes : int, tuple
+ Number of axes to contract or explicit sequences of axes for `a` and `b`, respectively.
+ If axes is an int equal to `N` , then contraction must be performed over the last `N` axes of `a`
+ and the first `N` axes of `b` in order.
+ The size of each corresponding axis (dimension) must match. Must be nonnegative.
+
+ If N equals 0 , the result is the tensor (outer) product.
+ If N equals 1 , the result is the tensor dot product.
+ If N equals 2 , the result is the tensor double contraction (default).
+
+ Default: 2.
+
+ Returns
+ ----------
+ out : ndarray
+ An array containing the tensor contraction whose shape consists of the non-contracted axes (dimensions) of the
+ first array `a`, followed by the non-contracted axes (dimensions) of the second array `b`.
+
+ Examples
+ --------
+ >>> x = np.arange(60.).reshape(3,4,5)
+ >>> y = np.arange(24.).reshape(4,3,2)
+ >>> z = np.linalg.tensordot(x, y, axes=([1,0],[0,1]))
+ >>> z.shape
+ (5, 2)
+ >>> z
+ array([[ 4400., 4730.],
+ [ 4532., 4874.],
+ [ 4664., 5018.],
+ [ 4796., 5162.],
+ [ 4928., 5306.]])
+ """
+ return _mx_nd_np.tensordot(a, b, axes)
+
+
+def diagonal(a, offset=0):
+ r"""
+ Returns the specified diagonals of a matrix (or a stack of matrices) `a`.
+
+ Notes
+ -----
+ `diagonal` is an alias for `diagonal`. It is a standard API in
+ https://data-apis.org/array-api/latest/extensions/linear_algebra_functions.html#linalg-diagonal-x-offset-0
+ instead of an official NumPy operator.
+
+ Parameters
+ ----------
+ a : ndarray
+ The array to apply diag method.
+ offset : int
+ Extracts or constructs kth diagonal given input array.
+ Offset specifying the off-diagonal relative to the main diagonal.
+
+ offset = 0 : the main diagonal.
+ offset > 0 : off-diagonal above the main diagonal.
+ offset < 0 : off-diagonal below the main diagonal.
+
+ Default: 0.
+
+ Returns
+ ----------
+ out : ndarray
+ An array containing the diagonals and whose shape is determined by removing the last two dimensions and
+ appending a dimension equal to the size of the resulting diagonals.
+ The returned array must have the same data type as a.
+
+ Examples
+ --------
+ >>> x = np.arange(9).reshape((3,3))
+ >>> x
+ array([[0., 1., 2.],
+ [3., 4., 5.],
+ [6., 7., 8.]])
+ >>> np.linalg.diagonal(x)
+ array([0., 4., 8.])
+ >>> np.linalg.diagonal(x, offset=1)
+ array([1., 5.])
+ >>> np.linalg.diagonal(x, offset=-1)
+ array([3., 7.])
+ """
+ return _mx_nd_np.diag(a, k=offset)
+
+
+def cross(a, b, axis=-1):
+ r"""
+ Returns the cross product of 3-element vectors.
+
+ If `a` and `b` are multi-dimensional arrays (i.e., both have a rank greater than 1),
+ then the cross-product of each pair of corresponding 3-element vectors is independently computed.
+
+ Notes
+ -----
+ `cross` is an alias for `cross`. It is a standard API in
+ https://data-apis.org/array-api/latest/extensions/linear_algebra_functions.html#linalg-cross-x1-x2-axis-1
+ instead of an official NumPy operator.
+
+ Parameters
+ ----------
+ a : ndarray
+ First input array. Should have a numeric data type.
+ b : ndarray
+ Second input array. Must have the same shape as a. Should have a numeric data type.
+ axis : int
+ If defined, the axis of `a` and `b` that defines the vector(s) and cross product(s).
+
+ Default: -1.
+
+ Returns
+ -------
+ out : (...) ndarray
+ An array containing the cross products.
+
+ Examples
+ --------
+ Vector cross-product.
+
+ >>> x = np.array([1., 2., 3.])
+ >>> y = np.array([4., 5., 6.])
+ >>> np.linalg.cross(x, y)
+ array([-3., 6., -3.])
+
+ One vector with dimension 2.
+
+ >>> x = np.array([1., 2.])
+ >>> y = np.array([4., 5., 6.])
+ >>> np.linalg.cross(x, y)
+ array([12., -6., -3.])
+
+ Equivalently:
+
+ >>> x = np.array([1., 2., 0.])
+ >>> y = np.array([4., 5., 6.])
+ >>>np.linalg.cross(x, y)
+ array([12., -6., -3.])
+
+ Both vectors with dimension 2.
+
+ >>> x = np.array([1., 2.])
+ >>> y = np.array([4., 5.])
+ >>> np.linalg.cross(x, y)
+ array(-3.)
+
+ Multiple vector cross-products. Note that the direction of the cross
+ product vector is defined by the `right-hand rule`.
+
+ >>> x = np.array([[1., 2., 3.], [4., 5., 6.]])
+ >>> y = np.array([[4., 5., 6.], [1., 2., 3.]])
+ >>> np.linalg.cross(x, y)
+ array([[-3., 6., -3.],
+ [ 3., -6., 3.]])
+ """
+ # For a given API standard, the axis of axisa, axisb, axisc are equal to the axis
+ return _mx_nd_np.cross(a, b, axisa=axis, axisb=axis, axisc=axis, axis=axis)
+
+
+def outer(a, b):
+ r"""
+ Computes the outer product of two vectors `a` and `b`.
+
+ Notes
+ -----
+ `outer` is an alias for `outer`. It is a standard API in
+ https://data-apis.org/array-api/latest/extensions/linear_algebra_functions.html#linalg-outer-x1-x2
+ instead of an official NumPy operator.
+
+ Parameters
+ ----------
+ a : ndarray
+ One-dimensional input array of size `N` . Should have a numeric data type.
+ b : ndarray
+ One-dimensional input array of size `M` . Should have a numeric data type.
+
+ Returns
+ -------
+ out : ndarray
+ A two-dimensional array containing the outer product and whose shape is `(N, M)`.
+ The returned array must have a data type determined by Type Promotion Rules.
+
+ Examples
+ --------
+ Make a (*very* coarse) grid for computing a Mandelbrot set:
+
+ >>> x = np.linalg.outer(np.ones((5,)), np.linspace(-2, 2, 5))
+ >>> x
+ array([[-2., -1., 0., 1., 2.],
+ [-2., -1., 0., 1., 2.],
+ [-2., -1., 0., 1., 2.],
+ [-2., -1., 0., 1., 2.],
+ [-2., -1., 0., 1., 2.]])
+ """
+ return _mx_nd_np.tensordot(a.flatten(), b.flatten(), 0)
+
+
def lstsq(a, b, rcond='warn'):
r"""
Return the least-squares solution to a linear matrix equation.
@@ -207,7 +513,8 @@ def pinv(a, rcond=1e-15, hermitian=False):
def norm(x, ord=None, axis=None, keepdims=False):
- r"""Matrix or vector norm.
+ r"""
+ Matrix or vector norm.
This function can only support Frobenius norm for now.
The Frobenius norm is given by [1]_:
@@ -271,7 +578,8 @@ def norm(x, ord=None, axis=None, keepdims=False):
def svd(a):
- r"""Singular Value Decomposition.
+ r"""
+ Singular Value Decomposition.
When `a` is a 2D array, it is factorized as ``ut @ np.diag(s) @ v``,
where `ut` and `v` are 2D orthonormal arrays and `s` is a 1D
@@ -772,7 +1080,8 @@ def tensorsolve(a, b, axes=None):
def eigvals(a):
- r"""Compute the eigenvalues of a general matrix.
+ r"""
+ Compute the eigenvalues of a general matrix.
Main difference between `eigvals` and `eig`: the eigenvectors aren't
returned.
@@ -840,7 +1149,8 @@ def eigvals(a):
def eigvalsh(a, UPLO='L'):
- r"""Compute the eigenvalues real symmetric matrix.
+ r"""
+ Compute the eigenvalues real symmetric matrix.
Main difference from eigh: the eigenvectors are not computed.
@@ -964,7 +1274,8 @@ def eig(a):
def eigh(a, UPLO='L'):
- r"""Return the eigenvalues and eigenvectors real symmetric matrix.
+ r"""
+ Return the eigenvalues and eigenvectors real symmetric matrix.
Returns two objects, a 1-D array containing the eigenvalues of `a`, and
a 2-D square array or matrix (depending on the input type) of the