diff --git a/_doc/sphinxdoc/source/api/npy.rst b/_doc/sphinxdoc/source/api/npy.rst index 4619fac11..73aeb64ea 100644 --- a/_doc/sphinxdoc/source/api/npy.rst +++ b/_doc/sphinxdoc/source/api/npy.rst @@ -97,6 +97,8 @@ Available numpy functions implemented with ONNX operators .. autosignature:: mlprodict.npy.numpy_onnx_impl.atanh +.. autosignature:: mlprodict.npy.numpy_onnx_impl.ceil + .. autosignature:: mlprodict.npy.numpy_onnx_impl.cos .. autosignature:: mlprodict.npy.numpy_onnx_impl.cosh @@ -117,6 +119,8 @@ Available numpy functions implemented with ONNX operators .. autosignature:: mlprodict.npy.numpy_onnx_impl.relu +.. autosignature:: mlprodict.npy.numpy_onnx_impl.round + .. autosignature:: mlprodict.npy.numpy_onnx_impl.sign .. autosignature:: mlprodict.npy.numpy_onnx_impl.sin @@ -156,6 +160,8 @@ ONNX functions executed python ONNX runtime .. autosignature:: mlprodict.npy.numpy_onnx_pyrt.atanh +.. autosignature:: mlprodict.npy.numpy_onnx_pyrt.ceil + .. autosignature:: mlprodict.npy.numpy_onnx_pyrt.cos .. autosignature:: mlprodict.npy.numpy_onnx_pyrt.cosh @@ -176,6 +182,8 @@ ONNX functions executed python ONNX runtime .. autosignature:: mlprodict.npy.numpy_onnx_pyrt.relu +.. autosignature:: mlprodict.npy.numpy_onnx_pyrt.round + .. autosignature:: mlprodict.npy.numpy_onnx_pyrt.sign .. autosignature:: mlprodict.npy.numpy_onnx_pyrt.sin diff --git a/_unittests/ut_npy/test_numpy_onnx_pyrt.py b/_unittests/ut_npy/test_numpy_onnx_pyrt.py index 75f79393d..4684a58d9 100644 --- a/_unittests/ut_npy/test_numpy_onnx_pyrt.py +++ b/_unittests/ut_npy/test_numpy_onnx_pyrt.py @@ -100,6 +100,10 @@ def test_atanh_float32(self): x = numpy.array([[0.5, 0.1], [-0.5, -0.1]], dtype=numpy.float32) self.common_test1(x, numpy.arctanh, nxnpy.atanh, numpy.float32) + def test_ceil_float32(self): + x = numpy.array([[0.5, 0.1], [-0.5, -0.1]], dtype=numpy.float32) + self.common_test1(x, numpy.ceil, nxnpy.ceil, numpy.float32) + def test_cos_float32(self): x = numpy.array([[0.5, 0.1], [-0.5, -0.1]], dtype=numpy.float32) self.common_test1(x, numpy.cos, nxnpy.cos, numpy.float32) @@ -152,6 +156,10 @@ def test_relu_float64(self): self.common_test1(x, lambda x: numpy.maximum(x, 0), nxnpy.relu, numpy.float64) + def test_round_float64(self): + x = numpy.array([[6.1, 5], [3.5, -7.8]], dtype=numpy.float64) + self.common_test1(x, numpy.round, nxnpy.round, numpy.float64) + def test_sign_float64(self): x = numpy.array([[-6.1, 5], [3.5, 7.8]], dtype=numpy.float64) self.common_test1(x, numpy.sign, nxnpy.sign, numpy.float64) diff --git a/_unittests/ut_npy/test_onnx_variable_ort.py b/_unittests/ut_npy/test_onnx_variable_ort.py index beabd873e..fbd2471f7 100644 --- a/_unittests/ut_npy/test_onnx_variable_ort.py +++ b/_unittests/ut_npy/test_onnx_variable_ort.py @@ -477,12 +477,12 @@ def test_ort_abs_set3(self): def test_ort_log(self): x = numpy.array([[6.1, 5], [3.5, 7.8]], dtype=numpy.float32) y = test_log(x) - self.assertEqualArray(y, numpy.log(x)) + self.assertEqualArray(y, numpy.log(x), decimal=6) def test_ort_abs_log_multi(self): x = numpy.array([[6.1, -5], [-3.5, 7.8]], dtype=numpy.float32) y = test_abs_log_multi(x) - self.assertEqualArray(y, numpy.log(numpy.abs(x))) + self.assertEqualArray(y, numpy.log(numpy.abs(x)), decimal=6) def test_ort_abs_shape(self): x = numpy.array([[6.1, -5], [3.5, -7.8]], dtype=numpy.float32) diff --git a/_unittests/ut_onnxrt/test_onnxrt_python_runtime_.py b/_unittests/ut_onnxrt/test_onnxrt_python_runtime_.py index 736f3aba0..feabf8c54 100644 --- a/_unittests/ut_onnxrt/test_onnxrt_python_runtime_.py +++ b/_unittests/ut_onnxrt/test_onnxrt_python_runtime_.py @@ -51,6 +51,7 @@ OnnxReduceSum, OnnxReduceSumApi11, OnnxReduceSum_11, OnnxReduceSum_1, OnnxReduceSumSquare, OnnxRelu, OnnxReshape, + OnnxRound, OnnxScatterElements, OnnxShape, OnnxSlice, OnnxSigmoid, OnnxSign, OnnxSin, OnnxSinh, OnnxSize, OnnxSoftmax, @@ -2335,6 +2336,10 @@ def test_onnxt_runtime_relu(self): self.common_test_onnxt_runtime_unary( OnnxRelu, lambda x: numpy.maximum(x, 0)) + @wraplog() + def test_onnxt_runtime_round(self): + self.common_test_onnxt_runtime_unary(OnnxRound, numpy.round) + @ignore_warnings(category=(RuntimeWarning, DeprecationWarning)) @wraplog() def test_onnxt_runtime_reshape(self): diff --git a/mlprodict/npy/numpy_onnx_impl.py b/mlprodict/npy/numpy_onnx_impl.py index 429b98659..fc935a6b1 100644 --- a/mlprodict/npy/numpy_onnx_impl.py +++ b/mlprodict/npy/numpy_onnx_impl.py @@ -12,6 +12,7 @@ OnnxArgMin, OnnxAsin, OnnxAsinh, OnnxAtan, OnnxAtanh, + OnnxCeil, OnnxCos, OnnxCosh, OnnxErf, OnnxExp, @@ -24,6 +25,7 @@ OnnxReduceProd, OnnxReduceSum, OnnxRelu, + OnnxRound, OnnxSign, OnnxSin, OnnxSinh, OnnxSqrt, @@ -99,6 +101,11 @@ def atanh(x): return OnnxVar(x, op=OnnxAtanh) +def ceil(x): + "See :epkg:`numpy:ceil`." + return OnnxVar(x, op=OnnxCeil) + + def cos(x): "See :epkg:`numpy:cos`." return OnnxVar(x, op=OnnxCos) @@ -157,6 +164,11 @@ def reciprocal(x): return OnnxVar(x, op=OnnxReciprocal) +def round(x): + "See :epkg:`numpy:round`." + return OnnxVar(x, op=OnnxRound) + + def sign(x): "See :epkg:`numpy:sign`." return OnnxVar(x, op=OnnxSign) diff --git a/mlprodict/npy/numpy_onnx_pyrt.py b/mlprodict/npy/numpy_onnx_pyrt.py index 3db2ab6ec..a4c45148e 100644 --- a/mlprodict/npy/numpy_onnx_pyrt.py +++ b/mlprodict/npy/numpy_onnx_pyrt.py @@ -20,6 +20,7 @@ asinh as nx_asinh, atan as nx_atan, atanh as nx_atanh, + ceil as nx_ceil, cos as nx_cos, cosh as nx_cosh, erf as nx_erf, @@ -30,6 +31,7 @@ prod as nx_prod, reciprocal as nx_reciprocal, relu as nx_relu, + round as nx_round, sign as nx_sign, sin as nx_sin, sinh as nx_sinh, @@ -107,6 +109,12 @@ def atanh(x): return nx_atanh(x) +@onnxnumpy_np(signature=NDArraySameTypeSameShape("floats")) +def ceil(x): + "ceil" + return nx_ceil(x) + + @onnxnumpy_np(signature=NDArraySameTypeSameShape("floats")) def cos(x): "cos" @@ -167,6 +175,12 @@ def relu(x): return nx_relu(x) +@onnxnumpy_np(signature=NDArraySameTypeSameShape("floats")) +def round(x): + "round" + return nx_round(x) + + @onnxnumpy_np(signature=NDArraySameTypeSameShape("floats")) def sign(x): "sign" diff --git a/mlprodict/onnxrt/ops_cpu/_op_list.py b/mlprodict/onnxrt/ops_cpu/_op_list.py index 05eebbb3e..31f2d1ec7 100644 --- a/mlprodict/onnxrt/ops_cpu/_op_list.py +++ b/mlprodict/onnxrt/ops_cpu/_op_list.py @@ -87,6 +87,7 @@ from .op_reduce_sum_square import ReduceSumSquare from .op_relu import Relu from .op_reshape import Reshape, Reshape_5, Reshape_13, Reshape_14 +from .op_round import Round from .op_rnn import RNN from .op_scaler import Scaler from .op_scan import Scan diff --git a/mlprodict/onnxrt/ops_cpu/op_round.py b/mlprodict/onnxrt/ops_cpu/op_round.py new file mode 100644 index 000000000..3f69f12c4 --- /dev/null +++ b/mlprodict/onnxrt/ops_cpu/op_round.py @@ -0,0 +1,26 @@ +# -*- encoding: utf-8 -*- +# pylint: disable=E0203,E1101,C0111 +""" +@file +@brief Runtime operator. +""" +import numpy +from ._op import OpRunUnaryNum + + +class Round(OpRunUnaryNum): + + def __init__(self, onnx_node, desc=None, **options): + OpRunUnaryNum.__init__(self, onnx_node, desc=desc, + **options) + + def _run(self, x): # pylint: disable=W0221 + if self.inplaces.get(0, False): + return self._run_inplace(x) + return (numpy.round(x), ) + + def _run_inplace(self, x): + return (numpy.round(x, out=x), ) + + def to_python(self, inputs): + return self._to_python_numpy(inputs, self.__class__.__name__.lower())