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

Commit f9baec9

Browse files
vexilligerahaojin2
authored andcommitted
[Numpy] implement np.column_stack (#16594)
* 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
1 parent a6a9706 commit f9baec9

File tree

9 files changed

+452
-8
lines changed

9 files changed

+452
-8
lines changed

python/mxnet/ndarray/numpy/_op.py

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,12 @@
3434
'log1p', 'rint', 'radians', 'reciprocal', 'square', 'negative', 'fix', 'ceil', 'floor',
3535
'trunc', 'logical_not', 'arcsinh', 'arccosh', 'arctanh', 'tensordot', 'histogram', 'eye',
3636
'linspace', 'logspace', 'expand_dims', 'tile', 'arange', 'split', 'vsplit', 'concatenate',
37-
'stack', 'vstack', 'dstack', 'mean', 'maximum', 'minimum', 'swapaxes', 'clip', 'argmax', 'argmin',
38-
'std', 'var', 'indices', 'copysign', 'ravel', 'hanning', 'hamming', 'blackman', 'flip',
37+
'stack', 'vstack', 'column_stack', 'dstack', 'mean', 'maximum', 'minimum', 'swapaxes', 'clip', 'argmax',
38+
'argmin', 'std', 'var', 'indices', 'copysign', 'ravel', 'hanning', 'hamming', 'blackman', 'flip',
3939
'around', 'hypot', 'rad2deg', 'deg2rad', 'unique', 'lcm', 'tril', 'identity', 'take',
4040
'ldexp', 'vdot', 'inner', 'outer', 'equal', 'not_equal', 'greater', 'less', 'greater_equal', 'less_equal',
4141
'hsplit', 'rot90', 'einsum', 'true_divide', 'nonzero', 'shares_memory', 'may_share_memory', 'diff']
4242

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

30063005

3006+
@set_module('mxnet.ndarray.numpy')
3007+
def column_stack(tup):
3008+
"""
3009+
Stack 1-D arrays as columns into a 2-D array.
3010+
Take a sequence of 1-D arrays and stack them as columns
3011+
to make a single 2-D array. 2-D arrays are stacked as-is,
3012+
just like with `hstack`. 1-D arrays are turned into 2-D columns
3013+
first.
3014+
3015+
Returns
3016+
--------
3017+
stacked : 2-D array
3018+
The array formed by stacking the given arrays.
3019+
3020+
See Also
3021+
--------
3022+
stack, hstack, vstack, concatenate
3023+
3024+
Examples
3025+
--------
3026+
>>> a = np.array((1,2,3))
3027+
>>> b = np.array((2,3,4))
3028+
>>> np.column_stack((a,b))
3029+
array([[1., 2.],
3030+
[2., 3.],
3031+
[3., 4.]])
3032+
"""
3033+
return _npi.column_stack(*tup)
3034+
3035+
30073036
@set_module('mxnet.ndarray.numpy')
30083037
def dstack(arrays):
30093038
"""

python/mxnet/numpy/multiarray.py

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@
5151
'degrees', 'log2', 'log1p', 'rint', 'radians', 'reciprocal', 'square', 'negative',
5252
'fix', 'ceil', 'floor', 'trunc', 'logical_not', 'arcsinh', 'arccosh', 'arctanh',
5353
'tensordot', 'histogram', 'eye', 'linspace', 'logspace', 'expand_dims', 'tile', 'arange',
54-
'split', 'vsplit', 'concatenate', 'stack', 'vstack', 'dstack', 'mean', 'maximum', 'minimum',
54+
'split', 'vsplit', 'concatenate', 'stack', 'vstack', 'column_stack', 'dstack', 'mean', 'maximum', 'minimum',
5555
'swapaxes', 'clip', 'argmax', 'argmin', 'std', 'var', 'indices', 'copysign', 'ravel', 'hanning', 'hamming',
5656
'blackman', 'flip', 'around', 'arctan2', 'hypot', 'rad2deg', 'deg2rad', 'unique', 'lcm', 'tril',
5757
'identity', 'take', 'ldexp', 'vdot', 'inner', 'outer', 'equal', 'not_equal', 'greater', 'less',
@@ -4904,6 +4904,42 @@ def vstack(arrays, out=None):
49044904
return _mx_nd_np.vstack(arrays)
49054905

49064906

4907+
@set_module('mxnet.numpy')
4908+
def column_stack(tup):
4909+
"""
4910+
Stack 1-D arrays as columns into a 2-D array.
4911+
4912+
Take a sequence of 1-D arrays and stack them as columns
4913+
to make a single 2-D array. 2-D arrays are stacked as-is,
4914+
just like with `hstack`. 1-D arrays are turned into 2-D columns
4915+
first.
4916+
4917+
Parameters
4918+
----------
4919+
tup : sequence of 1-D or 2-D arrays.
4920+
Arrays to stack. All of them must have the same first dimension.
4921+
4922+
Returns
4923+
--------
4924+
stacked : 2-D array
4925+
The array formed by stacking the given arrays.
4926+
4927+
See Also
4928+
--------
4929+
stack, hstack, vstack, concatenate
4930+
4931+
Examples
4932+
--------
4933+
>>> a = np.array((1,2,3))
4934+
>>> b = np.array((2,3,4))
4935+
>>> np.column_stack((a,b))
4936+
array([[1., 2.],
4937+
[2., 3.],
4938+
[3., 4.]])
4939+
"""
4940+
return _mx_nd_np.column_stack(tup)
4941+
4942+
49074943
@set_module('mxnet.numpy')
49084944
def dstack(arrays):
49094945
"""

python/mxnet/numpy_dispatch_protocol.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ def _run_with_array_ufunc_proto(*args, **kwargs):
121121
'var',
122122
'vdot',
123123
'vstack',
124+
'column_stack',
124125
'zeros_like',
125126
'linalg.norm',
126127
'trace',

python/mxnet/symbol/numpy/_symbol.py

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@
3636
'rint', 'radians', 'reciprocal', 'square', 'negative', 'fix', 'ceil', 'floor',
3737
'trunc', 'logical_not', 'arcsinh', 'arccosh', 'arctanh', 'tensordot', 'histogram', 'eye',
3838
'linspace', 'logspace', 'expand_dims', 'tile', 'arange', 'split', 'vsplit', 'concatenate',
39-
'stack', 'vstack', 'dstack', 'mean', 'maximum', 'minimum', 'swapaxes', 'clip', 'argmax', 'argmin',
40-
'std', 'var', 'indices', 'copysign', 'ravel', 'hanning', 'hamming', 'blackman', 'flip',
39+
'stack', 'vstack', 'column_stack', 'dstack', 'mean', 'maximum', 'minimum', 'swapaxes', 'clip', 'argmax',
40+
'argmin', 'std', 'var', 'indices', 'copysign', 'ravel', 'hanning', 'hamming', 'blackman', 'flip',
4141
'around', 'hypot', 'rad2deg', 'deg2rad', 'unique', 'lcm', 'tril', 'identity', 'take',
4242
'ldexp', 'vdot', 'inner', 'outer', 'equal', 'not_equal', 'greater', 'less', 'greater_equal',
4343
'less_equal', 'hsplit', 'rot90', 'einsum', 'true_divide', 'shares_memory', 'may_share_memory', 'diff']
@@ -3072,6 +3072,42 @@ def get_list(arrays):
30723072
return _npi.vstack(*arrays)
30733073

30743074

3075+
@set_module('mxnet.symbol.numpy')
3076+
def column_stack(tup):
3077+
"""
3078+
Stack 1-D arrays as columns into a 2-D array.
3079+
3080+
Take a sequence of 1-D arrays and stack them as columns
3081+
to make a single 2-D array. 2-D arrays are stacked as-is,
3082+
just like with `hstack`. 1-D arrays are turned into 2-D columns
3083+
first.
3084+
3085+
Parameters
3086+
----------
3087+
tup : sequence of 1-D or 2-D arrays.
3088+
Arrays to stack. All of them must have the same first dimension.
3089+
3090+
Returns
3091+
-------
3092+
stacked : 2-D array
3093+
The array formed by stacking the given arrays.
3094+
3095+
See Also
3096+
--------
3097+
stack, hstack, vstack, concatenate
3098+
3099+
Examples
3100+
--------
3101+
>>> a = np.array((1,2,3))
3102+
>>> b = np.array((2,3,4))
3103+
>>> np.column_stack((a,b))
3104+
array([[1., 2.],
3105+
[2., 3.],
3106+
[3., 4.]])
3107+
"""
3108+
return _npi.column_stack(*tup)
3109+
3110+
30753111
@set_module('mxnet.symbol.numpy')
30763112
def dstack(arrays):
30773113
"""

src/operator/numpy/np_matrix_op-inl.h

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,14 @@ struct NumpyVstackParam : public dmlc::Parameter<NumpyVstackParam> {
5252
}
5353
};
5454

55+
struct NumpyColumnStackParam : public dmlc::Parameter<NumpyColumnStackParam> {
56+
int num_args;
57+
DMLC_DECLARE_PARAMETER(NumpyColumnStackParam) {
58+
DMLC_DECLARE_FIELD(num_args).set_lower_bound(1)
59+
.describe("Number of inputs to be column stacked");
60+
}
61+
};
62+
5563
struct NumpyReshapeParam : public dmlc::Parameter<NumpyReshapeParam> {
5664
mxnet::TShape newshape;
5765
std::string order;
@@ -124,6 +132,78 @@ void NumpyTranspose(const nnvm::NodeAttrs& attrs,
124132
}
125133
}
126134

135+
template<typename xpu>
136+
void NumpyColumnStackForward(const nnvm::NodeAttrs& attrs,
137+
const OpContext& ctx,
138+
const std::vector<TBlob>& inputs,
139+
const std::vector<OpReqType>& req,
140+
const std::vector<TBlob>& outputs) {
141+
using namespace mshadow;
142+
using namespace mshadow_op;
143+
144+
const NumpyColumnStackParam& param = nnvm::get<NumpyColumnStackParam>(attrs.parsed);
145+
CHECK_EQ(inputs.size(), param.num_args);
146+
CHECK_EQ(outputs.size(), 1);
147+
CHECK_EQ(req.size(), 1);
148+
149+
// reshape if necessary
150+
std::vector<TBlob> data(param.num_args);
151+
for (int i = 0; i < param.num_args; i++) {
152+
if (inputs[i].shape_.ndim() == 0 || inputs[i].shape_.ndim() == 1) {
153+
TShape shape = Shape2(inputs[i].shape_.Size(), 1);
154+
data[i] = inputs[i].reshape(shape);
155+
} else {
156+
data[i] = inputs[i];
157+
}
158+
}
159+
160+
// initialize ConcatOp
161+
ConcatParam cparam;
162+
cparam.num_args = param.num_args;
163+
cparam.dim = 1;
164+
MSHADOW_TYPE_SWITCH(inputs[0].type_flag_, DType, {
165+
ConcatOp<xpu, DType> op;
166+
op.Init(cparam);
167+
op.Forward(ctx, data, req, outputs);
168+
});
169+
}
170+
171+
template<typename xpu>
172+
void NumpyColumnStackBackward(const nnvm::NodeAttrs& attrs,
173+
const OpContext& ctx,
174+
const std::vector<TBlob>& inputs,
175+
const std::vector<OpReqType>& req,
176+
const std::vector<TBlob>& outputs) {
177+
using namespace mshadow;
178+
using namespace mshadow_op;
179+
180+
const NumpyColumnStackParam& param = nnvm::get<NumpyColumnStackParam>(attrs.parsed);
181+
CHECK_EQ(inputs.size(), 1);
182+
CHECK_EQ(outputs.size(), param.num_args);
183+
CHECK_EQ(req.size(), param.num_args);
184+
185+
// reshape if necessary
186+
std::vector<TBlob> data(param.num_args);
187+
for (int i = 0; i < param.num_args; i++) {
188+
if (outputs[i].shape_.ndim() == 0 || outputs[i].shape_.ndim() == 1) {
189+
TShape shape = Shape2(outputs[i].shape_.Size(), 1);
190+
data[i] = outputs[i].reshape(shape);
191+
} else {
192+
data[i] = outputs[i];
193+
}
194+
}
195+
196+
// initialize ConcatOp
197+
ConcatParam cparam;
198+
cparam.num_args = param.num_args;
199+
cparam.dim = 1;
200+
MSHADOW_TYPE_SWITCH(inputs[0].type_flag_, DType, {
201+
ConcatOp<xpu, DType> op;
202+
op.Init(cparam);
203+
op.Backward(ctx, inputs[0], req, data);
204+
});
205+
}
206+
127207
template<typename xpu>
128208
void NumpyVstackForward(const nnvm::NodeAttrs& attrs,
129209
const OpContext& ctx,

0 commit comments

Comments
 (0)