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

Commit 6c42992

Browse files
JiangZhaohhaojin2
authored andcommitted
[numpy] add numpy operator : append (#16564)
* add operator : append ; fix op concatenate when axis = None * pylint disable remove mistake disable pylint
1 parent 9f6e819 commit 6c42992

File tree

9 files changed

+458
-53
lines changed

9 files changed

+458
-53
lines changed

python/mxnet/ndarray/numpy/_op.py

Lines changed: 59 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
'absolute', 'exp', 'expm1', 'arcsin', 'arccos', 'arctan', 'sign', 'log', 'degrees', 'log2',
3434
'log1p', 'rint', 'radians', 'reciprocal', 'square', 'negative', 'fix', 'ceil', 'floor',
3535
'trunc', 'logical_not', 'arcsinh', 'arccosh', 'arctanh', 'tensordot', 'histogram', 'eye',
36-
'linspace', 'logspace', 'expand_dims', 'tile', 'arange', 'split', 'vsplit', 'concatenate',
36+
'linspace', 'logspace', 'expand_dims', 'tile', 'arange', 'split', 'vsplit', 'concatenate', 'append',
3737
'stack', 'vstack', 'column_stack', 'dstack', 'mean', 'maximum', 'minimum', 'swapaxes', 'clip', 'argmax',
3838
'argmin', 'std', 'var', 'indices', 'copysign', 'ravel', 'hanning', 'hamming', 'blackman', 'flip',
3939
'around', 'hypot', 'rad2deg', 'deg2rad', 'unique', 'lcm', 'tril', 'identity', 'take',
@@ -2919,8 +2919,64 @@ def concatenate(seq, axis=0, out=None):
29192919
-------
29202920
res : ndarray
29212921
The concatenated array.
2922+
2923+
Examples
2924+
--------
2925+
>>> a = np.array([[1, 2], [3, 4]])
2926+
>>> b = np.array([[5, 6]])
2927+
>>> np.concatenate((a, b), axis=0)
2928+
array([[1., 2.],
2929+
[3., 4.],
2930+
[5., 6.]])
2931+
2932+
>>> np.concatenate((a, b), axis=None)
2933+
array([1., 2., 3., 4., 5., 6.])
2934+
2935+
>>> np.concatenate((a, b.T), axis=1)
2936+
array([[1., 2., 5.],
2937+
[3., 4., 6.]])
2938+
"""
2939+
return _npi.concatenate(*seq, axis=axis, out=out)
2940+
2941+
2942+
@set_module('mxnet.ndarray.numpy')
2943+
def append(arr, values, axis=None): # pylint: disable=redefined-outer-name
2944+
"""
2945+
Append values to the end of an array.
2946+
2947+
Parameters
2948+
----------
2949+
arr : ndarray
2950+
Values are appended to a copy of this array.
2951+
values : ndarray
2952+
These values are appended to a copy of `arr`. It must be of the
2953+
correct shape (the same shape as `arr`, excluding `axis`). If
2954+
`axis` is not specified, `values` can be any shape and will be
2955+
flattened before use.
2956+
axis : int, optional
2957+
The axis along which `values` are appended. If `axis` is not
2958+
given, both `arr` and `values` are flattened before use.
2959+
2960+
Returns
2961+
-------
2962+
append : ndarray
2963+
A copy of `arr` with `values` appended to `axis`. Note that
2964+
`append` does not occur in-place: a new array is allocated and
2965+
filled. If `axis` is None, `out` is a flattened array.
2966+
2967+
Examples
2968+
--------
2969+
>>> np.append(np.array([1, 2, 3]), np.array([[4, 5, 6],[7, 8, 9]]))
2970+
array([1., 2., 3., 4., 5., 6., 7., 8., 9.])
2971+
2972+
When `axis` is specified, `values` must have the correct shape.
2973+
2974+
>>> np.append(np.array([[1, 2, 3], [4, 5, 6]]), np.array([[7, 8, 9]]), axis=0)
2975+
array([[1., 2., 3.],
2976+
[4., 5., 6.],
2977+
[7., 8., 9.]])
29222978
"""
2923-
return _npi.concatenate(*seq, dim=axis, out=out)
2979+
return _npi.concatenate(arr, values, axis=axis, out=None)
29242980

29252981

29262982
@set_module('mxnet.ndarray.numpy')
@@ -5014,7 +5070,7 @@ def may_share_memory(a, b, max_work=None):
50145070
return _npi.share_memory(a, b).item()
50155071

50165072

5017-
def diff(a, n=1, axis=-1, prepend=None, append=None):
5073+
def diff(a, n=1, axis=-1, prepend=None, append=None): # pylint: disable=redefined-outer-name
50185074
r"""
50195075
numpy.diff(a, n=1, axis=-1, prepend=<no value>, append=<no value>)
50205076

python/mxnet/numpy/multiarray.py

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@
4949
'mod', 'remainder', 'power', 'arctan2', 'sin', 'cos', 'tan', 'sinh', 'cosh', 'tanh', 'log10',
5050
'sqrt', 'cbrt', 'abs', 'absolute', 'exp', 'expm1', 'arcsin', 'arccos', 'arctan', 'sign', 'log',
5151
'degrees', 'log2', 'log1p', 'rint', 'radians', 'reciprocal', 'square', 'negative',
52-
'fix', 'ceil', 'floor', 'trunc', 'logical_not', 'arcsinh', 'arccosh', 'arctanh',
52+
'fix', 'ceil', 'floor', 'trunc', 'logical_not', 'arcsinh', 'arccosh', 'arctanh', 'append',
5353
'tensordot', 'histogram', 'eye', 'linspace', 'logspace', 'expand_dims', 'tile', 'arange',
5454
'split', 'vsplit', 'concatenate', 'stack', 'vstack', 'column_stack', 'dstack', 'mean', 'maximum', 'minimum',
5555
'swapaxes', 'clip', 'argmax', 'argmin', 'std', 'var', 'indices', 'copysign', 'ravel', 'hanning', 'hamming',
@@ -4803,10 +4803,53 @@ def concatenate(seq, axis=0, out=None):
48034803
>>> np.concatenate((a, b.T), axis=1)
48044804
array([[1., 2., 5.],
48054805
[3., 4., 6.]])
4806+
4807+
>>> np.concatenate((a, b), axis=None)
4808+
array([1., 2., 3., 4., 5., 6.])
48064809
"""
48074810
return _mx_nd_np.concatenate(seq, axis=axis, out=out)
48084811

48094812

4813+
@set_module('mxnet.numpy')
4814+
def append(arr, values, axis=None): # pylint: disable=redefined-outer-name
4815+
"""
4816+
Append values to the end of an array.
4817+
4818+
Parameters
4819+
----------
4820+
arr : ndarray
4821+
Values are appended to a copy of this array.
4822+
values : ndarray
4823+
These values are appended to a copy of `arr`. It must be of the
4824+
correct shape (the same shape as `arr`, excluding `axis`). If
4825+
`axis` is not specified, `values` can be any shape and will be
4826+
flattened before use.
4827+
axis : int, optional
4828+
The axis along which `values` are appended. If `axis` is not
4829+
given, both `arr` and `values` are flattened before use.
4830+
4831+
Returns
4832+
-------
4833+
append : ndarray
4834+
A copy of `arr` with `values` appended to `axis`. Note that
4835+
`append` does not occur in-place: a new array is allocated and
4836+
filled. If `axis` is None, `out` is a flattened array.
4837+
4838+
Examples
4839+
--------
4840+
>>> np.append(np.array([1, 2, 3]), np.array([[4, 5, 6],[7, 8, 9]]))
4841+
array([1., 2., 3., 4., 5., 6., 7., 8., 9.])
4842+
4843+
When `axis` is specified, `values` must have the correct shape.
4844+
4845+
>>> np.append(np.array([[1, 2, 3], [4, 5, 6]]), np.array([[7, 8, 9]]), axis=0)
4846+
array([[1., 2., 3.],
4847+
[4., 5., 6.],
4848+
[7., 8., 9.]])
4849+
"""
4850+
return _mx_nd_np.append(arr, values, axis=axis)
4851+
4852+
48104853
@set_module('mxnet.numpy')
48114854
def stack(arrays, axis=0, out=None):
48124855
"""Join a sequence of arrays along a new axis.
@@ -7018,7 +7061,7 @@ def may_share_memory(a, b, max_work=None):
70187061
return _mx_nd_np.may_share_memory(a, b, max_work)
70197062

70207063

7021-
def diff(a, n=1, axis=-1, prepend=None, append=None):
7064+
def diff(a, n=1, axis=-1, prepend=None, append=None): # pylint: disable=redefined-outer-name
70227065
r"""
70237066
numpy.diff(a, n=1, axis=-1, prepend=<no value>, append=<no value>)
70247067

python/mxnet/numpy_dispatch_protocol.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ def _run_with_array_ufunc_proto(*args, **kwargs):
8686
'argmin',
8787
'argmax',
8888
'around',
89+
'append',
8990
'broadcast_arrays',
9091
'broadcast_to',
9192
'clip',

python/mxnet/symbol/numpy/_symbol.py

Lines changed: 61 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
'expm1', 'arcsin', 'arccos', 'arctan', 'sign', 'log', 'degrees', 'log2', 'log1p',
3636
'rint', 'radians', 'reciprocal', 'square', 'negative', 'fix', 'ceil', 'floor',
3737
'trunc', 'logical_not', 'arcsinh', 'arccosh', 'arctanh', 'tensordot', 'histogram', 'eye',
38-
'linspace', 'logspace', 'expand_dims', 'tile', 'arange', 'split', 'vsplit', 'concatenate',
38+
'linspace', 'logspace', 'expand_dims', 'tile', 'arange', 'split', 'vsplit', 'concatenate', 'append',
3939
'stack', 'vstack', 'column_stack', 'dstack', 'mean', 'maximum', 'minimum', 'swapaxes', 'clip', 'argmax',
4040
'argmin', 'std', 'var', 'indices', 'copysign', 'ravel', 'hanning', 'hamming', 'blackman', 'flip',
4141
'around', 'hypot', 'rad2deg', 'deg2rad', 'unique', 'lcm', 'tril', 'identity', 'take',
@@ -2992,6 +2992,7 @@ def vsplit(ary, indices_or_sections):
29922992
@set_module('mxnet.symbol.numpy')
29932993
def concatenate(seq, axis=0, out=None):
29942994
"""Join a sequence of arrays along an existing axis.
2995+
29952996
Parameters
29962997
----------
29972998
a1, a2, ... : sequence of array_like
@@ -3004,12 +3005,69 @@ def concatenate(seq, axis=0, out=None):
30043005
If provided, the destination to place the result. The shape must be
30053006
correct, matching that of what concatenate would have returned if no
30063007
out argument were specified.
3008+
30073009
Returns
30083010
-------
30093011
res : ndarray
30103012
The concatenated array.
3013+
3014+
Examples
3015+
--------
3016+
>>> a = np.array([[1, 2], [3, 4]])
3017+
>>> b = np.array([[5, 6]])
3018+
>>> np.concatenate((a, b), axis=0)
3019+
array([[1., 2.],
3020+
[3., 4.],
3021+
[5., 6.]])
3022+
3023+
>>> np.concatenate((a, b), axis=None)
3024+
array([1., 2., 3., 4., 5., 6.])
3025+
3026+
>>> np.concatenate((a, b.T), axis=1)
3027+
array([[1., 2., 5.],
3028+
[3., 4., 6.]])
3029+
"""
3030+
return _npi.concatenate(*seq, axis=axis, out=out)
3031+
3032+
3033+
@set_module('mxnet.symbol.numpy')
3034+
def append(arr, values, axis=None): # pylint: disable=redefined-outer-name
3035+
"""
3036+
Append values to the end of an array.
3037+
3038+
Parameters
3039+
----------
3040+
arr : ndarray
3041+
Values are appended to a copy of this array.
3042+
values : ndarray
3043+
These values are appended to a copy of `arr`. It must be of the
3044+
correct shape (the same shape as `arr`, excluding `axis`). If
3045+
`axis` is not specified, `values` can be any shape and will be
3046+
flattened before use.
3047+
axis : int, optional
3048+
The axis along which `values` are appended. If `axis` is not
3049+
given, both `arr` and `values` are flattened before use.
3050+
3051+
Returns
3052+
-------
3053+
append : ndarray
3054+
A copy of `arr` with `values` appended to `axis`. Note that
3055+
`append` does not occur in-place: a new array is allocated and
3056+
filled. If `axis` is None, `out` is a flattened array.
3057+
3058+
Examples
3059+
--------
3060+
>>> np.append(np.array([1, 2, 3]), np.array([[4, 5, 6],[7, 8, 9]]))
3061+
array([1., 2., 3., 4., 5., 6., 7., 8., 9.])
3062+
3063+
When `axis` is specified, `values` must have the correct shape.
3064+
3065+
>>> np.append(np.array([[1, 2, 3], [4, 5, 6]]), np.array([[7, 8, 9]]), axis=0)
3066+
array([[1., 2., 3.],
3067+
[4., 5., 6.],
3068+
[7., 8., 9.]])
30113069
"""
3012-
return _npi.concatenate(*seq, dim=axis, out=out)
3070+
return _npi.concatenate(arr, values, axis=axis, out=None)
30133071

30143072

30153073
@set_module('mxnet.symbol.numpy')
@@ -4665,7 +4723,7 @@ def may_share_memory(a, b, max_work=None):
46654723
return _npi.share_memory(a, b)
46664724

46674725

4668-
def diff(a, n=1, axis=-1, prepend=None, append=None):
4726+
def diff(a, n=1, axis=-1, prepend=None, append=None): # pylint: disable=redefined-outer-name
46694727
r"""
46704728
numpy.diff(a, n=1, axis=-1, prepend=<no value>, append=<no value>)
46714729

src/operator/numpy/np_matrix_op-inl.h

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -864,6 +864,87 @@ inline void HSplitOpBackward(const nnvm::NodeAttrs &attrs,
864864
}
865865
SplitOpBackwardImpl<xpu>(attrs, ctx, inputs, req, outputs, real_axis);
866866
}
867+
868+
struct NumpyConcatenateParam : public dmlc::Parameter<NumpyConcatenateParam> {
869+
int num_args;
870+
dmlc::optional<int> axis;
871+
DMLC_DECLARE_PARAMETER(NumpyConcatenateParam) {
872+
DMLC_DECLARE_FIELD(num_args)
873+
.set_lower_bound(1)
874+
.describe("Number of inputs to be concated.");
875+
DMLC_DECLARE_FIELD(axis)
876+
.set_default(dmlc::optional<int>(0))
877+
.describe("The axis along which `values` are appended. If `axis` is not"
878+
"given, both `arr` and `values` are flattened before use.");
879+
}
880+
};
881+
882+
template<typename xpu>
883+
void NumpyConcatenateForward(const nnvm::NodeAttrs& attrs,
884+
const OpContext& ctx,
885+
const std::vector<TBlob>& inputs,
886+
const std::vector<OpReqType>& req,
887+
const std::vector<TBlob>& outputs) {
888+
using namespace mshadow;
889+
using namespace mshadow_op;
890+
891+
const NumpyConcatenateParam& param = nnvm::get<NumpyConcatenateParam>(attrs.parsed);
892+
CHECK_EQ(inputs.size(), param.num_args);
893+
CHECK_EQ(outputs.size(), 1U);
894+
CHECK_EQ(req.size(), 1U);
895+
896+
std::vector<TBlob> data(param.num_args);
897+
for (int i = 0; i < param.num_args; i++) {
898+
if (!param.axis.has_value()) {
899+
data[i] = inputs[i].reshape(Shape1(inputs[i].shape_.Size()));
900+
} else {
901+
data[i] = inputs[i];
902+
}
903+
}
904+
905+
ConcatParam cparam;
906+
cparam.num_args = param.num_args;
907+
cparam.dim = param.axis.has_value() ? param.axis.value() : 0;
908+
MSHADOW_TYPE_SWITCH(inputs[0].type_flag_, DType, {
909+
ConcatOp<xpu, DType> op;
910+
op.Init(cparam);
911+
op.Forward(ctx, data, req, outputs);
912+
});
913+
}
914+
915+
template<typename xpu>
916+
void NumpyConcatenateBackward(const nnvm::NodeAttrs& attrs,
917+
const OpContext& ctx,
918+
const std::vector<TBlob>& inputs,
919+
const std::vector<OpReqType>& req,
920+
const std::vector<TBlob>& outputs) {
921+
using namespace mshadow;
922+
using namespace mshadow_op;
923+
924+
const NumpyConcatenateParam& param = nnvm::get<NumpyConcatenateParam>(attrs.parsed);
925+
CHECK_EQ(inputs.size(), 1U);
926+
CHECK_EQ(outputs.size(), param.num_args);
927+
CHECK_EQ(req.size(), param.num_args);
928+
929+
std::vector<TBlob> data(param.num_args);
930+
for (int i = 0; i < param.num_args; i++) {
931+
if (!param.axis.has_value()) {
932+
data[i] = outputs[i].reshape(Shape1(outputs[i].shape_.Size()));
933+
} else {
934+
data[i] = outputs[i];
935+
}
936+
}
937+
938+
ConcatParam cparam;
939+
cparam.num_args = param.num_args;
940+
cparam.dim = param.axis.has_value() ? param.axis.value() : 0;
941+
MSHADOW_TYPE_SWITCH(inputs[0].type_flag_, DType, {
942+
ConcatOp<xpu, DType> op;
943+
op.Init(cparam);
944+
op.Backward(ctx, inputs[0], req, data);
945+
});
946+
}
947+
867948
} // namespace op
868949
} // namespace mxnet
869950

0 commit comments

Comments
 (0)