Skip to content
This repository has been archived by the owner on Nov 17, 2023. It is now read-only.

Commit

Permalink
[Numpy] implement np.column_stack (#16594)
Browse files Browse the repository at this point in the history
* implement np.column_stack

* cpplint

* remove column_stack from numpy interoperability test temporarily

* style and test fix

* fix pylint and add interoperability test

* fix doc string, add comment, remove dead code

* pylint

* ci

* ci

* ci

* [Numpy] Numpy operator diff (#15906)

* numpy diff operator implemented

append and prepend not supported yet

remove the prepend and append checking interface from the backend

refine the code, enrich the test set and all tests passed

registered the diff operator into npi scope

all tests passed

comments and minor modification

format codes and fix warning for sanity check

minor modification for sanity check

fix sanity

fix the tolerance bound of testing np.diff

resolve minor coding style issue

replace the given tests by random picking

minor fix

* interoperability test added

* implement np.column_stack

* cpplint

* remove column_stack from numpy interoperability test temporarily

* style and test fix

* fix pylint and add interoperability test

* fix doc string, add comment, remove dead code

* pylint

* ci

* ci

* ci

* rebase resolve conflicts

* pylint
  • Loading branch information
vexilligera authored and haojin2 committed Oct 31, 2019
1 parent a6a9706 commit f9baec9
Show file tree
Hide file tree
Showing 9 changed files with 452 additions and 8 deletions.
35 changes: 32 additions & 3 deletions python/mxnet/ndarray/numpy/_op.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,12 @@
'log1p', 'rint', 'radians', 'reciprocal', 'square', 'negative', 'fix', 'ceil', 'floor',
'trunc', 'logical_not', 'arcsinh', 'arccosh', 'arctanh', 'tensordot', 'histogram', 'eye',
'linspace', 'logspace', 'expand_dims', 'tile', 'arange', 'split', 'vsplit', 'concatenate',
'stack', 'vstack', 'dstack', 'mean', 'maximum', 'minimum', 'swapaxes', 'clip', 'argmax', 'argmin',
'std', 'var', 'indices', 'copysign', 'ravel', 'hanning', 'hamming', 'blackman', 'flip',
'stack', 'vstack', 'column_stack', 'dstack', 'mean', 'maximum', 'minimum', 'swapaxes', 'clip', 'argmax',
'argmin', 'std', 'var', 'indices', 'copysign', 'ravel', 'hanning', 'hamming', 'blackman', 'flip',
'around', 'hypot', 'rad2deg', 'deg2rad', 'unique', 'lcm', 'tril', 'identity', 'take',
'ldexp', 'vdot', 'inner', 'outer', 'equal', 'not_equal', 'greater', 'less', 'greater_equal', 'less_equal',
'hsplit', 'rot90', 'einsum', 'true_divide', 'nonzero', 'shares_memory', 'may_share_memory', 'diff']


@set_module('mxnet.ndarray.numpy')
def zeros(shape, dtype=_np.float32, order='C', ctx=None):
"""Return a new array of given shape and type, filled with zeros.
Expand Down Expand Up @@ -3004,6 +3003,36 @@ def get_list(arrays):
return _npi.vstack(*arrays)


@set_module('mxnet.ndarray.numpy')
def column_stack(tup):
"""
Stack 1-D arrays as columns into a 2-D array.
Take a sequence of 1-D arrays and stack them as columns
to make a single 2-D array. 2-D arrays are stacked as-is,
just like with `hstack`. 1-D arrays are turned into 2-D columns
first.
Returns
--------
stacked : 2-D array
The array formed by stacking the given arrays.
See Also
--------
stack, hstack, vstack, concatenate
Examples
--------
>>> a = np.array((1,2,3))
>>> b = np.array((2,3,4))
>>> np.column_stack((a,b))
array([[1., 2.],
[2., 3.],
[3., 4.]])
"""
return _npi.column_stack(*tup)


@set_module('mxnet.ndarray.numpy')
def dstack(arrays):
"""
Expand Down
38 changes: 37 additions & 1 deletion python/mxnet/numpy/multiarray.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
'degrees', 'log2', 'log1p', 'rint', 'radians', 'reciprocal', 'square', 'negative',
'fix', 'ceil', 'floor', 'trunc', 'logical_not', 'arcsinh', 'arccosh', 'arctanh',
'tensordot', 'histogram', 'eye', 'linspace', 'logspace', 'expand_dims', 'tile', 'arange',
'split', 'vsplit', 'concatenate', 'stack', 'vstack', 'dstack', 'mean', 'maximum', 'minimum',
'split', 'vsplit', 'concatenate', 'stack', 'vstack', 'column_stack', 'dstack', 'mean', 'maximum', 'minimum',
'swapaxes', 'clip', 'argmax', 'argmin', 'std', 'var', 'indices', 'copysign', 'ravel', 'hanning', 'hamming',
'blackman', 'flip', 'around', 'arctan2', 'hypot', 'rad2deg', 'deg2rad', 'unique', 'lcm', 'tril',
'identity', 'take', 'ldexp', 'vdot', 'inner', 'outer', 'equal', 'not_equal', 'greater', 'less',
Expand Down Expand Up @@ -4904,6 +4904,42 @@ def vstack(arrays, out=None):
return _mx_nd_np.vstack(arrays)


@set_module('mxnet.numpy')
def column_stack(tup):
"""
Stack 1-D arrays as columns into a 2-D array.
Take a sequence of 1-D arrays and stack them as columns
to make a single 2-D array. 2-D arrays are stacked as-is,
just like with `hstack`. 1-D arrays are turned into 2-D columns
first.
Parameters
----------
tup : sequence of 1-D or 2-D arrays.
Arrays to stack. All of them must have the same first dimension.
Returns
--------
stacked : 2-D array
The array formed by stacking the given arrays.
See Also
--------
stack, hstack, vstack, concatenate
Examples
--------
>>> a = np.array((1,2,3))
>>> b = np.array((2,3,4))
>>> np.column_stack((a,b))
array([[1., 2.],
[2., 3.],
[3., 4.]])
"""
return _mx_nd_np.column_stack(tup)


@set_module('mxnet.numpy')
def dstack(arrays):
"""
Expand Down
1 change: 1 addition & 0 deletions python/mxnet/numpy_dispatch_protocol.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ def _run_with_array_ufunc_proto(*args, **kwargs):
'var',
'vdot',
'vstack',
'column_stack',
'zeros_like',
'linalg.norm',
'trace',
Expand Down
40 changes: 38 additions & 2 deletions python/mxnet/symbol/numpy/_symbol.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@
'rint', 'radians', 'reciprocal', 'square', 'negative', 'fix', 'ceil', 'floor',
'trunc', 'logical_not', 'arcsinh', 'arccosh', 'arctanh', 'tensordot', 'histogram', 'eye',
'linspace', 'logspace', 'expand_dims', 'tile', 'arange', 'split', 'vsplit', 'concatenate',
'stack', 'vstack', 'dstack', 'mean', 'maximum', 'minimum', 'swapaxes', 'clip', 'argmax', 'argmin',
'std', 'var', 'indices', 'copysign', 'ravel', 'hanning', 'hamming', 'blackman', 'flip',
'stack', 'vstack', 'column_stack', 'dstack', 'mean', 'maximum', 'minimum', 'swapaxes', 'clip', 'argmax',
'argmin', 'std', 'var', 'indices', 'copysign', 'ravel', 'hanning', 'hamming', 'blackman', 'flip',
'around', 'hypot', 'rad2deg', 'deg2rad', 'unique', 'lcm', 'tril', 'identity', 'take',
'ldexp', 'vdot', 'inner', 'outer', 'equal', 'not_equal', 'greater', 'less', 'greater_equal',
'less_equal', 'hsplit', 'rot90', 'einsum', 'true_divide', 'shares_memory', 'may_share_memory', 'diff']
Expand Down Expand Up @@ -3072,6 +3072,42 @@ def get_list(arrays):
return _npi.vstack(*arrays)


@set_module('mxnet.symbol.numpy')
def column_stack(tup):
"""
Stack 1-D arrays as columns into a 2-D array.
Take a sequence of 1-D arrays and stack them as columns
to make a single 2-D array. 2-D arrays are stacked as-is,
just like with `hstack`. 1-D arrays are turned into 2-D columns
first.
Parameters
----------
tup : sequence of 1-D or 2-D arrays.
Arrays to stack. All of them must have the same first dimension.
Returns
-------
stacked : 2-D array
The array formed by stacking the given arrays.
See Also
--------
stack, hstack, vstack, concatenate
Examples
--------
>>> a = np.array((1,2,3))
>>> b = np.array((2,3,4))
>>> np.column_stack((a,b))
array([[1., 2.],
[2., 3.],
[3., 4.]])
"""
return _npi.column_stack(*tup)


@set_module('mxnet.symbol.numpy')
def dstack(arrays):
"""
Expand Down
80 changes: 80 additions & 0 deletions src/operator/numpy/np_matrix_op-inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,14 @@ struct NumpyVstackParam : public dmlc::Parameter<NumpyVstackParam> {
}
};

struct NumpyColumnStackParam : public dmlc::Parameter<NumpyColumnStackParam> {
int num_args;
DMLC_DECLARE_PARAMETER(NumpyColumnStackParam) {
DMLC_DECLARE_FIELD(num_args).set_lower_bound(1)
.describe("Number of inputs to be column stacked");
}
};

struct NumpyReshapeParam : public dmlc::Parameter<NumpyReshapeParam> {
mxnet::TShape newshape;
std::string order;
Expand Down Expand Up @@ -124,6 +132,78 @@ void NumpyTranspose(const nnvm::NodeAttrs& attrs,
}
}

template<typename xpu>
void NumpyColumnStackForward(const nnvm::NodeAttrs& attrs,
const OpContext& ctx,
const std::vector<TBlob>& inputs,
const std::vector<OpReqType>& req,
const std::vector<TBlob>& outputs) {
using namespace mshadow;
using namespace mshadow_op;

const NumpyColumnStackParam& param = nnvm::get<NumpyColumnStackParam>(attrs.parsed);
CHECK_EQ(inputs.size(), param.num_args);
CHECK_EQ(outputs.size(), 1);
CHECK_EQ(req.size(), 1);

// reshape if necessary
std::vector<TBlob> data(param.num_args);
for (int i = 0; i < param.num_args; i++) {
if (inputs[i].shape_.ndim() == 0 || inputs[i].shape_.ndim() == 1) {
TShape shape = Shape2(inputs[i].shape_.Size(), 1);
data[i] = inputs[i].reshape(shape);
} else {
data[i] = inputs[i];
}
}

// initialize ConcatOp
ConcatParam cparam;
cparam.num_args = param.num_args;
cparam.dim = 1;
MSHADOW_TYPE_SWITCH(inputs[0].type_flag_, DType, {
ConcatOp<xpu, DType> op;
op.Init(cparam);
op.Forward(ctx, data, req, outputs);
});
}

template<typename xpu>
void NumpyColumnStackBackward(const nnvm::NodeAttrs& attrs,
const OpContext& ctx,
const std::vector<TBlob>& inputs,
const std::vector<OpReqType>& req,
const std::vector<TBlob>& outputs) {
using namespace mshadow;
using namespace mshadow_op;

const NumpyColumnStackParam& param = nnvm::get<NumpyColumnStackParam>(attrs.parsed);
CHECK_EQ(inputs.size(), 1);
CHECK_EQ(outputs.size(), param.num_args);
CHECK_EQ(req.size(), param.num_args);

// reshape if necessary
std::vector<TBlob> data(param.num_args);
for (int i = 0; i < param.num_args; i++) {
if (outputs[i].shape_.ndim() == 0 || outputs[i].shape_.ndim() == 1) {
TShape shape = Shape2(outputs[i].shape_.Size(), 1);
data[i] = outputs[i].reshape(shape);
} else {
data[i] = outputs[i];
}
}

// initialize ConcatOp
ConcatParam cparam;
cparam.num_args = param.num_args;
cparam.dim = 1;
MSHADOW_TYPE_SWITCH(inputs[0].type_flag_, DType, {
ConcatOp<xpu, DType> op;
op.Init(cparam);
op.Backward(ctx, inputs[0], req, data);
});
}

template<typename xpu>
void NumpyVstackForward(const nnvm::NodeAttrs& attrs,
const OpContext& ctx,
Expand Down
Loading

0 comments on commit f9baec9

Please sign in to comment.