| # coding: utf-8 |
| # pylint: disable= too-many-lines, redefined-builtin, protected-access |
| # pylint: disable=import-error, no-name-in-module, undefined-variable |
| """NDArray API of mxnet.""" |
| from __future__ import absolute_import |
| from __future__ import division |
| try: |
| from __builtin__ import slice as py_slice |
| except ImportError: |
| from builtins import slice as py_slice |
| |
| import ctypes |
| import warnings |
| |
| import os as _os |
| import sys as _sys |
| |
| import operator |
| import numpy as np |
| from .base import _LIB, string_types, numeric_types |
| from .base import c_array, py_str, c_str, mx_real_t |
| from .base import mx_uint, NDArrayHandle, check_call |
| from .base import ctypes2buffer |
| from .context import Context |
| from . import _ndarray_internal as _internal |
| |
| # Use different verison of SymbolBase |
| # When possible, use cython to speedup part of computation. |
| try: |
| if int(_os.environ.get("MXNET_ENABLE_CYTHON", True)) == 0: |
| from ._ctypes.ndarray import NDArrayBase, _init_ndarray_module |
| elif _sys.version_info >= (3, 0): |
| from ._cy3.ndarray import NDArrayBase, _init_ndarray_module |
| else: |
| from ._cy2.ndarray import NDArrayBase, _init_ndarray_module |
| except ImportError: |
| if int(_os.environ.get("MXNET_ENFORCE_CYTHON", False)) != 0: |
| raise ImportError("Cython Module cannot be loaded but MXNET_ENFORCE_CYTHON=1") |
| from ._ctypes.ndarray import NDArrayBase, _init_ndarray_module |
| |
| |
| # pylint: disable= no-member |
| _DTYPE_NP_TO_MX = { |
| np.float32 : 0, |
| np.float64 : 1, |
| np.float16 : 2, |
| np.uint8 : 3, |
| np.int32 : 4 |
| } |
| |
| _DTYPE_MX_TO_NP = { |
| 0 : np.float32, |
| 1 : np.float64, |
| 2 : np.float16, |
| 3 : np.uint8, |
| 4 : np.int32 |
| } |
| # pylint: enable= no-member |
| |
| def _new_empty_handle(): |
| """Returns a new empty handle. |
| |
| Empty handle can be used to hold result. |
| |
| Returns |
| ------- |
| handle |
| A new empty NDArray handle. |
| """ |
| hdl = NDArrayHandle() |
| check_call(_LIB.MXNDArrayCreateNone(ctypes.byref(hdl))) |
| return hdl |
| |
| def _new_alloc_handle(shape, ctx, delay_alloc, dtype=mx_real_t): |
| """Return a new handle with specified shape and context. |
| |
| Empty handle is only used to hold results. |
| |
| Returns |
| ------- |
| handle |
| A new empty NDArray handle. |
| """ |
| hdl = NDArrayHandle() |
| check_call(_LIB.MXNDArrayCreateEx( |
| c_array(mx_uint, shape), |
| mx_uint(len(shape)), |
| ctypes.c_int(ctx.device_typeid), |
| ctypes.c_int(ctx.device_id), |
| ctypes.c_int(int(delay_alloc)), |
| ctypes.c_int(int(_DTYPE_NP_TO_MX[np.dtype(dtype).type])), |
| ctypes.byref(hdl))) |
| return hdl |
| |
| def waitall(): |
| """Wait for all async operations to finish in MXNet. |
| |
| This function is used for benchmarking only. |
| """ |
| check_call(_LIB.MXNDArrayWaitAll()) |
| |
| class NDArray(NDArrayBase): |
| """An array object representing a multidimensional, homogeneous array of |
| fixed-size items. |
| |
| """ |
| __slots__ = [] |
| # pylint: disable= no-member, undefined-variable |
| def __repr__(self): |
| """Returns a string representation of the array.""" |
| shape_info = 'x'.join(['%d' % x for x in self.shape]) |
| return '<%s %s @%s>' % (self.__class__.__name__, |
| shape_info, self.context) |
| |
| def __add__(self, other): |
| """x.__add__(y) <=> x+y <=> mx.nd.add(x, y) """ |
| return add(self, other) |
| |
| def __iadd__(self, other): |
| """x.__iadd__(y) <=> x+=y """ |
| if not self.writable: |
| raise ValueError('trying to add to a readonly NDArray') |
| if isinstance(other, NDArray): |
| return broadcast_add(self, other, out=self) |
| elif isinstance(other, numeric_types): |
| return _internal._plus_scalar(self, float(other), out=self) |
| else: |
| raise TypeError('type %s not supported' % str(type(other))) |
| |
| def __radd__(self, other): |
| return self.__add__(other) |
| |
| def __sub__(self, other): |
| """x.__sub__(y) <=> x-y <=> mx.nd.subtract(x, y) """ |
| return subtract(self, other) |
| |
| def __isub__(self, other): |
| """x.__isub__(y) <=> x-=y """ |
| if not self.writable: |
| raise ValueError('trying to subtract from a readonly NDArray') |
| if isinstance(other, NDArray): |
| return broadcast_sub(self, other, out=self) |
| elif isinstance(other, numeric_types): |
| return _internal._minus_scalar(self, float(other), out=self) |
| else: |
| raise TypeError('type %s not supported' % str(type(other))) |
| |
| def __rsub__(self, other): |
| """x.__rsub__(y) <=> y-x <=> mx.nd.subtract(y, x) """ |
| return subtract(other, self) |
| |
| def __mul__(self, other): |
| """x.__mul__(y) <=> x*y <=> mx.nd.multiply(x, y) """ |
| return multiply(self, other) |
| |
| def __neg__(self): |
| """x.__neg__(y) <=> -x """ |
| return _internal._mul_scalar(self, -1.0) |
| |
| def __imul__(self, other): |
| """x.__imul__(y) <=> x*=y """ |
| if not self.writable: |
| raise ValueError('trying to multiply to a readonly NDArray') |
| if isinstance(other, NDArray): |
| return broadcast_mul(self, other, out=self) |
| elif isinstance(other, numeric_types): |
| return _internal._mul_scalar(self, float(other), out=self) |
| else: |
| raise TypeError('type %s not supported' % str(type(other))) |
| |
| def __rmul__(self, other): |
| return self.__mul__(other) |
| |
| def __div__(self, other): |
| """x.__div__(y) <=> x/y <=> mx.nd.divide(x, y) """ |
| return divide(self, other) |
| |
| def __rdiv__(self, other): |
| """x.__rdiv__(y) <=> y/x <=> mx.nd.divide(y, x) """ |
| return divide(other, self) |
| |
| def __idiv__(self, other): |
| """x.__rdiv__(y) <=> x/=y """ |
| if not self.writable: |
| raise ValueError('trying to divide from a readonly NDArray') |
| if isinstance(other, NDArray): |
| return broadcast_div(self, other, out=self) |
| elif isinstance(other, numeric_types): |
| return _internal._div_scalar(self, float(other), out=self) |
| else: |
| raise TypeError('type %s not supported' % str(type(other))) |
| |
| def __truediv__(self, other): |
| return divide(self, other) |
| |
| def __rtruediv__(self, other): |
| return divide(other, self) |
| |
| def __itruediv__(self, other): |
| return self.__idiv__(other) |
| |
| def __pow__(self, other): |
| """x.__pow__(y) <=> x**y <=> mx.nd.power(x,y) """ |
| return power(self, other) |
| |
| def __rpow__(self, other): |
| """x.__pow__(y) <=> y**x <=> mx.nd.power(y,x) """ |
| return power(other, self) |
| |
| def __eq__(self, other): |
| """x.__eq__(y) <=> x==y <=> mx.nd.equal(x, y) """ |
| return equal(self, other) |
| |
| def __ne__(self, other): |
| """x.__ne__(y) <=> x!=y <=> mx.nd.not_equal(x, y) """ |
| return not_equal(self, other) |
| |
| def __gt__(self, other): |
| """x.__gt__(y) <=> x>y <=> mx.nd.greater(x, y) """ |
| return greater(self, other) |
| |
| def __ge__(self, other): |
| """x.__ge__(y) <=> x>=y <=> mx.nd.greater_equal(x, y) """ |
| return greater_equal(self, other) |
| |
| def __lt__(self, other): |
| """x.__lt__(y) <=> x<y <=> mx.nd.lesser(x, y) """ |
| return lesser(self, other) |
| |
| def __le__(self, other): |
| """x.__le__(y) <=> x<=y <=> mx.nd.less_equal(x, y) """ |
| return lesser_equal(self, other) |
| |
| def __getstate__(self): |
| handle = self.handle |
| this = {'handle' : None} |
| if handle is not None: |
| length = ctypes.c_size_t() |
| cptr = ctypes.POINTER(ctypes.c_char)() |
| check_call(_LIB.MXNDArraySaveRawBytes(self.handle, |
| ctypes.byref(length), |
| ctypes.byref(cptr))) |
| this['handle'] = ctypes2buffer(cptr, length.value) |
| return this |
| |
| def __setstate__(self, state): |
| # pylint: disable=assigning-non-slot |
| handle = state['handle'] |
| if handle is not None: |
| buf = handle |
| handle = NDArrayHandle() |
| ptr = (ctypes.c_char * len(buf)).from_buffer(buf) |
| length = ctypes.c_size_t(len(buf)) |
| check_call(_LIB.MXNDArrayLoadFromRawBytes(ptr, length, ctypes.byref(handle))) |
| self.handle = handle |
| else: |
| self.handle = None |
| |
| def __setitem__(self, key, value): |
| """x.__setitem__(i, y) <=> x[i]=y |
| |
| Set self[key] to value. |
| |
| Parameters |
| ---------- |
| key : int, slice or tuple |
| The indexing key. |
| value : scalar, NDArray or numpy.ndarray |
| The value to set. |
| |
| Examples |
| -------- |
| >>> x = mx.nd.zeros((2,3)) |
| >>> x[:] = 1 |
| >>> x.asnumpy() |
| array([[ 1., 1., 1.], |
| [ 1., 1., 1.]], dtype=float32) |
| >>> x.asnumpy() |
| array([[ 1., 1., 1.], |
| [ 1., 1., 1.]], dtype=float32) |
| >>> x[:,1:2] = 2 |
| >>> x.asnumpy() |
| array([[ 1., 2., 1.], |
| [ 1., 2., 1.]], dtype=float32) |
| >>> x[1:2,1:] = 3 |
| >>> x.asnumpy() |
| array([[ 1., 2., 1.], |
| [ 1., 3., 3.]], dtype=float32) |
| >>> x[1:,0:2] = mx.nd.zeros((1,2)) |
| >>> x.asnumpy() |
| array([[ 1., 2., 1.], |
| [ 0., 0., 3.]], dtype=float32) |
| >>> x[1,2] = 4 |
| >>> x.asnumpy() |
| array([[ 1., 2., 1.], |
| [ 0., 0., 4.]], dtype=float32) |
| """ |
| # pylint: disable=too-many-branches |
| if not self.writable: |
| raise ValueError('Failed to assign to a readonly NDArray') |
| if isinstance(key, int): |
| sliced_arr = self._at(key) |
| sliced_arr[:] = value |
| return |
| if isinstance(key, py_slice): |
| if key.step is not None: |
| raise ValueError('NDArray only supports continuous slicing on axis 0') |
| if key.start is not None or key.stop is not None: |
| sliced_arr = self._slice(key.start, key.stop) |
| sliced_arr[:] = value |
| return |
| if isinstance(value, NDArray): |
| if value.handle is not self.handle: |
| value.copyto(self) |
| elif isinstance(value, numeric_types): |
| _internal._set_value(float(value), out=self) |
| elif isinstance(value, (np.ndarray, np.generic)): |
| self._sync_copyfrom(value) |
| else: |
| raise TypeError('type %s not supported' % str(type(value))) |
| if isinstance(key, tuple): |
| # multi-dimension indexing |
| my_shape = self.shape |
| assert len(key) == len(my_shape) |
| for slice_i in key: |
| assert isinstance(slice_i, (py_slice, int)) |
| begin = [0 for _ in my_shape] |
| end = [x for x in my_shape] |
| for i, slice_i in enumerate(key): |
| if isinstance(slice_i, int): |
| assert slice_i < my_shape[i] |
| begin[i] = slice_i |
| end[i] = slice_i + 1 |
| if isinstance(slice_i, py_slice): |
| # only support continuous slicing |
| assert slice_i.step is None |
| begin[i] = slice_i.start or 0 |
| end[i] = slice_i.stop or my_shape[i] |
| assert begin[i] < end[i] |
| assert end[i] <= my_shape[i] |
| begin = tuple(begin) |
| end = tuple(end) |
| if isinstance(value, NDArray): |
| value = value.as_in_context(self.context) |
| _internal._crop_assign(self, value, out=self, |
| begin=begin, end=end) |
| elif isinstance(value, numeric_types): |
| _internal._crop_assign_scalar(self, out=self, |
| begin=begin, end=end, |
| scalar=value) |
| elif isinstance(value, (np.ndarray, np.generic)): |
| value = array(value, ctx=self.context) |
| _internal._crop_assign(self, value, out=self, |
| begin=begin, end=end) |
| else: |
| raise TypeError('type %s not supported' % str(type(value))) |
| # pylint: enable=too-many-branches |
| |
| def __getitem__(self, key): |
| """x.__getitem__(i) <=> x[i] |
| |
| Returns a sliced view of this array. |
| |
| Parameters |
| ---------- |
| key : int or slice |
| Indexing key. |
| |
| Examples |
| -------- |
| >>> x = mx.nd.arange(0,6).reshape((2,3)) |
| >>> x.asnumpy() |
| array([[ 0., 1., 2.], |
| [ 3., 4., 5.]], dtype=float32) |
| >>> x[1].asnumpy() |
| array([ 3., 4., 5.], dtype=float32) |
| >>> y = x[0:1] |
| >>> y[:] = 2 |
| >>> x.asnumpy() |
| array([[ 2., 2., 2.], |
| [ 3., 4., 5.]], dtype=float32) |
| """ |
| # multi-dimensional slicing is not supported yet |
| if isinstance(key, int): |
| if key > self.shape[0] - 1: |
| raise IndexError( |
| 'index {} is out of bounds for axis 0 with size {}'.format( |
| key, self.shape[0])) |
| return self._at(key) |
| if isinstance(key, py_slice): |
| if key.step is not None: |
| raise ValueError('NDArray only supports continuous slicing on axis 0') |
| if key.start is not None or key.stop is not None: |
| return self._slice(key.start, key.stop) |
| else: |
| return self |
| if isinstance(key, tuple): |
| raise ValueError('Multi-dimension indexing is not supported') |
| |
| |
| def _sync_copyfrom(self, source_array): |
| """Peforms a synchronized copy from the array. |
| |
| Parameters |
| ---------- |
| source_array : array_like) |
| The data source we would like to copy from. |
| """ |
| if not isinstance(source_array, np.ndarray): |
| try: |
| source_array = np.array(source_array, dtype=self.dtype) |
| except: |
| raise TypeError('array must consist of array-like data,' + |
| 'type %s is not supported' % str(type(array))) |
| source_array = np.ascontiguousarray(source_array, dtype=self.dtype) |
| if source_array.shape != self.shape: |
| raise ValueError('Shape inconsistent: expected %s vs got %s'%( |
| str(self.shape), str(source_array.shape))) |
| check_call(_LIB.MXNDArraySyncCopyFromCPU( |
| self.handle, |
| source_array.ctypes.data_as(ctypes.c_void_p), |
| ctypes.c_size_t(source_array.size))) |
| |
| def _slice(self, start, stop): |
| """Returns a sliced NDArray that shares memory with current one. |
| |
| Parameters |
| ---------- |
| start : int |
| Starting index of slice. |
| stop : int |
| Finishing index of slice. |
| """ |
| handle = NDArrayHandle() |
| start = mx_uint(start) if start else mx_uint(0) |
| stop = mx_uint(stop) if stop else mx_uint(self.shape[0]) |
| check_call(_LIB.MXNDArraySlice( |
| self.handle, start, stop, ctypes.byref(handle))) |
| return NDArray(handle=handle, writable=self.writable) |
| |
| def _at(self, idx): |
| """Returns a sliced view of this array. |
| |
| Parameters |
| ---------- |
| idx : int |
| index of sub array. |
| """ |
| handle = NDArrayHandle() |
| idx = mx_uint(idx) |
| check_call(_LIB.MXNDArrayAt( |
| self.handle, idx, ctypes.byref(handle))) |
| return NDArray(handle=handle, writable=self.writable) |
| |
| def reshape(self, shape): |
| """Returns a view of this array with a new shape without altering any data. |
| |
| Parameters |
| ---------- |
| shape : tuple of int |
| The new shape should not change the array size, namely |
| ``np.prod(new_shape)`` should be equal to ``np.prod(self.shape)``. |
| One shape dimension can be -1. In this case, the value is inferred |
| from the length of the array and remaining dimensions. |
| |
| |
| Returns |
| ------- |
| NDArray |
| An array with desired shape that shares data with this array. |
| |
| Examples |
| -------- |
| >>> x = mx.nd.arange(0,6).reshape((2,3)) |
| >>> x.asnumpy() |
| array([[ 0., 1., 2.], |
| [ 3., 4., 5.]], dtype=float32) |
| >>> y = x.reshape((3,2)) |
| >>> y.asnumpy() |
| array([[ 0., 1.], |
| [ 2., 3.], |
| [ 4., 5.]], dtype=float32) |
| >>> y = x.reshape((3,-1)) |
| >>> y.asnumpy() |
| array([[ 0., 1.], |
| [ 2., 3.], |
| [ 4., 5.]], dtype=float32) |
| >>> y[:] = -1 |
| >>> x.asnumpy() |
| array([[-1., -1., -1.], |
| [-1., -1., -1.]], dtype=float32) |
| """ |
| handle = NDArrayHandle() |
| |
| # Infer the correct size for dim == -1 |
| shape = list(shape) |
| for index, element in enumerate(shape): |
| if element == -1: |
| remainder = list(self.shape) |
| for i, e in enumerate(shape): # pylint: disable=invalid-name |
| if i != index and e == -1: |
| raise ValueError('Only one dimension can be inferred.') |
| try: |
| remainder.remove(e) |
| except ValueError: |
| pass |
| shape[index] = np.product(remainder) |
| # We have already gone through the whole shape, break |
| break |
| |
| # Actual reshape |
| check_call(_LIB.MXNDArrayReshape(self.handle, |
| len(shape), |
| c_array(ctypes.c_int, shape), |
| ctypes.byref(handle))) |
| return NDArray(handle=handle, writable=self.writable) |
| |
| # pylint: disable= undefined-variable |
| def broadcast_to(self, shape): |
| """Broadcasts an array to a new shape. |
| |
| Broadcast only allows on axes with size 1. The new shape cannot change |
| the number of dimensions such as from 2D to 3D. |
| |
| Parameters |
| ---------- |
| shape : tuple of int |
| The shape of the desired array. |
| |
| Returns |
| ------- |
| NDArray |
| A NDArray with the desired shape that is not sharing data with this |
| array, even if the new shape is the same as ``self.shape``. |
| |
| Examples |
| -------- |
| >>> x = mx.nd.arange(0,3).reshape((1,3,1)) |
| >>> x.asnumpy() |
| array([[[ 0.], |
| [ 1.], |
| [ 2.]]], dtype=float32) |
| >>> y = x.broadcast_to((2,3,3)) |
| >>> y.asnumpy() |
| array([[[ 0., 0., 0.], |
| [ 1., 1., 1.], |
| [ 2., 2., 2.]], |
| <BLANKLINE> |
| [[ 0., 0., 0.], |
| [ 1., 1., 1.], |
| [ 2., 2., 2.]]], dtype=float32) |
| """ |
| cur_shape = self.shape |
| err_str = 'operands could not be broadcast together with remapped shapes' \ |
| '[original->remapped]: {} and requested shape {}'.format(cur_shape, shape) |
| if len(shape) < len(cur_shape): |
| raise ValueError(err_str) |
| cur_shape = (1,) * (len(shape) - len(cur_shape)) + cur_shape |
| cur_shape_arr = np.array(cur_shape) |
| broadcasting_axes = np.nonzero(cur_shape_arr != np.array(shape)) |
| if (cur_shape_arr[broadcasting_axes] != 1).any(): |
| raise ValueError(err_str) |
| if cur_shape != self.shape: |
| return broadcast_to(self.reshape(cur_shape), shape=shape) |
| else: |
| return broadcast_to(self, shape=tuple(shape)) |
| # pylint: enable= undefined-variable |
| |
| def wait_to_read(self): |
| """Waits until all previous write operations on the current array are finished. |
| |
| This method guarantees that all previous write operations that pushed |
| into the backend engine for execution are actually finished. |
| |
| Examples |
| -------- |
| >>> import time |
| >>> tic = time.time() |
| >>> a = mx.nd.ones((1000,1000)) |
| >>> b = mx.nd.dot(a, a) |
| >>> print(time.time() - tic) # doctest: +SKIP |
| 0.003854036331176758 |
| >>> b.wait_to_read() |
| >>> print(time.time() - tic) # doctest: +SKIP |
| 0.0893700122833252 |
| """ |
| check_call(_LIB.MXNDArrayWaitToRead(self.handle)) |
| |
| |
| @property |
| def ndim(self): |
| """Returns the number of dimensions of this array |
| |
| Examples |
| -------- |
| >>> x = mx.nd.array([1, 2, 3, 4]) |
| >>> x.ndim |
| 1 |
| >>> x = mx.nd.array([[1, 2], |
| [3, 4]]) |
| >>> x.ndim |
| 2 |
| """ |
| return len(self.shape) |
| |
| @property |
| def shape(self): |
| """Tuple of array dimensions. |
| |
| Examples |
| -------- |
| >>> x = mx.nd.array([1, 2, 3, 4]) |
| >>> x.shape |
| (4L,) |
| >>> y = mx.nd.zeros((2, 3, 4)) |
| >>> y.shape |
| (2L, 3L, 4L) |
| """ |
| ndim = mx_uint() |
| pdata = ctypes.POINTER(mx_uint)() |
| check_call(_LIB.MXNDArrayGetShape( |
| self.handle, ctypes.byref(ndim), ctypes.byref(pdata))) |
| return tuple(pdata[:ndim.value]) |
| |
| @property |
| def size(self): |
| """Number of elements in the array. |
| |
| Equivalent to the product of the array’s dimensions. |
| |
| Examples |
| -------- |
| >>> import numpy as np |
| >>> x = mx.nd.zeros((3, 5, 2)) |
| >>> x.size |
| 30 |
| >>> np.prod(x.shape) |
| 30 |
| """ |
| return np.prod(self.shape) |
| |
| @property |
| def context(self): |
| """Device context of the array. |
| |
| Examples |
| -------- |
| >>> x = mx.nd.array([1, 2, 3, 4]) |
| >>> x.context |
| cpu(0) |
| >>> type(x.context) |
| <class 'mxnet.context.Context'> |
| >>> y = mx.nd.zeros((2,3), mx.gpu(0)) |
| >>> y.context |
| gpu(0) |
| """ |
| dev_typeid = ctypes.c_int() |
| dev_id = ctypes.c_int() |
| check_call(_LIB.MXNDArrayGetContext( |
| self.handle, ctypes.byref(dev_typeid), ctypes.byref(dev_id))) |
| return Context(Context.devtype2str[dev_typeid.value], dev_id.value) |
| |
| @property |
| def dtype(self): |
| """Data-type of the array’s elements. |
| |
| Returns |
| ------- |
| numpy.dtype |
| This NDArray's data type. |
| |
| Examples |
| -------- |
| >>> x = mx.nd.zeros((2,3)) |
| >>> x.dtype |
| <type 'numpy.float32'> |
| >>> y = mx.nd.zeros((2,3), dtype='int32') |
| >>> y.dtype |
| <type 'numpy.int32'> |
| """ |
| mx_dtype = ctypes.c_int() |
| check_call(_LIB.MXNDArrayGetDType( |
| self.handle, ctypes.byref(mx_dtype))) |
| return _DTYPE_MX_TO_NP[mx_dtype.value] |
| |
| @property |
| # pylint: disable= invalid-name, undefined-variable |
| def T(self): |
| """Returns a copy of the array with axes transposed. |
| |
| Equivalent to ``mx.nd.transpose(self)`` except that |
| self is returned if ``self.ndim < 2``. |
| |
| Unlike ``numpy.ndarray.T``, this function returns a copy |
| rather than a view of the array unless ``self.ndim < 2``. |
| |
| Examples |
| -------- |
| >>> x = mx.nd.arange(0,6).reshape((2,3)) |
| >>> x.asnumpy() |
| array([[ 0., 1., 2.], |
| [ 3., 4., 5.]], dtype=float32) |
| >>> x.T.asnumpy() |
| array([[ 0., 3.], |
| [ 1., 4.], |
| [ 2., 5.]], dtype=float32) |
| |
| """ |
| if len(self.shape) < 2: |
| return self |
| return transpose(self) |
| # pylint: enable= invalid-name, undefined-variable |
| |
| def asnumpy(self): |
| """Returns a ``numpy.ndarray`` object with value copied from this array. |
| |
| Examples |
| -------- |
| >>> x = mx.nd.ones((2,3)) |
| >>> y = x.asnumpy() |
| >>> type(y) |
| <type 'numpy.ndarray'> |
| >>> y |
| array([[ 1., 1., 1.], |
| [ 1., 1., 1.]], dtype=float32) |
| >>> z = mx.nd.ones((2,3), dtype='int32') |
| >>> z.asnumpy() |
| array([[1, 1, 1], |
| [1, 1, 1]], dtype=int32) |
| """ |
| data = np.empty(self.shape, dtype=self.dtype) |
| check_call(_LIB.MXNDArraySyncCopyToCPU( |
| self.handle, |
| data.ctypes.data_as(ctypes.c_void_p), |
| ctypes.c_size_t(data.size))) |
| return data |
| |
| def asscalar(self): |
| """Returns a scalar whose value is copied from this array. |
| |
| This function is equivalent to ``self.asnumpy()[0]``. This NDArray must have shape (1,). |
| |
| Examples |
| -------- |
| >>> x = mx.nd.ones((1,), dtype='int32') |
| >>> x.asscalar() |
| 1 |
| >>> type(x.asscalar()) |
| <type 'numpy.int32'> |
| """ |
| if self.shape != (1,): |
| raise ValueError("The current array is not a scalar") |
| return self.asnumpy()[0] |
| |
| def astype(self, dtype): |
| """Returns a copy of the array after casting to a specified type. |
| |
| Parameters |
| ---------- |
| dtype : numpy.dtype or str |
| The type of the returned array. |
| |
| Examples |
| -------- |
| >>> x = mx.nd.zeros((2,3), dtype='float32') |
| >>> y = x.astype('int32') |
| >>> y.dtype |
| <type 'numpy.int32'> |
| """ |
| res = empty(self.shape, ctx=self.context, dtype=dtype) |
| self.copyto(res) |
| return res |
| |
| def copyto(self, other): |
| """Copies the value of this array to another array. |
| |
| If ``other`` is a ``NDArray`` object, then ``other.shape`` and |
| ``self.shape`` should be the same. This function copies the value from |
| ``self`` to ``other``. |
| |
| If ``other`` is a context, a new ``NDArray`` will be first created on |
| the target context, and the value of ``self`` is copied. |
| |
| Parameters |
| ---------- |
| other : NDArray or Context |
| The destination array or context. |
| |
| Returns |
| ------- |
| NDArray |
| The copied array. If ``other`` is an ``NDArray``, then the return value |
| and ``other`` will point to the same ``NDArray``. |
| |
| Examples |
| -------- |
| >>> x = mx.nd.ones((2,3)) |
| >>> y = mx.nd.zeros((2,3), mx.gpu(0)) |
| >>> z = x.copyto(y) |
| >>> z is y |
| True |
| >>> y.asnumpy() |
| array([[ 1., 1., 1.], |
| [ 1., 1., 1.]], dtype=float32) |
| >>> y.copyto(mx.gpu(0)) |
| <NDArray 2x3 @gpu(0)> |
| |
| """ |
| if isinstance(other, NDArray): |
| if other.handle is self.handle: |
| warnings.warn('You are attempting to copy an array to itself', RuntimeWarning) |
| return |
| return _internal._copyto(self, out=other) |
| elif isinstance(other, Context): |
| hret = NDArray(_new_alloc_handle(self.shape, other, True, self.dtype)) |
| return _internal._copyto(self, out=hret) |
| else: |
| raise TypeError('copyto does not support type ' + str(type(other))) |
| |
| def copy(self): |
| """Makes a copy of this ``NDArray``, keeping the same context. |
| |
| Returns |
| ------- |
| NDArray |
| The copied array |
| |
| Examples |
| -------- |
| >>> x = mx.nd.ones((2,3)) |
| >>> y = x.copy() |
| >>> y.asnumpy() |
| array([[ 1., 1., 1.], |
| [ 1., 1., 1.]], dtype=float32) |
| """ |
| return self.copyto(self.context) |
| |
| def as_in_context(self, context): |
| """Returns an array on the target device with the same value as this array. |
| |
| If the target context is the same as ``self.context``, then ``self`` is |
| returned. Otherwise, a copy is made. |
| |
| Parameters |
| ---------- |
| context : Context |
| The target context. |
| |
| Returns |
| ------- |
| NDArray |
| The target array. |
| |
| |
| Examples |
| -------- |
| >>> x = mx.nd.ones((2,3)) |
| >>> y = x.as_in_context(mx.cpu()) |
| >>> y is x |
| True |
| >>> z = x.as_in_context(mx.gpu(0)) |
| >>> z is x |
| False |
| """ |
| if self.context == context: |
| return self |
| return self.copyto(context) |
| |
| _init_ndarray_module(NDArray, "mxnet") |
| |
| def onehot_encode(indices, out): |
| """One-hot encoding indices into matrix out. |
| |
| Deprecated, use ``one_hot`` instead. |
| """ |
| # pylint: disable= no-member, protected-access |
| return _internal._onehot_encode(indices, out, out=out) |
| # pylint: enable= no-member, protected-access |
| |
| |
| def empty(shape, ctx=None, dtype=mx_real_t): |
| """Returns a new array of given shape and type, without initializing entries. |
| |
| Parameters |
| ---------- |
| shape : int or tuple of int |
| The shape of the empty array. |
| ctx : Context, optional |
| An optional device context (default is the current default context). |
| dtype : str or numpy.dtype, optional |
| An optional value type (default is `float32`). |
| |
| Returns |
| ------- |
| NDArray |
| A created array. |
| |
| Examples |
| -------- |
| >>> mx.nd.empty(1) |
| <NDArray 1 @cpu(0)> |
| >>> mx.nd.empty((1,2), mx.gpu(0)) |
| <NDArray 1x2 @gpu(0)> |
| >>> mx.nd.empty((1,2), mx.gpu(0), 'float16') |
| <NDArray 1x2 @gpu(0)> |
| """ |
| if isinstance(shape, int): |
| shape = (shape, ) |
| if ctx is None: |
| ctx = Context.default_ctx |
| return NDArray(handle=_new_alloc_handle(shape, ctx, False, dtype)) |
| |
| def zeros(shape, ctx=None, dtype=mx_real_t): |
| """Returns a new array filled with all zeros, with the given shape and type. |
| |
| Parameters |
| ---------- |
| shape : int or tuple of int |
| The shape of the empty array. |
| ctx : Context, optional |
| An optional device context (default is the current default context). |
| dtype : str or numpy.dtype, optional |
| An optional value type (default is `float32`). |
| |
| Returns |
| ------- |
| NDArray |
| A created array |
| |
| Examples |
| -------- |
| >>> mx.nd.zeros(1).asnumpy() |
| array([ 0.], dtype=float32) |
| >>> mx.nd.zeros((1,2), mx.gpu(0)) |
| <NDArray 1x2 @gpu(0)> |
| >>> mx.nd.zeros((1,2), mx.gpu(0), 'float16').asnumpy() |
| array([[ 0., 0.]], dtype=float16) |
| """ |
| if ctx is None: |
| ctx = Context.default_ctx |
| # pylint: disable= no-member, protected-access |
| return _internal._zeros(shape=shape, ctx=ctx, dtype=dtype) |
| # pylint: enable= no-member, protected-access |
| |
| def ones(shape, ctx=None, dtype=mx_real_t): |
| """Returns a new array filled with all ones, with the given shape and type. |
| |
| Parameters |
| ---------- |
| shape : int or tuple of int |
| The shape of the empty array. |
| ctx : Context, optional |
| An optional device context. |
| Defaults to the current default context (``mxnet.Context.default_ctx``). |
| dtype : str or numpy.dtype, optional |
| An optional value type (default is `float32`). |
| |
| Returns |
| ------- |
| NDArray |
| A new array of the specified shape filled with all ones. |
| |
| Examples |
| -------- |
| >>> mx.nd.ones(1).asnumpy() |
| array([ 1.], dtype=float32) |
| >>> mx.nd.ones((1,2), mx.gpu(0)) |
| <NDArray 1x2 @gpu(0)> |
| >>> mx.nd.ones((1,2), dtype='float16').asnumpy() |
| array([[ 1., 1.]], dtype=float16) |
| """ |
| if ctx is None: |
| ctx = Context.default_ctx |
| # pylint: disable= no-member, protected-access |
| return _internal._ones(shape=shape, ctx=ctx, dtype=dtype) |
| # pylint: enable= no-member, protected-access |
| |
| def full(shape, val, ctx=None, dtype=mx_real_t): |
| """Returns a new array of given shape and type, filled with the given value ``val``. |
| |
| Parameters |
| -------- |
| shape : int or tuple of int) |
| The shape of the empty array. |
| val : scalar |
| Fill value |
| ctx : Context, optional |
| An optional device context (default is the current default context). |
| dtype : str or numpy.dtype, optional |
| An optional value type (default is `float32`). |
| |
| Returns |
| ------- |
| NDArray |
| A created array |
| |
| Examples |
| -------- |
| >>> mx.nd.full(1, 2.0).asnumpy() |
| array([ 2.], dtype=float32) |
| >>> mx.nd.full((1, 2), 2.0, mx.gpu(0)) |
| <NDArray 1x2 @gpu(0)> |
| >>> mx.nd.full((1, 2), 2.0, dtype='float16').asnumpy() |
| array([[ 2., 2.]], dtype=float16) |
| """ |
| arr = empty(shape, ctx, dtype) |
| arr[:] = val |
| return arr |
| |
| |
| def array(source_array, ctx=None, dtype=None): |
| """Creates a new array from any object exposing the array interface. |
| |
| Parameters |
| ---------- |
| source_array : array_like |
| Any object exposing the array interface, an object whose ``__array__`` |
| method returns an array, or any (nested) sequence. |
| ctx : Context, optional |
| An optional device context (default is the current default context). |
| dtype : str or numpy.dtype, optional |
| |
| An optional value type. If the ``source_array`` is an NDArray, then defaults to |
| ``source_array.dtype``, otherwise default to ``float32``. |
| |
| Returns |
| ------- |
| NDArray |
| An ``NDArray`` array with the same contets as the ``source_array``. |
| |
| Examples |
| -------- |
| >>> import numpy as np |
| >>> mx.nd.array([1, 2, 3]) |
| <NDArray 3 @cpu(0)> |
| >>> mx.nd.array([[1, 2], [3, 4]]) |
| <NDArray 2x2 @cpu(0)> |
| >>> mx.nd.array(np.zeros((3,2))) |
| <NDArray 3x2 @cpu(0)> |
| >>> mx.nd.array(np.zeros((3,2)), mx.gpu(0)) |
| <NDArray 3x2 @gpu(0)> |
| """ |
| if isinstance(source_array, NDArray): |
| dtype = source_array.dtype if dtype is None else dtype |
| else: |
| dtype = mx_real_t if dtype is None else dtype |
| if not isinstance(source_array, np.ndarray): |
| try: |
| source_array = np.array(source_array, dtype=dtype) |
| except: |
| raise TypeError('source_array must be array like object') |
| arr = empty(source_array.shape, ctx, dtype) |
| arr[:] = source_array |
| return arr |
| |
| |
| # pylint: disable= no-member, protected-access, too-many-arguments |
| def arange(start, stop=None, step=1.0, repeat=1, ctx=None, dtype=mx_real_t): |
| """Returns evenly spaced values within a given interval. |
| |
| Values are generated within the half-open interval [start, stop). In other |
| words, the interval includes start but excludes stop. For integer |
| arguments, the function is equivalent to the built-in Python function ``range`` |
| and to ``numpy.arange``, but returns an ``NDArray``. |
| |
| Parameters |
| ---------- |
| start : int, optional |
| An optional start of interval, the default value is 0. |
| stop : int |
| The end of interval. |
| step : int, optional |
| A optional spacing between values, the default value is 1. |
| repeat : int, optional |
| The repeating time of all elements. |
| ctx : Context, optional |
| An optional device context (default is the current default context) |
| dtype : str or numpy.dtype, optional |
| An optional value type (default is `float32`). |
| |
| dtype : str or numpy.dtype, optional |
| The value type of the NDArray, default to np.float32. |
| |
| Returns |
| ------- |
| NDArray |
| The created NDArray |
| |
| Examples |
| -------- |
| >>> mx.nd.arange(3).asnumpy() |
| array([ 0., 1., 2.], dtype=float32) |
| >>> mx.nd.arange(2,6).asnumpy() |
| array([ 2., 3., 4., 5.], dtype=float32) |
| >>> mx.nd.arange(2,6,2).asnumpy() |
| array([ 2., 4.], dtype=float32) |
| >>> mx.nd.arange(2,6,step=2).asnumpy() |
| array([ 2., 4.], dtype=float32) |
| >>> mx.nd.arange(2,6,step=2,repeat=2).asnumpy() |
| array([ 2., 2., 4., 4.], dtype=float32) |
| >>> mx.nd.arange(2,6,step=2,repeat=3).asnumpy() |
| array([ 2., 2., 2., 4., 4., 4.], dtype=float32) |
| >>> mx.nd.arange(2,6,step=2,repeat=3,dtype='int32').asnumpy() |
| array([2, 2, 2, 4, 4, 4], dtype=int32) |
| """ |
| if ctx is None: |
| ctx = Context.default_ctx |
| return _internal._arange(start=start, stop=stop, step=step, repeat=repeat, |
| dtype=dtype, ctx=str(ctx)) |
| # pylint: enable= no-member, protected-access, too-many-arguments |
| |
| #pylint: disable= too-many-arguments, no-member, protected-access |
| def _ufunc_helper(lhs, rhs, fn_array, fn_scalar, lfn_scalar, rfn_scalar=None): |
| """ Helper function for element-wise operation. |
| The function will perform numpy-like broadcasting if needed and call different functions. |
| |
| Parameters |
| -------- |
| lhs : NDArray or numeric value |
| Left-hand side operand. |
| |
| rhs : NDArray or numeric value |
| Right-hand operand, |
| |
| fn_array : function |
| Function to be called if both lhs and rhs are of ``NDArray`` type. |
| |
| fn_scalar : function |
| Function to be called if both lhs and rhs are numeric values. |
| |
| lfn_scalar : function |
| Function to be called if lhs is ``NDArray`` while rhs is numeric value |
| |
| rfn_scalar : function |
| Function to be called if lhs is numeric value while rhs is ``NDArray``; |
| if none is provided, then the function is commutative, so rfn_scalar is equal to lfn_scalar |
| |
| Returns |
| -------- |
| NDArray |
| result array |
| """ |
| if isinstance(lhs, numeric_types): |
| if isinstance(rhs, numeric_types): |
| return fn_scalar(lhs, rhs) |
| else: |
| if rfn_scalar is None: |
| # commutative function |
| return lfn_scalar(rhs, float(lhs)) |
| else: |
| return rfn_scalar(rhs, float(lhs)) |
| elif isinstance(rhs, numeric_types): |
| return lfn_scalar(lhs, float(rhs)) |
| elif isinstance(rhs, NDArray): |
| return fn_array(lhs, rhs) |
| else: |
| raise TypeError('type %s not supported' % str(type(rhs))) |
| #pylint: enable= too-many-arguments, no-member, protected-access |
| |
| def add(lhs, rhs): |
| """Add arguments, element-wise with broadcasting. |
| |
| Equivalent to ``lhs + rhs`` |
| |
| Parameters |
| ---------- |
| lhs : scalar or array |
| rhs : scalar or array |
| The arrays to be added. If ``lhs.shape != rhs.shape``, they must be |
| broadcastable to a common shape |
| |
| Returns |
| ------- |
| NDArray |
| The sum of lhs and rhs, element-wise. |
| |
| Examples |
| -------- |
| >>> x = mx.nd.ones((2,3)) |
| >>> y = mx.nd.arange(2).reshape((2,1)) |
| >>> z = mx.nd.arange(2).reshape((1,2)) |
| >>> (x+2).asnumpy() |
| array([[ 3., 3., 3.], |
| [ 3., 3., 3.]], dtype=float32) |
| >>> (x+y).asnumpy() |
| array([[ 1., 1., 1.], |
| [ 2., 2., 2.]], dtype=float32) |
| >>> (z + y).asnumpy() |
| array([[ 0., 1.], |
| [ 1., 2.]], dtype=float32) |
| """ |
| # pylint: disable= no-member, protected-access |
| return _ufunc_helper( |
| lhs, |
| rhs, |
| broadcast_add, |
| operator.add, |
| _internal._plus_scalar, |
| None) |
| # pylint: enable= no-member, protected-access |
| |
| def subtract(lhs, rhs): |
| """Subtracts arguments element-wise with broadcasting. |
| |
| Equivalent to ``lhs - rhs``. |
| |
| Parameters |
| ---------- |
| lhs : scalar or array |
| rhs : scalar or array |
| The arrays to be added. If ``lhs.shape != rhs.shape``, they must be |
| broadcastable to a common shape. |
| |
| Returns |
| ------- |
| NDArray |
| The difference of lhs and rhs, element-wise. |
| |
| Examples |
| -------- |
| >>> x = mx.nd.ones((2,3)) |
| >>> y = mx.nd.arange(2).reshape((2,1)) |
| >>> z = mx.nd.arange(2).reshape((1,2)) |
| >>> (x-2).asnumpy() |
| array([[-1., -1., -1.], |
| [-1., -1., -1.]], dtype=float32) |
| >>> (x-y).asnumpy() |
| array([[ 1., 1., 1.], |
| [ 0., 0., 0.]], dtype=float32) |
| >>> (z-y).asnumpy() |
| array([[ 0., 1.], |
| [-1., 0.]], dtype=float32) |
| """ |
| # pylint: disable= no-member, protected-access |
| return _ufunc_helper( |
| lhs, |
| rhs, |
| broadcast_sub, |
| operator.sub, |
| _internal._minus_scalar, |
| _internal._rminus_scalar) |
| # pylint: enable= no-member, protected-access |
| |
| def multiply(lhs, rhs): |
| """Multiplies arguments element-wise with broadcasting. |
| |
| Equivalent to ``lhs * rhs``. |
| |
| Parameters |
| ---------- |
| lhs : scalar or array |
| rhs : scalar or array |
| The arrays to be added. If ``lhs.shape != rhs.shape``, they must be |
| broadcastable to a common shape. |
| |
| Returns |
| ------- |
| NDArray |
| The multiplication of lhs and rhs, element-wise. |
| |
| Examples |
| -------- |
| >>> x = mx.nd.ones((2,3)) |
| >>> y = mx.nd.arange(2).reshape((2,1)) |
| >>> z = mx.nd.arange(2).reshape((1,2)) |
| >>> (x*2).asnumpy() |
| array([[ 2., 2., 2.], |
| [ 2., 2., 2.]], dtype=float32) |
| >>> (x*y).asnumpy() |
| array([[ 0., 0., 0.], |
| [ 1., 1., 1.]], dtype=float32) |
| >>> (z*y).asnumpy() |
| array([[ 0., 0.], |
| [ 0., 1.]], dtype=float32) |
| """ |
| # pylint: disable= no-member, protected-access |
| return _ufunc_helper( |
| lhs, |
| rhs, |
| broadcast_mul, |
| operator.mul, |
| _internal._mul_scalar, |
| None) |
| # pylint: enable= no-member, protected-access |
| |
| def divide(lhs, rhs): |
| """Divides arguments element-wise with broadcasting. |
| |
| Equivalent to ``lhs / rhs``. |
| |
| Parameters |
| ---------- |
| lhs : scalar or array |
| rhs : scalar or array |
| The arrays to be added. If ``lhs.shape != rhs.shape``, they must be |
| broadcastable to a common shape. |
| |
| Returns |
| ------- |
| NDArray |
| The quotient of ``lhs/rhs``, element-wise. |
| |
| Examples |
| -------- |
| >>> x = mx.nd.ones((2,3)) |
| >>> y = mx.nd.arange(2).reshape((2,1)) |
| >>> z = mx.nd.arange(2).reshape((1,2)) |
| >>> x/2 |
| <NDArray 2x3 @cpu(0)> |
| >>> (x/2).asnumpy() |
| array([[ 0.5, 0.5, 0.5], |
| [ 0.5, 0.5, 0.5]], dtype=float32) |
| >>> (x/y).asnumpy() |
| array([[ inf, inf, inf], |
| [ 1., 1., 1.]], dtype=float32) |
| >>> (y/z).asnumpy() |
| array([[ nan, 0.], |
| [ inf, 1.]], dtype=float32) |
| """ |
| # pylint: disable= no-member, protected-access |
| return _ufunc_helper( |
| lhs, |
| rhs, |
| broadcast_div, |
| operator.truediv, |
| _internal._div_scalar, |
| _internal._rdiv_scalar) |
| # pylint: enable= no-member, protected-access |
| |
| def power(base, exp): |
| """First array elements raised to powers from second array, element-wise |
| with broadcasting. |
| |
| Equivalent to ``base ** exp``. |
| |
| Parameters |
| ---------- |
| base : scalar or NDArray |
| exp : scalar or NDArray |
| The arrays to be added. If ``base.shape != exp.shape``, they must be |
| broadcastable to a common shape. |
| |
| Returns |
| -------- |
| NDArray |
| The bases in x raised to the exponents in y. |
| |
| Examples |
| -------- |
| >>> x = mx.nd.ones((2,3))*2 |
| >>> y = mx.nd.arange(1,3).reshape((2,1)) |
| >>> z = mx.nd.arange(1,3).reshape((2,1)) |
| >>> (x**2).asnumpy() |
| array([[ 4., 4., 4.], |
| [ 4., 4., 4.]], dtype=float32) |
| >>> (x**y).asnumpy() |
| array([[ 2., 2., 2.], |
| [ 4., 4., 4.]], dtype=float32) |
| >>> (z**y).asnumpy() |
| array([[ 1.], |
| [ 4.]], dtype=float32) |
| """ |
| # pylint: disable= no-member, protected-access |
| return _ufunc_helper( |
| base, |
| exp, |
| broadcast_power, |
| operator.pow, |
| _internal._power_scalar, |
| _internal._rpower_scalar) |
| # pylint: enable= no-member, protected-access |
| |
| def maximum(lhs, rhs): |
| """Element-wise maximum of array elements with broadcasting. |
| |
| Parameters |
| ---------- |
| lhs : scalar or array |
| rhs : scalar or array |
| The arrays to be added. If ``lhs.shape != rhs.shape``, they must be |
| broadcastable to a common shape. |
| |
| Returns |
| ------- |
| NDArray |
| The maximum of lhs and rhs, element-wise. |
| |
| Examples |
| -------- |
| >>> x = mx.nd.ones((2,3)) |
| >>> y = mx.nd.arange(2).reshape((2,1)) |
| >>> z = mx.nd.arange(2).reshape((1,2)) |
| >>> mx.nd.maximum(x, 2).asnumpy() |
| array([[ 2., 2., 2.], |
| [ 2., 2., 2.]], dtype=float32) |
| >>> mx.nd.maximum(x, y).asnumpy() |
| array([[ 1., 1., 1.], |
| [ 1., 1., 1.]], dtype=float32) |
| >>> mx.nd.maximum(y, z).asnumpy() |
| array([[ 0., 1.], |
| [ 1., 1.]], dtype=float32) |
| """ |
| # pylint: disable= no-member, protected-access |
| return _ufunc_helper( |
| lhs, |
| rhs, |
| broadcast_maximum, |
| lambda x, y: x if x > y else y, |
| _internal._maximum_scalar, |
| None) |
| # pylint: enable= no-member, protected-access |
| |
| def minimum(lhs, rhs): |
| """Element-wise minimum of array elements with broadcasting. |
| |
| Parameters |
| ---------- |
| lhs : scalar or array |
| rhs : scalar or array |
| The arrays to be added. If ``lhs.shape != rhs.shape``, they must be |
| broadcastable to a common shape. |
| |
| Returns |
| ------- |
| NDArray |
| The minimum of lhs and rhs, element-wise. |
| |
| Examples |
| -------- |
| >>> x = mx.nd.ones((2,3)) |
| >>> y = mx.nd.arange(2).reshape((2,1)) |
| >>> z = mx.nd.arange(2).reshape((1,2)) |
| >>> mx.nd.minimum(x, 2).asnumpy() |
| array([[ 1., 1., 1.], |
| [ 1., 1., 1.]], dtype=float32) |
| >>> mx.nd.minimum(x, y).asnumpy() |
| array([[ 0., 0., 0.], |
| [ 1., 1., 1.]], dtype=float32) |
| >>> mx.nd.minimum(z, y).asnumpy() |
| array([[ 0., 0.], |
| [ 0., 1.]], dtype=float32) |
| """ |
| # pylint: disable= no-member, protected-access |
| return _ufunc_helper( |
| lhs, |
| rhs, |
| broadcast_minimum, |
| lambda x, y: x if x < y else y, |
| _internal._minimum_scalar, |
| None) |
| # pylint: enable= no-member, protected-access |
| |
| def equal(lhs, rhs): |
| """Returns (lhs == rhs), element-wise with broadcasting. |
| |
| Equivalent to ``lhs == rhs`` |
| |
| Parameters |
| ---------- |
| lhs : scalar or array |
| rhs : scalar or array |
| The arrays to be added. If ``lhs.shape != rhs.shape``, they must be |
| broadcastable to a common shape. |
| |
| Returns |
| ------- |
| NDArray |
| For each element in lhs, rhs, return True if lhs is equal to rhs and False otherwise. |
| |
| Examples |
| -------- |
| >>> x = mx.nd.ones((2,3)) |
| >>> y = mx.nd.arange(2).reshape((2,1)) |
| >>> z = mx.nd.arange(2).reshape((1,2)) |
| >>> (x == 1).asnumpy() |
| array([[ 1., 1., 1.], |
| [ 1., 1., 1.]], dtype=float32) |
| >>> (x == y).asnumpy() |
| array([[ 0., 0., 0.], |
| [ 1., 1., 1.]], dtype=float32) |
| >>> (z == y).asnumpy() |
| array([[ 1., 0.], |
| [ 0., 1.]], dtype=float32) |
| """ |
| # pylint: disable= no-member, protected-access |
| return _ufunc_helper( |
| lhs, |
| rhs, |
| broadcast_equal, |
| lambda x, y: 1 if x == y else 0, |
| _internal._equal_scalar, |
| None) |
| # pylint: enable= no-member, protected-access |
| |
| def not_equal(lhs, rhs): |
| """Returns (lhs != rhs), element-wise with broadcasting. |
| |
| Equivalent to ``lhs != rhs``. |
| |
| Parameters |
| ---------- |
| lhs : scalar or array |
| rhs : scalar or array |
| The arrays to be added. If ``lhs.shape != rhs.shape``, they must be |
| broadcastable to a common shape, |
| |
| Returns |
| ------- |
| NDArray |
| For each element in lhs, rhs, return True if lhs is not equal to rhs and False otherwise. |
| |
| Examples |
| -------- |
| >>> x = mx.nd.ones((2,3)) |
| >>> y = mx.nd.arange(2).reshape((2,1)) |
| >>> z = mx.nd.arange(2).reshape((1,2)) |
| >>> (z == y).asnumpy() |
| array([[ 1., 0.], |
| [ 0., 1.]], dtype=float32) |
| >>> (x != 1).asnumpy() |
| array([[ 0., 0., 0.], |
| [ 0., 0., 0.]], dtype=float32) |
| >>> (x != y).asnumpy() |
| array([[ 1., 1., 1.], |
| [ 0., 0., 0.]], dtype=float32) |
| >>> (z != y).asnumpy() |
| array([[ 0., 1.], |
| [ 1., 0.]], dtype=float32) |
| """ |
| # pylint: disable= no-member, protected-access |
| return _ufunc_helper( |
| lhs, |
| rhs, |
| broadcast_not_equal, |
| lambda x, y: 1 if x != y else 0, |
| _internal._not_equal_scalar, |
| None) |
| # pylint: enable= no-member, protected-access |
| |
| def greater(lhs, rhs): |
| """Returns (lhs > rhs), element-wise with broadcasting. |
| |
| Equivalent to ``lhs > rhs``. |
| |
| Parameters |
| ---------- |
| lhs : scalar or array |
| rhs : scalar or array |
| The arrays to be added. If ``lhs.shape != rhs.shape``, they must be |
| broadcastable to a common shape. |
| |
| Returns |
| ------- |
| NDArray |
| For each element in lhs, rhs, return True if lhs is greater than rhs and False otherwise. |
| |
| Examples |
| -------- |
| >>> x = mx.nd.ones((2,3)) |
| >>> y = mx.nd.arange(2).reshape((2,1)) |
| >>> z = mx.nd.arange(2).reshape((1,2)) |
| >>> (x > 1).asnumpy() |
| array([[ 0., 0., 0.], |
| [ 0., 0., 0.]], dtype=float32) |
| >>> (x > y).asnumpy() |
| array([[ 1., 1., 1.], |
| [ 0., 0., 0.]], dtype=float32) |
| >>> (z > y).asnumpy() |
| array([[ 0., 1.], |
| [ 0., 0.]], dtype=float32) |
| """ |
| # pylint: disable= no-member, protected-access |
| return _ufunc_helper( |
| lhs, |
| rhs, |
| broadcast_greater, |
| lambda x, y: 1 if x > y else 0, |
| _internal._greater_scalar, |
| _internal._lesser_scalar) |
| # pylint: enable= no-member, protected-access |
| |
| def greater_equal(lhs, rhs): |
| """Returns (lhs >= rhs), element-wise with broadcasting. |
| |
| Equivalent to ``lhs >= rhs``. |
| |
| Parameters |
| ---------- |
| lhs : scalar or array |
| rhs : scalar or array |
| The arrays to be added. If ``lhs.shape != rhs.shape``, they must be |
| broadcastable to a common shape. |
| |
| Returns |
| ------- |
| NDArray |
| For each element in lhs, rhs, return True if lhs is greater equal than |
| rhs and False otherwise. |
| |
| Examples |
| -------- |
| >>> x = mx.nd.ones((2,3)) |
| >>> y = mx.nd.arange(2).reshape((2,1)) |
| >>> z = mx.nd.arange(2).reshape((1,2)) |
| >>> (x >= 1).asnumpy() |
| array([[ 1., 1., 1.], |
| [ 1., 1., 1.]], dtype=float32) |
| >>> (x >= y).asnumpy() |
| array([[ 1., 1., 1.], |
| [ 1., 1., 1.]], dtype=float32) |
| >>> (z >= y).asnumpy() |
| array([[ 1., 1.], |
| [ 0., 1.]], dtype=float32) |
| """ |
| # pylint: disable= no-member, protected-access |
| return _ufunc_helper( |
| lhs, |
| rhs, |
| broadcast_greater_equal, |
| lambda x, y: 1 if x >= y else 0, |
| _internal._greater_equal_scalar, |
| _internal._lesser_equal_scalar) |
| # pylint: enable= no-member, protected-access |
| |
| def lesser(lhs, rhs): |
| """Returns (lhs < rhs), element-wise with broadcasting. |
| |
| Equivalent to ``lhs < rhs``. |
| |
| Parameters |
| ---------- |
| lhs : scalar or array |
| rhs : scalar or array |
| The arrays to be added. If ``lhs.shape != rhs.shape``, they must be |
| broadcastable to a common shape. |
| |
| Returns |
| ------- |
| NDArray |
| For each element in lhs, rhs, return True if lhs is lesser than rhs and False otherwise. |
| |
| Examples |
| -------- |
| >>> x = mx.nd.ones((2,3)) |
| >>> y = mx.nd.arange(2).reshape((2,1)) |
| >>> z = mx.nd.arange(2).reshape((1,2)) |
| >>> (x < 1).asnumpy() |
| array([[ 0., 0., 0.], |
| [ 0., 0., 0.]], dtype=float32) |
| >>> (x < y).asnumpy() |
| array([[ 0., 0., 0.], |
| [ 0., 0., 0.]], dtype=float32) |
| >>> (z < y).asnumpy() |
| array([[ 0., 0.], |
| [ 1., 0.]], dtype=float32) |
| """ |
| # pylint: disable= no-member, protected-access |
| return _ufunc_helper( |
| lhs, |
| rhs, |
| broadcast_lesser, |
| lambda x, y: 1 if x < y else 0, |
| _internal._lesser_scalar, |
| _internal._greater_scalar) |
| # pylint: enable= no-member, protected-access |
| |
| |
| def lesser_equal(lhs, rhs): |
| """Returns (lhs <= rhs), element-wise with broadcasting. |
| |
| Equivalent to ``lhs <= rhs``. |
| |
| Parameters |
| ---------- |
| lhs : scalar or array |
| rhs : scalar or array |
| The arrays to be added. If ``lhs.shape != rhs.shape``, they must be |
| broadcastable to a common shape. |
| |
| Returns |
| ------- |
| NDArray |
| For each element in lhs, rhs, return True if lhs is lesser equal than |
| rhs and False otherwise. |
| |
| Examples |
| -------- |
| >>> x = mx.nd.ones((2,3)) |
| >>> y = mx.nd.arange(2).reshape((2,1)) |
| >>> z = mx.nd.arange(2).reshape((1,2)) |
| >>> (x <= 1).asnumpy() |
| array([[ 1., 1., 1.], |
| [ 1., 1., 1.]], dtype=float32) |
| >>> (x <= y).asnumpy() |
| array([[ 0., 0., 0.], |
| [ 1., 1., 1.]], dtype=float32) |
| >>> (z <= y).asnumpy() |
| array([[ 1., 0.], |
| [ 1., 1.]], dtype=float32) |
| """ |
| # pylint: disable= no-member, protected-access |
| return _ufunc_helper( |
| lhs, |
| rhs, |
| broadcast_lesser_equal, |
| lambda x, y: 1 if x <= y else 0, |
| _internal._lesser_equal_scalar, |
| _internal._greater_equal_scalar) |
| # pylint: enable= no-member, protected-access |
| |
| def true_divide(lhs, rhs): |
| """Same as ``divide``. |
| """ |
| return divide(lhs, rhs) |
| |
| def negative(arr): |
| """Numerical negative, element-wise. |
| |
| Equals ``-arr`` |
| |
| Parameters |
| ---------- |
| arr : NDArray |
| The input array |
| |
| Returns |
| ------- |
| NDArray |
| ``-arr`` |
| |
| Examples |
| -------- |
| >>> x = mx.nd.ones((2,3)) |
| >>> (-x).asnumpy() |
| array([[-1., -1., -1.], |
| [-1., -1., -1.]], dtype=float32) |
| """ |
| return multiply(arr, -1.0) |
| |
| def load(fname): |
| """Load array from file. |
| |
| See more details in ``save``. |
| |
| Parameters |
| ---------- |
| fname : str |
| The filename. |
| |
| Returns |
| ------- |
| list of NDArray or dict of str to NDArray |
| Loaded data. |
| """ |
| if not isinstance(fname, string_types): |
| raise TypeError('fname required to be a string') |
| out_size = mx_uint() |
| out_name_size = mx_uint() |
| handles = ctypes.POINTER(NDArrayHandle)() |
| names = ctypes.POINTER(ctypes.c_char_p)() |
| check_call(_LIB.MXNDArrayLoad(c_str(fname), |
| ctypes.byref(out_size), |
| ctypes.byref(handles), |
| ctypes.byref(out_name_size), |
| ctypes.byref(names))) |
| if out_name_size.value == 0: |
| return [NDArray(NDArrayHandle(handles[i])) for i in range(out_size.value)] |
| else: |
| assert out_name_size.value == out_size.value |
| return dict( |
| (py_str(names[i]), NDArray(NDArrayHandle(handles[i]))) for i in range(out_size.value)) |
| |
| |
| def save(fname, data): |
| """Save a list of arrays of a str->array dict into file. |
| |
| Examples of filenames: |
| |
| - ``/path/to/file`` |
| - ``s3://my-bucket/path/to/file`` (if compiled with AWS S3 supports) |
| - ``hdfs://path/to/file`` (if compiled with HDFS supports) |
| |
| Parameters |
| ---------- |
| fname : str |
| The filename. |
| data : list of ``NDArray` or dict of str to ``NDArray`` |
| The data for saving. |
| |
| Examples |
| -------- |
| >>> x = mx.nd.zeros((2,3)) |
| >>> y = mx.nd.ones((1,4)) |
| >>> mx.nd.save('my_list', [x,y]) |
| >>> mx.nd.save('my_dict', {'x':x, 'y':y}) |
| >>> mx.nd.load('my_list') |
| [<NDArray 2x3 @cpu(0)>, <NDArray 1x4 @cpu(0)>] |
| >>> mx.nd.load('my_dict') |
| {'y': <NDArray 1x4 @cpu(0)>, 'x': <NDArray 2x3 @cpu(0)>} |
| """ |
| handles = [] |
| if isinstance(data, dict): |
| keys = [] |
| for key, val in data.items(): |
| if not isinstance(key, string_types): |
| raise TypeError('save only accept dict str->NDArray or list of NDArray') |
| if not isinstance(val, NDArray): |
| raise TypeError('save only accept dict str->NDArray or list of NDArray') |
| keys.append(c_str(key)) |
| handles.append(val.handle) |
| keys = c_array(ctypes.c_char_p, keys) |
| else: |
| for val in data: |
| if not isinstance(val, NDArray): |
| raise TypeError('save only accept dict str->NDArray or list of NDArray') |
| handles.append(val.handle) |
| keys = None |
| check_call(_LIB.MXNDArraySave(c_str(fname), |
| mx_uint(len(handles)), |
| c_array(NDArrayHandle, handles), |
| keys)) |
| |
| |
| def concatenate(arrays, axis=0, always_copy=True): |
| """DEPRECATED, use ``concat`` instead |
| |
| Parameters |
| ---------- |
| arrays : list of `NDArray` |
| Arrays to be concatenate. They must have identical shape except |
| the first dimension. They also must have the same data type. |
| axis : int |
| The axis along which to concatenate. |
| always_copy : bool |
| Default `True`. When not `True`, if the arrays only contain one |
| `NDArray`, that element will be returned directly, avoid copying. |
| |
| Returns |
| ------- |
| NDArray |
| An `NDArray` that lives on the same context as `arrays[0].context`. |
| """ |
| assert isinstance(arrays, list) |
| assert len(arrays) > 0 |
| assert isinstance(arrays[0], NDArray) |
| |
| if not always_copy and len(arrays) == 1: |
| return arrays[0] |
| |
| shape_axis = arrays[0].shape[axis] |
| shape_rest1 = arrays[0].shape[0:axis] |
| shape_rest2 = arrays[0].shape[axis+1:] |
| dtype = arrays[0].dtype |
| for arr in arrays[1:]: |
| shape_axis += arr.shape[axis] |
| assert shape_rest1 == arr.shape[0:axis] |
| assert shape_rest2 == arr.shape[axis+1:] |
| assert dtype == arr.dtype |
| ret_shape = shape_rest1 + (shape_axis,) + shape_rest2 |
| ret = empty(ret_shape, ctx=arrays[0].context, dtype=dtype) |
| |
| idx = 0 |
| begin = [0 for _ in ret_shape] |
| end = list(ret_shape) |
| for arr in arrays: |
| if axis == 0: |
| ret[idx:idx+arr.shape[0]] = arr |
| else: |
| begin[axis] = idx |
| end[axis] = idx+arr.shape[axis] |
| # pylint: disable=no-member,protected-access |
| _internal._crop_assign(ret, arr, out=ret, |
| begin=tuple(begin), |
| end=tuple(end)) |
| # pylint: enable=no-member,protected-access |
| idx += arr.shape[axis] |
| |
| return ret |
| |
| def imdecode(str_img, clip_rect=(0, 0, 0, 0), out=None, index=0, channels=3, mean=None): |
| """DEPRECATED, use mx.img instead |
| |
| Parameters |
| ---------- |
| str_img : str |
| Binary image data |
| clip_rect : iterable of 4 int |
| Clip decoded image to rectangle (x0, y0, x1, y1). |
| out : NDArray |
| Output buffer. Can be 3 dimensional (c, h, w) or 4 dimensional (n, c, h, w). |
| index : int |
| Output decoded image to i-th slice of 4 dimensional buffer. |
| channels : int |
| Number of channels to output. Decode to grey scale when channels = 1. |
| mean : NDArray |
| Subtract mean from decode image before outputing. |
| """ |
| # pylint: disable= no-member, protected-access, too-many-arguments |
| if mean is None: |
| mean = NDArray(_new_empty_handle()) |
| if out is None: |
| return _internal._imdecode(mean, index, |
| clip_rect[0], |
| clip_rect[1], |
| clip_rect[2], |
| clip_rect[3], |
| channels, |
| len(str_img), |
| str_img=str_img) |
| else: |
| return _internal._imdecode(mean, index, |
| clip_rect[0], |
| clip_rect[1], |
| clip_rect[2], |
| clip_rect[3], |
| channels, |
| len(str_img), |
| str_img=str_img, |
| out=out) |
| |
| # from .base import add_fileline_to_docstring |
| # add_fileline_to_docstring(__name__) |