"""Packaged operations based on MindSpore."""
__all__ = [
'absolute',
'arange',
'argmax',
'argmin',
'argsort',
'assign',
'intersection',
'matmul',
'maximum',
'minimum',
'mean',
'mul',
'sort',
'sqrt',
'squeeze',
'tile',
'reshape',
'zeros',
'zeros_like',
'softmax',
'Tensor',
'summation'
]
from typing import List, Tuple, Union, Callable
import numpy as np
import mindspore
from mindspore import nn
import mindspore.ops.operations as op
_Axis = Union[int, Tuple[int, ...], List[int]]
_Idx = Union[int, mindspore.Tensor, Tuple[int, ...], Tuple[mindspore.Tensor, ...]]
_Number = Union[int, float, np.int, np.float]
_Shape = Union[int, Tuple[int, ...]]
Tensor = mindspore.Tensor
def absolute(inputs: Tensor) -> Tensor:
"""Get the absolute value of a tensor value."""
abs_op = op.Abs()
outputs = abs_op(inputs)
return outputs
def arange(
start: _Number,
end: _Number,
step: _Number = 1,
dtype: mindspore.dtype = None) -> Tensor:
"""Get the arange value of tensor."""
nums = np.arange(start=start, stop=end, step=step, dtype=np.int32)
nums = mindspore.Tensor(nums, dtype=dtype)
return nums
def argmax(inputs: Tensor, axis: int = -1, keep_dims: bool = False) -> Tensor:
"""Returns the indices of the maximum values along an axis."""
inputs_np = inputs.asnumpy()
outputs = np.argmax(inputs_np, axis=axis)
if keep_dims:
outputs = np.expand_dims(outputs, axis=axis)
return mindspore.Tensor(outputs, mindspore.int32)
def argmin(inputs: Tensor, axis: int = -1, keep_dims: bool = False) -> Tensor:
"""Returns the indices of the minimum values along an axis."""
inputs_np = inputs.asnumpy()
outputs = np.argmin(inputs_np, axis=axis)
if keep_dims:
outputs = np.expand_dims(outputs, axis=axis)
return mindspore.Tensor(outputs, mindspore.int32)
def argsort(inputs: Tensor, axis: int = -1, descending: bool = False) -> Tensor:
"""Returns the indices that would sort an array."""
inputs_np = inputs.asnumpy()
factor = -1 if descending else 1
indices_np = np.argsort(factor * inputs_np, axis=axis)
indices = mindspore.Tensor(indices_np, dtype=mindspore.int32)
return indices
def assign(inputs: Tensor, idx: _Idx, value: Tensor) -> Tensor:
"""Assign a tensor value to the given tensor and index."""
inputs_np = inputs.asnumpy()
if isinstance(idx, Tensor):
idx = idx.asnumpy()
value_np = value.asnumpy()
inputs_np[idx] = value_np
outputs = mindspore.Tensor(inputs_np)
return outputs
def intersection(*inputs: Tensor) -> Tensor:
"""Get the intersection value by the given tensor list."""
outputs_np = np.ones_like(inputs[0])
for inp in inputs:
outputs_np &= inp.asnumpy()
outputs = mindspore.Tensor(outputs_np)
return outputs
def matmul(inputs_x: Tensor, inputs_y: Tensor) -> Tensor:
"""Multiplies matrix `inputs_x` and matrix `inputs_y`."""
matmul_op = op.MatMul()
outputs = matmul_op(inputs_x, inputs_y)
return outputs
def maximum(inputs: Tensor, axis: _Axis = (), keep_dims: bool = False) -> Tensor:
"""Reduces a dimension of a tensor by the maximum value in this dimension."""
max_op = op.ReduceMax(keep_dims)
outputs = max_op(inputs, axis)
return outputs
def minimum(inputs: Tensor, axis: _Axis = (), keep_dims: bool = False) -> Tensor:
"""Reduces a dimension of a tensor by the minimum value in the dimension."""
max_op = op.ReduceMin(keep_dims)
outputs = max_op(inputs, axis)
return outputs
def mean(inputs: Tensor, axis: _Axis = (), keep_dims: bool = False) -> Tensor:
"""Reduces a dimension of a tensor by averaging all elements in the dimension."""
mean_op = op.ReduceMean(keep_dims)
outputs = mean_op(inputs, axis)
return outputs
def mul(inputs_x: Tensor, inputs_y: Tensor) -> Tensor:
"""
Multiplies two tensors element-wise.
Inputs of `input_x` and `input_y` comply with the implicit type conversion rules to make the data types consistent.
The inputs must be two tensors or one tensor and one scalar.
When the inputs are two tensors,
dtypes of them cannot be both bool, and the shapes of them could be broadcast.
When the inputs are one tensor and one scalar,
the scalar could only be a constant.
Inputs:
- **input_x** (Union[Tensor, Number, bool]) - The first input is a number or
a bool or a tensor whose data type is number or bool.
- **input_y** (Union[Tensor, Number, bool]) - The second input is a number or
a bool when the first input is a tensor or a tensor whose data type is number or bool.
Outputs:
Tensor, the shape is the same as the one after broadcasting,
and the data type is the one with higher precision or higher digits among the two inputs.
"""
mul_op = op.Mul()
outputs = mul_op(inputs_x, inputs_y)
return outputs
def sort(inputs: Tensor, axis: _Axis = -1, descending: bool = False) -> Tensor:
"""Return a sorted copy of an array."""
inputs_np = inputs.asnumpy()
outputs_np = np.sort(inputs_np, axis=axis)
if descending:
outputs_np = np.flip(outputs_np, axis=axis)
outputs = mindspore.Tensor(outputs_np)
return outputs
def squeeze(inputs: Tensor, axis: _Axis = ()):
"""Returns a tensor with the same type but dimensions of 1 are removed based on `axis`."""
squeeze_op = op.Squeeze(axis)
outputs = squeeze_op(inputs)
return outputs
def tile(inputs: Tensor, shape: Tuple[int, ...]) -> Tensor:
"""Replicates a tensor with given multiples times."""
tile_op = op.Tile()
outputs = tile_op(inputs, shape)
return outputs
def reshape(inputs: Tensor, shape: _Shape) -> Tensor:
"""Reshapes input tensor with the same values based on a given shape tuple."""
if isinstance(shape, int):
shape = (shape,)
return op.Reshape()(inputs, shape)
def zeros(shape: _Shape, dtype: mindspore.dtype = None) -> Tensor:
"""Return a new array of given shape and type, filled with zeros."""
outputs = np.zeros(shape)
return mindspore.Tensor(outputs, dtype=dtype)
def zeros_like(inputs: Tensor, dtype: mindspore.dtype = None) -> Tensor:
"""Return an array of zeros with the same shape and type as a given array."""
inputs_np = inputs.asnumpy()
outputs_np = np.zeros_like(inputs_np)
outputs = mindspore.Tensor(outputs_np, dtype)
return outputs
def random(shape: _Shape, dtype: mindspore.dtype = None) -> Tensor:
"""Return random floats in the half-open interval [0.0, 1.0)."""
outputs_np = np.random.random(shape)
outputs = mindspore.Tensor(outputs_np, dtype)
return outputs
def randint(low: int, high: int, shape: _Shape, dtype: mindspore.dtype = mindspore.int8) -> Tensor:
"""Return random integers from `low` (inclusive) to `high` (exclusive)."""
outputs_np = np.random.randint(low, high, size=shape)
outputs = mindspore.Tensor(outputs_np, dtype=dtype)
return outputs
def softmax(axis: int = -1) -> Callable:
"""Softmax activation function."""
func = nn.Softmax(axis=axis)
return func
def summation(inputs: Tensor, axis: _Axis = (), keep_dims: bool = False) -> Tensor:
"""Reduces a dimension of a tensor by summing all elements in the dimension."""
sum_op = op.ReduceSum(keep_dims)
outputs = sum_op(inputs, axis)
return outputs
def stack(inputs: List[Tensor], axis: int) -> Tensor:
"""Stacks a list of tensors in specified axis."""
stack_op = op.Stack(axis)
outputs = stack_op(inputs)
return outputs
def sqrt(inputs: Tensor) -> Tensor:
"""Returns square root of a tensor element-wise."""
sqrt_op = op.Sqrt()
return sqrt_op(inputs)