[GitHub] [incubator-mxnet] haojin2 commented on a change in pull request #17084: [numpy] add op median

2019-12-15 Thread GitBox
haojin2 commented on a change in pull request #17084: [numpy] add op median
URL: https://github.com/apache/incubator-mxnet/pull/17084#discussion_r358090250
 
 

 ##
 File path: python/mxnet/numpy/multiarray.py
 ##
 @@ -5340,6 +5340,59 @@ def swapaxes(a, axis1, axis2):
 return _npi.swapaxes(a, dim1=axis1, dim2=axis2)
 
 
+@set_module('mxnet.numpy')
+def median(a, axis=None, out=None, keepdims=False):
+r"""
+Compute the median along the specified axis.
 
 Review comment:
   get rid of the 4 extra blank spaces.


This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


With regards,
Apache Git Services


[GitHub] [incubator-mxnet] haojin2 commented on a change in pull request #17084: [numpy] add op median

2019-12-15 Thread GitBox
haojin2 commented on a change in pull request #17084: [numpy] add op median
URL: https://github.com/apache/incubator-mxnet/pull/17084#discussion_r358090445
 
 

 ##
 File path: python/mxnet/symbol/numpy/_symbol.py
 ##
 @@ -3429,6 +3429,59 @@ def get_list(arrays):
 return _npi.stack(*arrays, axis=axis, out=out)
 
 
+@set_module('mxnet.symbol.numpy')
+def median(a, axis=None, out=None, keepdims=False):
+r"""
+Compute the median along the specified axis.
+
+Returns the median of the array elements.
+
+Parameters
+--
+a : array_like
 
 Review comment:
   For symbolic version, input should be `_Symbol`


This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


With regards,
Apache Git Services


[GitHub] [incubator-mxnet] haojin2 commented on a change in pull request #17084: [numpy] add op median

2019-12-15 Thread GitBox
haojin2 commented on a change in pull request #17084: [numpy] add op median
URL: https://github.com/apache/incubator-mxnet/pull/17084#discussion_r358090292
 
 

 ##
 File path: python/mxnet/ndarray/numpy/_op.py
 ##
 @@ -3576,6 +3577,59 @@ def swapaxes(a, axis1, axis2):
 return _npi.swapaxes(a, dim1=axis1, dim2=axis2)
 
 
+@set_module('mxnet.ndarray.numpy')
+def median(a, axis=None, out=None, keepdims=False):
+r"""
+Compute the median along the specified axis.
 
 Review comment:
   same here.


This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


With regards,
Apache Git Services


[GitHub] [incubator-mxnet] haojin2 commented on a change in pull request #17084: [numpy] add op median

2019-12-15 Thread GitBox
haojin2 commented on a change in pull request #17084: [numpy] add op median
URL: https://github.com/apache/incubator-mxnet/pull/17084#discussion_r358090346
 
 

 ##
 File path: python/mxnet/symbol/numpy/_symbol.py
 ##
 @@ -3429,6 +3429,59 @@ def get_list(arrays):
 return _npi.stack(*arrays, axis=axis, out=out)
 
 
+@set_module('mxnet.symbol.numpy')
+def median(a, axis=None, out=None, keepdims=False):
+r"""
+Compute the median along the specified axis.
 
 Review comment:
   same here.


This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


With regards,
Apache Git Services


[GitHub] [incubator-mxnet] haojin2 commented on a change in pull request #17084: [numpy] add op median

2019-12-15 Thread GitBox
haojin2 commented on a change in pull request #17084: [numpy] add op median
URL: https://github.com/apache/incubator-mxnet/pull/17084#discussion_r358090682
 
 

 ##
 File path: src/imperative/imperative_utils.h
 ##
 @@ -274,7 +274,7 @@ inline void SetDependency(const nnvm::NodeAttrs& attrs,
 LOG(FATAL) << "resource type not yet supported";
   }
 }
-CHECK_LE(ntmp, 1) << "Only support 1 temp space request";
+CHECK_LE(ntmp, 2) << "Only support 1 temp space request";
 
 Review comment:
   you should not change this line.


This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


With regards,
Apache Git Services


[GitHub] [incubator-mxnet] haojin2 commented on a change in pull request #17084: [numpy] add op median

2019-12-15 Thread GitBox
haojin2 commented on a change in pull request #17084: [numpy] add op median
URL: https://github.com/apache/incubator-mxnet/pull/17084#discussion_r358090629
 
 

 ##
 File path: python/mxnet/symbol/numpy/_symbol.py
 ##
 @@ -3429,6 +3429,59 @@ def get_list(arrays):
 return _npi.stack(*arrays, axis=axis, out=out)
 
 
+@set_module('mxnet.symbol.numpy')
+def median(a, axis=None, out=None, keepdims=False):
+r"""
+Compute the median along the specified axis.
+
+Returns the median of the array elements.
+
+Parameters
+--
+a : array_like
+Input array or object that can be converted to an array.
+axis : {int, sequence of int, None}, optional
+Axis or axes along which the medians are computed. The default
+is to compute the median along a flattened version of the array.
+A sequence of axes is supported since version 1.9.0.
+out : ndarray, optional
+Alternative output array in which to place the result. It must
+have the same shape and buffer length as the expected output,
+but the type (of the output) will be cast if necessary.
+keepdims : bool, optional
+If this is set to True, the axes which are reduced are left
+in the result as dimensions with size one. With this option,
+the result will broadcast correctly against the original `arr`.
+
+Returns
+---
+median : ndarray
+A new array holding the result. If the input contains integers
+or floats smaller than ``float64``, then the output data-type is
+``np.float64``.  Otherwise, the data-type of the output is the
+same as that of the input. If `out` is specified, that array is
+returned instead.
+
+See Also
+
+mean, percentile
+
+Examples
 
 Review comment:
   No examples for symbolic case


This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


With regards,
Apache Git Services


[GitHub] [incubator-mxnet] haojin2 commented on a change in pull request #17084: [numpy] add op median

2019-12-15 Thread GitBox
haojin2 commented on a change in pull request #17084: [numpy] add op median
URL: https://github.com/apache/incubator-mxnet/pull/17084#discussion_r358090527
 
 

 ##
 File path: python/mxnet/symbol/numpy/_symbol.py
 ##
 @@ -3429,6 +3429,59 @@ def get_list(arrays):
 return _npi.stack(*arrays, axis=axis, out=out)
 
 
+@set_module('mxnet.symbol.numpy')
+def median(a, axis=None, out=None, keepdims=False):
+r"""
+Compute the median along the specified axis.
+
+Returns the median of the array elements.
+
+Parameters
+--
+a : array_like
+Input array or object that can be converted to an array.
+axis : {int, sequence of int, None}, optional
+Axis or axes along which the medians are computed. The default
+is to compute the median along a flattened version of the array.
+A sequence of axes is supported since version 1.9.0.
+out : ndarray, optional
 
 Review comment:
   Here it should also be `_Symbol`


This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


With regards,
Apache Git Services


[GitHub] [incubator-mxnet] haojin2 commented on a change in pull request #17084: [numpy] add op median

2019-12-15 Thread GitBox
haojin2 commented on a change in pull request #17084: [numpy] add op median
URL: https://github.com/apache/incubator-mxnet/pull/17084#discussion_r358090578
 
 

 ##
 File path: python/mxnet/symbol/numpy/_symbol.py
 ##
 @@ -3429,6 +3429,59 @@ def get_list(arrays):
 return _npi.stack(*arrays, axis=axis, out=out)
 
 
+@set_module('mxnet.symbol.numpy')
+def median(a, axis=None, out=None, keepdims=False):
+r"""
+Compute the median along the specified axis.
+
+Returns the median of the array elements.
+
+Parameters
+--
+a : array_like
+Input array or object that can be converted to an array.
+axis : {int, sequence of int, None}, optional
+Axis or axes along which the medians are computed. The default
+is to compute the median along a flattened version of the array.
+A sequence of axes is supported since version 1.9.0.
+out : ndarray, optional
+Alternative output array in which to place the result. It must
+have the same shape and buffer length as the expected output,
+but the type (of the output) will be cast if necessary.
+keepdims : bool, optional
+If this is set to True, the axes which are reduced are left
+in the result as dimensions with size one. With this option,
+the result will broadcast correctly against the original `arr`.
+
+Returns
+---
+median : ndarray
 
 Review comment:
   `_Symbol`


This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


With regards,
Apache Git Services


[GitHub] [incubator-mxnet] haojin2 commented on a change in pull request #17084: [numpy] add op median

2019-12-15 Thread GitBox
haojin2 commented on a change in pull request #17084: [numpy] add op median
URL: https://github.com/apache/incubator-mxnet/pull/17084#discussion_r358090938
 
 

 ##
 File path: src/operator/numpy/np_broadcast_reduce_op.h
 ##
 @@ -843,6 +846,196 @@ void NumpyBroadcastToForward(const nnvm::NodeAttrs& 
attrs,
 req, outputs, expanded_ishape);
 }
 
+struct NumpyMedianParam : public dmlc::Parameter {
+  dmlc::optional> axis;
+  bool keepdims;
+  DMLC_DECLARE_PARAMETER(NumpyMedianParam) {
+DMLC_DECLARE_FIELD(axis)
+  .set_default(dmlc::optional>())
+  .describe("Axis or axes along which the medians are computed. "
+"The default is to compute the "
+"median along a flattened version of the array.");
+DMLC_DECLARE_FIELD(keepdims)
+  .set_default(false)
+  .describe("If this is set to `True`, the reduced axes are left "
+"in the result as dimension with size one.");
+  }
+};
+
+template
+struct median_forward {
+  template
+  MSHADOW_XINLINE static void Map(int i,
+  DType* out,
+  const DType* a_sort,
+  mshadow::Shape t_shape,
+  mshadow::Shape r_shape) {
+using namespace mshadow;
+using namespace mxnet_op;
+using namespace std;
+
+auto r_coord = unravel(i, r_shape);
+
+Shape t_coord(t_shape);
+
+for (int j = 0; j < NDim-1; ++j) {
+  t_coord[j] = r_coord[j+1];
+}
+
+float idx = 0.5 * (t_shape[NDim-1]-1);
+
+if (floor(idx) == ceil(idx)) {
+  int idx_below = floor(idx);
+  t_coord[NDim-1] = idx_below;
+  size_t t_idx1 = ravel(t_coord, t_shape);
+  out[i] = a_sort[t_idx1];
+} else{
+  int idx_below = floor(idx);
+  t_coord[NDim-1] = idx_below;
+  size_t t_idx1 = ravel(t_coord, t_shape);
+  size_t t_idx2 = t_idx1 + 1;
+  DType x1 = a_sort[t_idx1];
+  DType x2 = a_sort[t_idx2];
+  out[i] = (x1 + x2) / 2;}
+  }
+};
+
+template
+void NumpyMedianForward(const nnvm::NodeAttrs& attrs,
+  const OpContext& ctx,
+  const std::vector& inputs,
+  const std::vector& req,
+  const std::vector& outputs) {
+  if (req[0] == kNullOp)
+return;
+
+  using namespace mxnet;
+  using namespace mxnet_op;
+  CHECK_EQ(inputs.size(), 1U);
+  CHECK_EQ(outputs.size(), 1U);
+
+  Stream *s = ctx.get_stream();
+
+  auto ¶m = nnvm::get(attrs.parsed);
 
 Review comment:
   ```c++
 NumpyMedianParam& param = nnvm::get(attrs.parsed);
   ```


This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


With regards,
Apache Git Services


[GitHub] [incubator-mxnet] haojin2 commented on a change in pull request #17084: [numpy] add op median

2019-12-17 Thread GitBox
haojin2 commented on a change in pull request #17084: [numpy] add op median
URL: https://github.com/apache/incubator-mxnet/pull/17084#discussion_r359121659
 
 

 ##
 File path: tests/python/unittest/test_numpy_op.py
 ##
 @@ -712,6 +712,41 @@ def avg_backward(a, w, avg, axes, init_a_grad=None, 
init_w_grad=None):
 assert_almost_equal(mx_sum_of_weights.asnumpy(), 
np_sum_of_weights, rtol=rtol, atol=atol)
 assert_almost_equal(mx_out.asnumpy(), np_out.astype(dtype), rtol=rtol, 
atol=atol)
 
+def test_np_median():
+class TestMedian(HybridBlock):
+def __init__(self, axis=None, keepdims=False):
+super(TestMedian, self).__init__()
+self._axis = axis
+self._keepdims = keepdims
+
+def hybrid_forward(self, F, a):
+return F.np.median(a, axis=self._axis, keepdims=self._keepdims)
+
+flags = [True, False]
+dtypes = ['float16', 'float32', 'float64']
+qtypes = ['float32', 'float64']
+tensor_shapes = [
+((2, 3), None),
+((2, 3, 4, 5), 3),
+((2, 3, 4), (0, 2)),
+((2, 3, 4), 1)
+]
+for hybridize, keepdims, (a_shape, axis), dtype in \
 
 Review comment:
   one more blank line above


This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


With regards,
Apache Git Services


[GitHub] [incubator-mxnet] haojin2 commented on a change in pull request #17084: [numpy] add op median

2019-12-17 Thread GitBox
haojin2 commented on a change in pull request #17084: [numpy] add op median
URL: https://github.com/apache/incubator-mxnet/pull/17084#discussion_r359121727
 
 

 ##
 File path: tests/python/unittest/test_numpy_interoperability.py
 ##
 @@ -695,6 +695,13 @@ def _add_workload_mean(array_pool):
 OpArgMngr.add_workload('mean', np.array([[1, 2, 3], [4, 5, 6]]), axis=0)
 OpArgMngr.add_workload('mean', np.array([[1, 2, 3], [4, 5, 6]]), axis=1)
 
+def _add_workload_median(array_pool):
 
 Review comment:
   one more blank line above.


This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


With regards,
Apache Git Services


[GitHub] [incubator-mxnet] haojin2 commented on a change in pull request #17084: [numpy] add op median

2019-12-17 Thread GitBox
haojin2 commented on a change in pull request #17084: [numpy] add op median
URL: https://github.com/apache/incubator-mxnet/pull/17084#discussion_r359121643
 
 

 ##
 File path: tests/python/unittest/test_numpy_op.py
 ##
 @@ -712,6 +712,41 @@ def avg_backward(a, w, avg, axes, init_a_grad=None, 
init_w_grad=None):
 assert_almost_equal(mx_sum_of_weights.asnumpy(), 
np_sum_of_weights, rtol=rtol, atol=atol)
 assert_almost_equal(mx_out.asnumpy(), np_out.astype(dtype), rtol=rtol, 
atol=atol)
 
+def test_np_median():
+class TestMedian(HybridBlock):
+def __init__(self, axis=None, keepdims=False):
+super(TestMedian, self).__init__()
+self._axis = axis
+self._keepdims = keepdims
+
+def hybrid_forward(self, F, a):
+return F.np.median(a, axis=self._axis, keepdims=self._keepdims)
+
+flags = [True, False]
+dtypes = ['float16', 'float32', 'float64']
+qtypes = ['float32', 'float64']
+tensor_shapes = [
+((2, 3), None),
+((2, 3, 4, 5), 3),
+((2, 3, 4), (0, 2)),
+((2, 3, 4), 1)
+]
+for hybridize, keepdims, (a_shape, axis), dtype in \
+itertools.product(flags, flags, tensor_shapes, dtypes):
+atol = 3e-4 if dtype == 'float16' else 1e-4
+rtol = 3e-2 if dtype == 'float16' else 1e-2
+test_median = TestMedian(axis=axis, keepdims=keepdims)
+if hybridize:
+test_median.hybridize()
+a = np.random.uniform(-1.0, 1.0, size=a_shape)
+np_out = _np.median(a.asnumpy(), axis=axis, keepdims=keepdims)
+mx_out = test_median(a)
+assert mx_out.shape == np_out.shape
+assert_almost_equal(mx_out.asnumpy(), np_out, atol=atol, rtol=rtol)
+
+mx_out = np.median(a, axis=axis, keepdims=keepdims)
+np_out = _np.median(a.asnumpy(), axis=axis, keepdims=keepdims)
+assert_almost_equal(mx_out.asnumpy(), np_out, atol=atol, rtol=rtol)
 
 Review comment:
   one more blank line below.


This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


With regards,
Apache Git Services


[GitHub] [incubator-mxnet] haojin2 commented on a change in pull request #17084: [numpy] add op median

2019-12-17 Thread GitBox
haojin2 commented on a change in pull request #17084: [numpy] add op median
URL: https://github.com/apache/incubator-mxnet/pull/17084#discussion_r359127588
 
 

 ##
 File path: src/operator/numpy/np_broadcast_reduce_op.h
 ##
 @@ -843,6 +846,354 @@ void NumpyBroadcastToForward(const nnvm::NodeAttrs& 
attrs,
 req, outputs, expanded_ishape);
 }
 
+struct NumpyMedianParam : public dmlc::Parameter {
+  dmlc::optional> axis;
+  bool keepdims;
+  DMLC_DECLARE_PARAMETER(NumpyMedianParam) {
+DMLC_DECLARE_FIELD(axis)
+  .set_default(dmlc::optional>())
+  .describe("Axis or axes along which the medians are computed. "
+"The default is to compute the "
+"median along a flattened version of the array.");
+DMLC_DECLARE_FIELD(keepdims)
+  .set_default(false)
+  .describe("If this is set to `True`, the reduced axes are left "
+"in the result as dimension with size one.");
+  }
+};
+
+template
+struct median_forward {
+  template
+  MSHADOW_XINLINE static void Map(int i,
+  DType* out,
+  const DType* a_sort,
+  mshadow::Shape t_shape,
+  mshadow::Shape r_shape) {
+using namespace mshadow;
+using namespace mxnet_op;
+using namespace std;
+
+auto r_coord = unravel(i, r_shape);
+
+Shape t_coord(t_shape);
+
+for (int j = 0; j < NDim-1; ++j) {
+  t_coord[j] = r_coord[j+1];
+}
+
+float idx = 0.5 * (t_shape[NDim-1]-1);
+
+if (floor(idx) == ceil(idx)) {
+  int idx_below = floor(idx);
+  t_coord[NDim-1] = idx_below;
+  size_t t_idx1 = ravel(t_coord, t_shape);
+  out[i] = a_sort[t_idx1];
+} else{
+  int idx_below = floor(idx);
+  t_coord[NDim-1] = idx_below;
+  size_t t_idx1 = ravel(t_coord, t_shape);
+  size_t t_idx2 = t_idx1 + 1;
+  DType x1 = a_sort[t_idx1];
+  DType x2 = a_sort[t_idx2];
+  out[i] = (x1 + x2) / 2;}
+  }
+};
+
+template
+void NumpyMedianForward(const nnvm::NodeAttrs& attrs,
+  const OpContext& ctx,
 
 Review comment:
   alignment


This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


With regards,
Apache Git Services


[GitHub] [incubator-mxnet] haojin2 commented on a change in pull request #17084: [numpy] add op median

2019-12-17 Thread GitBox
haojin2 commented on a change in pull request #17084: [numpy] add op median
URL: https://github.com/apache/incubator-mxnet/pull/17084#discussion_r359127664
 
 

 ##
 File path: src/operator/numpy/np_broadcast_reduce_op.h
 ##
 @@ -843,6 +846,354 @@ void NumpyBroadcastToForward(const nnvm::NodeAttrs& 
attrs,
 req, outputs, expanded_ishape);
 }
 
+struct NumpyMedianParam : public dmlc::Parameter {
+  dmlc::optional> axis;
+  bool keepdims;
+  DMLC_DECLARE_PARAMETER(NumpyMedianParam) {
+DMLC_DECLARE_FIELD(axis)
+  .set_default(dmlc::optional>())
+  .describe("Axis or axes along which the medians are computed. "
+"The default is to compute the "
+"median along a flattened version of the array.");
+DMLC_DECLARE_FIELD(keepdims)
+  .set_default(false)
+  .describe("If this is set to `True`, the reduced axes are left "
+"in the result as dimension with size one.");
+  }
+};
+
+template
+struct median_forward {
+  template
+  MSHADOW_XINLINE static void Map(int i,
+  DType* out,
+  const DType* a_sort,
+  mshadow::Shape t_shape,
+  mshadow::Shape r_shape) {
+using namespace mshadow;
+using namespace mxnet_op;
+using namespace std;
+
+auto r_coord = unravel(i, r_shape);
+
+Shape t_coord(t_shape);
+
+for (int j = 0; j < NDim-1; ++j) {
+  t_coord[j] = r_coord[j+1];
+}
+
+float idx = 0.5 * (t_shape[NDim-1]-1);
+
+if (floor(idx) == ceil(idx)) {
+  int idx_below = floor(idx);
+  t_coord[NDim-1] = idx_below;
+  size_t t_idx1 = ravel(t_coord, t_shape);
+  out[i] = a_sort[t_idx1];
+} else{
+  int idx_below = floor(idx);
+  t_coord[NDim-1] = idx_below;
+  size_t t_idx1 = ravel(t_coord, t_shape);
+  size_t t_idx2 = t_idx1 + 1;
+  DType x1 = a_sort[t_idx1];
+  DType x2 = a_sort[t_idx2];
+  out[i] = (x1 + x2) / 2;}
+  }
+};
+
+template
+void NumpyMedianForward(const nnvm::NodeAttrs& attrs,
+  const OpContext& ctx,
+  const std::vector& inputs,
+  const std::vector& req,
+  const std::vector& outputs) {
+  if (req[0] == kNullOp)
+return;
 
 Review comment:
   ```c++
 if (req[0] == kNullOp) return;
   ```


This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


With regards,
Apache Git Services


[GitHub] [incubator-mxnet] haojin2 commented on a change in pull request #17084: [numpy] add op median

2019-12-17 Thread GitBox
haojin2 commented on a change in pull request #17084: [numpy] add op median
URL: https://github.com/apache/incubator-mxnet/pull/17084#discussion_r359132590
 
 

 ##
 File path: src/operator/numpy/np_broadcast_reduce_op_value.cc
 ##
 @@ -320,6 +321,36 @@ NNVM_REGISTER_OP(_backward_np_average)
 return std::vector{ResourceRequest::kTempSpace};
 });
 
+inline bool NumpyMedianType(const nnvm::NodeAttrs& attrs,
+  std::vector *in_attrs,
+  std::vector *out_attrs) {
+  CHECK_EQ(in_attrs->size(), 1U);
+  CHECK_EQ(out_attrs->size(), 1U);
+
+  TYPE_ASSIGN_CHECK(*out_attrs, 0, mshadow::kFloat32);
+  return out_attrs->at(0) != -1 && in_attrs->at(0) != -1;
+}
+
+NNVM_REGISTER_OP(_npi_median)
+.set_num_inputs(1)
+.set_num_outputs(1)
+.set_attr_parser(ParamParser)
+.set_attr("FInferShape", NumpyMedianShape)
+.set_attr("FInferType", NumpyMedianType)
+.set_attr("FListInputNames",
+  [](const NodeAttrs& attrs) {
+return std::vector{"a"};
+  })
+.add_argument("a", "NDArray-or-Symbol", "The input")
+.add_arguments(NumpyMedianParam::__FIELDS__())
+.set_attr("FCompute", NumpyMedianForward)
+.set_attr("FResourceRequest",
+  [](const NodeAttrs& attrs) {
+return std::vector{ResourceRequest::kTempSpace};
+  })
+// .set_attr("THasDeterministicOutput", true)
 
 Review comment:
   get rid of unused code


This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


With regards,
Apache Git Services


[GitHub] [incubator-mxnet] haojin2 commented on a change in pull request #17084: [numpy] add op median

2019-12-17 Thread GitBox
haojin2 commented on a change in pull request #17084: [numpy] add op median
URL: https://github.com/apache/incubator-mxnet/pull/17084#discussion_r359132646
 
 

 ##
 File path: src/operator/numpy/np_broadcast_reduce_op.h
 ##
 @@ -843,6 +846,354 @@ void NumpyBroadcastToForward(const nnvm::NodeAttrs& 
attrs,
 req, outputs, expanded_ishape);
 }
 
+struct NumpyMedianParam : public dmlc::Parameter {
+  dmlc::optional> axis;
+  bool keepdims;
+  DMLC_DECLARE_PARAMETER(NumpyMedianParam) {
+DMLC_DECLARE_FIELD(axis)
+  .set_default(dmlc::optional>())
+  .describe("Axis or axes along which the medians are computed. "
+"The default is to compute the "
+"median along a flattened version of the array.");
+DMLC_DECLARE_FIELD(keepdims)
+  .set_default(false)
+  .describe("If this is set to `True`, the reduced axes are left "
+"in the result as dimension with size one.");
+  }
+};
+
+template
+struct median_forward {
+  template
+  MSHADOW_XINLINE static void Map(int i,
+  DType* out,
+  const DType* a_sort,
+  mshadow::Shape t_shape,
+  mshadow::Shape r_shape) {
+using namespace mshadow;
+using namespace mxnet_op;
+using namespace std;
+
+auto r_coord = unravel(i, r_shape);
+
+Shape t_coord(t_shape);
+
+for (int j = 0; j < NDim-1; ++j) {
+  t_coord[j] = r_coord[j+1];
+}
+
+float idx = 0.5 * (t_shape[NDim-1]-1);
+
+if (floor(idx) == ceil(idx)) {
+  int idx_below = floor(idx);
+  t_coord[NDim-1] = idx_below;
+  size_t t_idx1 = ravel(t_coord, t_shape);
+  out[i] = a_sort[t_idx1];
+} else{
+  int idx_below = floor(idx);
+  t_coord[NDim-1] = idx_below;
+  size_t t_idx1 = ravel(t_coord, t_shape);
+  size_t t_idx2 = t_idx1 + 1;
+  DType x1 = a_sort[t_idx1];
+  DType x2 = a_sort[t_idx2];
+  out[i] = (x1 + x2) / 2;}
+  }
+};
+
+template
+void NumpyMedianForward(const nnvm::NodeAttrs& attrs,
+  const OpContext& ctx,
+  const std::vector& inputs,
+  const std::vector& req,
+  const std::vector& outputs) {
+  if (req[0] == kNullOp)
+return;
+
+  using namespace mxnet;
+  using namespace mxnet_op;
+  CHECK_EQ(inputs.size(), 1U);
+  CHECK_EQ(outputs.size(), 1U);
+
+  Stream *s = ctx.get_stream();
+
+  NumpyMedianParam param = nnvm::get(attrs.parsed);
+  const TBlob& a = inputs[0];
+  const TBlob& r = outputs[0];
+
+  auto small = NumpyReduceAxesShapeImpl(a.shape_, param.axis, false);
+
+  dmlc::optional> axis = param.axis;
+
+  TShape r_shape;
+  r_shape = TShape(small.ndim()+1, 1);
+  for (int i = 1; i < r_shape.ndim(); ++i) {
+r_shape[i] = small[i-1];
+  }
+
+  TShape axes;
+  if (!axis.has_value()) {
+axes = TShape(a.shape_.ndim(), 1);
+for (int i = 0; i < a.shape_.ndim(); ++i) {
+  axes[i] = i;
+}
+  } else {
+auto axis_tuple = axis.value();
+axes = TShape(axis_tuple.ndim(), 1);
+for (int i = 0; i < axis_tuple.ndim(); ++i) {
+  axes[i] = axis_tuple[i];
+}
+  }
+
+  TShape t_axes(a.shape_.ndim(), 1);
+  int j = 0;
+  for (int i = 0; i < t_axes.ndim(); ++i) {
+bool red = false;
+for (int k = 0; k < axes.ndim(); ++k) {
+  if (axes[k] == i) {
+red = true;
+  }
+}
+if (!red) {
+  t_axes[j] = i;
+  j++;
+}
+  }
+  for (int jj = j; jj < t_axes.ndim(); ++jj) {
+t_axes[jj] = axes[jj-j];
+  }
+
+  TShape t_shape(small.ndim()+1, 1);
+  for (int i = 0; i < small.ndim(); ++i) {
+t_shape[i] = small[i];
+  }
+  size_t red_size = 1;
+  for (int i = 0; i < axes.ndim(); ++i) {
+red_size *= a.shape_[axes[i]];
+  }
+  t_shape[t_shape.ndim()-1] = red_size;
+  TShape t_shape_ex(a.shape_.ndim(), 1);
+  for (int i = 0; i < small.ndim(); ++i) {
+t_shape_ex[i] = small[i];
+  }
+  for (int i = small.ndim(); i < a.shape_.ndim(); ++i) {
+t_shape_ex[i] = a.shape_[axes[i-small.ndim()]];
+  }
+
+  TopKParam topk_param = TopKParam();
+  topk_param.axis = dmlc::optional(-1);
+  topk_param.is_ascend = true;
+  topk_param.k = 0;
+  topk_param.ret_typ = topk_enum::kReturnValue;
+
+  MSHADOW_TYPE_SWITCH(a.type_flag_, DType, {
+using namespace mshadow::expr;
+Tensor workspace;
+Tensor temp_workspace;
+Tensor sorted_dat;
+Tensor indices, sel_indices;
+size_t batch_size = 0;
+index_t element_num = 0;  // number of batches + the size of each batch
+int axis_topk = 0;
+bool do_transpose = false;
+bool is_ascend = false;
+index_t k = 0;
+size_t alignment = std::max(sizeof(DType), sizeof(index_t));
+mxnet::TShape target_shape;
+
+size_t temp_data_size = a.shape_.Size() * sizeof(DType);
+size_t idx_size = a.shape_.Size() * sizeof(index_t);
+size_t temp_mem_size = 2 * temp_data_size + idx

[GitHub] [incubator-mxnet] haojin2 commented on a change in pull request #17084: [numpy] add op median

2019-12-17 Thread GitBox
haojin2 commented on a change in pull request #17084: [numpy] add op median
URL: https://github.com/apache/incubator-mxnet/pull/17084#discussion_r359132679
 
 

 ##
 File path: src/operator/numpy/np_broadcast_reduce_op.h
 ##
 @@ -843,6 +846,354 @@ void NumpyBroadcastToForward(const nnvm::NodeAttrs& 
attrs,
 req, outputs, expanded_ishape);
 }
 
+struct NumpyMedianParam : public dmlc::Parameter {
+  dmlc::optional> axis;
+  bool keepdims;
+  DMLC_DECLARE_PARAMETER(NumpyMedianParam) {
+DMLC_DECLARE_FIELD(axis)
+  .set_default(dmlc::optional>())
+  .describe("Axis or axes along which the medians are computed. "
+"The default is to compute the "
+"median along a flattened version of the array.");
+DMLC_DECLARE_FIELD(keepdims)
+  .set_default(false)
+  .describe("If this is set to `True`, the reduced axes are left "
+"in the result as dimension with size one.");
+  }
+};
+
+template
+struct median_forward {
+  template
+  MSHADOW_XINLINE static void Map(int i,
+  DType* out,
+  const DType* a_sort,
+  mshadow::Shape t_shape,
+  mshadow::Shape r_shape) {
+using namespace mshadow;
+using namespace mxnet_op;
+using namespace std;
+
+auto r_coord = unravel(i, r_shape);
+
+Shape t_coord(t_shape);
+
+for (int j = 0; j < NDim-1; ++j) {
+  t_coord[j] = r_coord[j+1];
+}
+
+float idx = 0.5 * (t_shape[NDim-1]-1);
+
+if (floor(idx) == ceil(idx)) {
+  int idx_below = floor(idx);
+  t_coord[NDim-1] = idx_below;
+  size_t t_idx1 = ravel(t_coord, t_shape);
+  out[i] = a_sort[t_idx1];
+} else{
+  int idx_below = floor(idx);
+  t_coord[NDim-1] = idx_below;
+  size_t t_idx1 = ravel(t_coord, t_shape);
+  size_t t_idx2 = t_idx1 + 1;
+  DType x1 = a_sort[t_idx1];
+  DType x2 = a_sort[t_idx2];
+  out[i] = (x1 + x2) / 2;}
+  }
+};
+
+template
+void NumpyMedianForward(const nnvm::NodeAttrs& attrs,
+  const OpContext& ctx,
+  const std::vector& inputs,
+  const std::vector& req,
+  const std::vector& outputs) {
+  if (req[0] == kNullOp)
+return;
+
+  using namespace mxnet;
+  using namespace mxnet_op;
+  CHECK_EQ(inputs.size(), 1U);
+  CHECK_EQ(outputs.size(), 1U);
+
+  Stream *s = ctx.get_stream();
+
+  NumpyMedianParam param = nnvm::get(attrs.parsed);
+  const TBlob& a = inputs[0];
+  const TBlob& r = outputs[0];
+
+  auto small = NumpyReduceAxesShapeImpl(a.shape_, param.axis, false);
+
+  dmlc::optional> axis = param.axis;
+
+  TShape r_shape;
+  r_shape = TShape(small.ndim()+1, 1);
+  for (int i = 1; i < r_shape.ndim(); ++i) {
+r_shape[i] = small[i-1];
+  }
+
+  TShape axes;
+  if (!axis.has_value()) {
+axes = TShape(a.shape_.ndim(), 1);
+for (int i = 0; i < a.shape_.ndim(); ++i) {
+  axes[i] = i;
+}
+  } else {
+auto axis_tuple = axis.value();
+axes = TShape(axis_tuple.ndim(), 1);
+for (int i = 0; i < axis_tuple.ndim(); ++i) {
+  axes[i] = axis_tuple[i];
+}
+  }
+
+  TShape t_axes(a.shape_.ndim(), 1);
+  int j = 0;
+  for (int i = 0; i < t_axes.ndim(); ++i) {
+bool red = false;
+for (int k = 0; k < axes.ndim(); ++k) {
+  if (axes[k] == i) {
+red = true;
+  }
+}
+if (!red) {
+  t_axes[j] = i;
+  j++;
+}
+  }
+  for (int jj = j; jj < t_axes.ndim(); ++jj) {
+t_axes[jj] = axes[jj-j];
+  }
+
+  TShape t_shape(small.ndim()+1, 1);
+  for (int i = 0; i < small.ndim(); ++i) {
+t_shape[i] = small[i];
+  }
+  size_t red_size = 1;
+  for (int i = 0; i < axes.ndim(); ++i) {
+red_size *= a.shape_[axes[i]];
+  }
+  t_shape[t_shape.ndim()-1] = red_size;
+  TShape t_shape_ex(a.shape_.ndim(), 1);
+  for (int i = 0; i < small.ndim(); ++i) {
+t_shape_ex[i] = small[i];
+  }
+  for (int i = small.ndim(); i < a.shape_.ndim(); ++i) {
+t_shape_ex[i] = a.shape_[axes[i-small.ndim()]];
+  }
+
+  TopKParam topk_param = TopKParam();
+  topk_param.axis = dmlc::optional(-1);
+  topk_param.is_ascend = true;
+  topk_param.k = 0;
+  topk_param.ret_typ = topk_enum::kReturnValue;
+
+  MSHADOW_TYPE_SWITCH(a.type_flag_, DType, {
+using namespace mshadow::expr;
+Tensor workspace;
+Tensor temp_workspace;
+Tensor sorted_dat;
+Tensor indices, sel_indices;
+size_t batch_size = 0;
+index_t element_num = 0;  // number of batches + the size of each batch
+int axis_topk = 0;
+bool do_transpose = false;
+bool is_ascend = false;
+index_t k = 0;
+size_t alignment = std::max(sizeof(DType), sizeof(index_t));
+mxnet::TShape target_shape;
+
+size_t temp_data_size = a.shape_.Size() * sizeof(DType);
+size_t idx_size = a.shape_.Size() * sizeof(index_t);
+size_t temp_mem_size = 2 * temp_data_size + idx

[GitHub] [incubator-mxnet] haojin2 commented on a change in pull request #17084: [numpy] add op median

2020-02-16 Thread GitBox
haojin2 commented on a change in pull request #17084: [numpy] add op median
URL: https://github.com/apache/incubator-mxnet/pull/17084#discussion_r380002267
 
 

 ##
 File path: python/mxnet/ndarray/numpy/_op.py
 ##
 @@ -6550,6 +6550,57 @@ def percentile(a, q, axis=None, out=None, 
overwrite_input=None, interpolation='l
keepdims=keepdims, q_scalar=None, out=out)
 
 
+@set_module('mxnet.ndarray.numpy')
+def median(a, axis=None, out=None, overwrite_input=None, keepdims=False):
+r"""
+Compute the median along the specified axis.
+Returns the median of the array elements.
+Parameters
+--
+a : array_like
+Input array or object that can be converted to an array.
+axis : {int, sequence of int, None}, optional
+Axis or axes along which the medians are computed. The default
+is to compute the median along a flattened version of the array.
+A sequence of axes is supported since version 1.9.0.
+out : ndarray, optional
+Alternative output array in which to place the result. It must
+have the same shape and buffer length as the expected output,
+but the type (of the output) will be cast if necessary.
+keepdims : bool, optional
+If this is set to True, the axes which are reduced are left
+in the result as dimensions with size one. With this option,
+the result will broadcast correctly against the original `arr`.
+Returns
+---
+median : ndarray
+A new array holding the result. If the input contains integers
+or floats smaller than ``float32``, then the output data-type is
+``np.float32``.  Otherwise, the data-type of the output is the
+same as that of the input. If `out` is specified, that array is
+returned instead.
+See Also
+
+mean, percentile
+Examples
+
+>>> a = np.array([[10, 7, 4], [3, 2, 1]])
+>>> a
+array([[10,  7,  4],
+[ 3,  2,  1]])
+>>> np.median(a)
+3.5
+>>> np.median(a, axis=0)
+array([6.5, 4.5, 2.5])
+>>> np.median(a, axis=1)
+array([7.,  2.])
+"""
+from mxnet import np, npx
 
 Review comment:
   no need for the import here.


This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


With regards,
Apache Git Services


[GitHub] [incubator-mxnet] haojin2 commented on a change in pull request #17084: [numpy] add op median

2020-02-16 Thread GitBox
haojin2 commented on a change in pull request #17084: [numpy] add op median
URL: https://github.com/apache/incubator-mxnet/pull/17084#discussion_r380002411
 
 

 ##
 File path: python/mxnet/ndarray/numpy/_op.py
 ##
 @@ -6550,6 +6550,57 @@ def percentile(a, q, axis=None, out=None, 
overwrite_input=None, interpolation='l
keepdims=keepdims, q_scalar=None, out=out)
 
 
+@set_module('mxnet.ndarray.numpy')
+def median(a, axis=None, out=None, overwrite_input=None, keepdims=False):
+r"""
+Compute the median along the specified axis.
+Returns the median of the array elements.
+Parameters
+--
+a : array_like
+Input array or object that can be converted to an array.
+axis : {int, sequence of int, None}, optional
+Axis or axes along which the medians are computed. The default
+is to compute the median along a flattened version of the array.
+A sequence of axes is supported since version 1.9.0.
+out : ndarray, optional
+Alternative output array in which to place the result. It must
+have the same shape and buffer length as the expected output,
+but the type (of the output) will be cast if necessary.
+keepdims : bool, optional
+If this is set to True, the axes which are reduced are left
+in the result as dimensions with size one. With this option,
+the result will broadcast correctly against the original `arr`.
+Returns
+---
+median : ndarray
+A new array holding the result. If the input contains integers
+or floats smaller than ``float32``, then the output data-type is
+``np.float32``.  Otherwise, the data-type of the output is the
+same as that of the input. If `out` is specified, that array is
+returned instead.
+See Also
+
+mean, percentile
+Examples
+
+>>> a = np.array([[10, 7, 4], [3, 2, 1]])
+>>> a
+array([[10,  7,  4],
+[ 3,  2,  1]])
+>>> np.median(a)
+3.5
+>>> np.median(a, axis=0)
+array([6.5, 4.5, 2.5])
+>>> np.median(a, axis=1)
+array([7.,  2.])
+"""
+from mxnet import np, npx
+npx.set_np()
+return quantile(a=a, q=np.array(0.5), axis=axis, out=out, 
overwrite_input=overwrite_input,
 
 Review comment:
   `...quantile(a=a, q=0.5, ...)`


This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


With regards,
Apache Git Services


[GitHub] [incubator-mxnet] haojin2 commented on a change in pull request #17084: [numpy] add op median

2020-02-16 Thread GitBox
haojin2 commented on a change in pull request #17084: [numpy] add op median
URL: https://github.com/apache/incubator-mxnet/pull/17084#discussion_r380002724
 
 

 ##
 File path: tests/python/unittest/test_numpy_op.py
 ##
 @@ -7083,6 +7083,47 @@ def test_np_share_memory():
 assert not op(np.ones((5, 0), dtype=dt), np.ones((0, 3, 0), 
dtype=adt))
 
 
+def test_np_median():
+class TestMedian(HybridBlock):
+def __init__(self, axis=None, keepdims=False):
+super(TestMedian, self).__init__()
+self._axis = axis
+self._keepdims = keepdims
+
+def hybrid_forward(self, F, a):
+return F.np.median(a, axis=self._axis, keepdims=self._keepdims)
+
+flags = [True, False]
+dtypes = ['float16', 'float32', 'float64']
+qtypes = ['float32', 'float64']
+tensor_shapes = [
+((2, 3), None),
+((2, 3, 4, 5), 3),
+((2, 3, 4), (0, 2)),
+((2, 3, 4), 1)
+]
+
+for hybridize, keepdims, (a_shape, axis), dtype in \
+itertools.product(flags, flags, tensor_shapes, dtypes):
+atol = 3e-4 if dtype == 'float16' else 1e-4
+rtol = 3e-2 if dtype == 'float16' else 1e-2
+test_median = TestMedian(axis=axis, keepdims=keepdims)
+if hybridize:
+test_median.hybridize()
+a = np.random.uniform(-1.0, 1.0, size=a_shape)
+np_out = _np.median(a.asnumpy(), axis=axis, keepdims=keepdims)
+mx_out = test_median(a)
+
+assert mx_out.shape == np_out.shape
+assert_almost_equal(mx_out.asnumpy(), np_out, atol=atol, rtol=rtol)
+
+mx_out = np.median(a, axis=axis, keepdims=keepdims)
+np_out = _np.median(a.asnumpy(), axis=axis, keepdims=keepdims)
+
+assert_almost_equal(mx_out.asnumpy(), np_out, atol=atol, rtol=rtol)
+
 
 Review comment:
   2 blank lines between functions.


This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


With regards,
Apache Git Services