diff --git a/paddle/fluid/operators/activation_op.cc b/paddle/fluid/operators/activation_op.cc index 6dd94e9746e10e7dc6cecbb10037d657ee71f29a..1d0dda7cd66264573ad73cc8f6cfdf39c2ce52fa 100644 --- a/paddle/fluid/operators/activation_op.cc +++ b/paddle/fluid/operators/activation_op.cc @@ -284,6 +284,27 @@ $$out = cosh(x)$$ )DOC"; +UNUSED constexpr char AsinhDoc[] = R"DOC( +Asinh Activation Operator. + +$$out = asinh(x)$$ + +)DOC"; + +UNUSED constexpr char AcoshDoc[] = R"DOC( +Acosh Activation Operator. + +$$out = acosh(x)$$ + +)DOC"; + +UNUSED constexpr char AtanhDoc[] = R"DOC( +Atanh Activation Operator. + +$$out = atanh(x)$$ + +)DOC"; + UNUSED constexpr char RoundDoc[] = R"DOC( The OP rounds the values in the input to the nearest integer value. @@ -832,6 +853,9 @@ REGISTER_ACTIVATION_OP_MAKER(Tan, TanDoc); REGISTER_ACTIVATION_OP_MAKER(Sin, SinDoc); REGISTER_ACTIVATION_OP_MAKER(Sinh, SinhDoc); REGISTER_ACTIVATION_OP_MAKER(Cosh, CoshDoc); +REGISTER_ACTIVATION_OP_MAKER(Acosh, AcoshDoc); +REGISTER_ACTIVATION_OP_MAKER(Asinh, AsinhDoc); +REGISTER_ACTIVATION_OP_MAKER(Atanh, AtanhDoc); REGISTER_ACTIVATION_OP_MAKER(Round, RoundDoc); REGISTER_ACTIVATION_OP_MAKER(Reciprocal, ReciprocalDoc); REGISTER_ACTIVATION_OP_MAKER(Log, LogDoc); diff --git a/paddle/fluid/operators/activation_op.cu b/paddle/fluid/operators/activation_op.cu index a60fea409438d94ea8615a184d7256fedaec6602..4818043b93be2d2ad40aaf7a5c8cc3f13a69c3c7 100644 --- a/paddle/fluid/operators/activation_op.cu +++ b/paddle/fluid/operators/activation_op.cu @@ -473,6 +473,85 @@ struct CudaTanhGradFunctor : public BaseActivationFunctor { static constexpr ActBwdOpFwdDeps FwdDeps() { return kDepOut; } }; +template +struct CudaAcoshFunctor : public BaseActivationFunctor { + using MPType = typename details::MPTypeTrait::Type; + + // Acosh(x) = acosh(x) + __device__ __forceinline__ T operator()(const T& arg_x) const { + MPType x = static_cast(arg_x); + return static_cast(acosh(x)); + } +}; + +template +struct CudaAcoshGradFunctor : public BaseActivationFunctor { + using MPType = typename details::MPTypeTrait::Type; + MPType one = static_cast(1.0f); + // dx = dout * 1 / sqrt(x^2 - 1) + __device__ __forceinline__ T operator()(const T& arg_dout, + const T& arg_x) const { + MPType dout = static_cast(arg_dout); + MPType x = static_cast(arg_x); + return static_cast(dout * one / sqrt(x * x - one)); + } + + static constexpr ActBwdOpFwdDeps FwdDeps() { return kDepX; } +}; + +template +struct CudaAsinhFunctor : public BaseActivationFunctor { + using MPType = typename details::MPTypeTrait::Type; + + // Asinh(x) = asinh(x) + __device__ __forceinline__ T operator()(const T& arg_x) const { + MPType x = static_cast(arg_x); + return static_cast(asinh(x)); + } +}; + +template +struct CudaAsinhGradFunctor : public BaseActivationFunctor { + using MPType = typename details::MPTypeTrait::Type; + MPType one = static_cast(1.0f); + + // dx = dout * 1/sqrt(x^2 + 1) + __device__ __forceinline__ T operator()(const T& arg_dout, + const T& arg_x) const { + MPType dout = static_cast(arg_dout); + MPType x = static_cast(arg_x); + return static_cast(dout * one / sqrt(x * x + one)); + } + + static constexpr ActBwdOpFwdDeps FwdDeps() { return kDepX; } +}; + +template +struct CudaAtanhFunctor : public BaseActivationFunctor { + using MPType = typename details::MPTypeTrait::Type; + + // Atanh(x) = atanh(x) + __device__ __forceinline__ T operator()(const T& arg_x) const { + MPType x = static_cast(arg_x); + return static_cast(atanh(x)); + } +}; + +template +struct CudaAtanhGradFunctor : public BaseActivationFunctor { + using MPType = typename details::MPTypeTrait::Type; + MPType one = static_cast(1.0f); + // dx = dout * 1/(1- x^2) + __device__ __forceinline__ T operator()(const T& arg_dout, + const T& arg_x) const { + MPType dout = static_cast(arg_dout); + MPType x = static_cast(arg_x); + return static_cast(dout * one / (one - x * x)); + } + + static constexpr ActBwdOpFwdDeps FwdDeps() { return kDepX; } +}; + template struct CudaReciprocalFunctor : public BaseActivationFunctor { T one = static_cast(1.0f); @@ -1707,6 +1786,9 @@ REGISTER_OP_CUDA_KERNEL( __macro(asin, Asin, CudaAsinFunctor, CudaAsinGradFunctor); \ __macro(sinh, Sinh, CudaSinhFunctor, CudaSinhGradFunctor); \ __macro(cosh, Cosh, CudaCoshFunctor, CudaCoshGradFunctor); \ + __macro(asinh, Asinh, CudaAsinhFunctor, CudaAsinhGradFunctor); \ + __macro(acosh, Acosh, CudaAcoshFunctor, CudaAcoshGradFunctor); \ + __macro(atanh, Atanh, CudaAtanhFunctor, CudaAtanhGradFunctor); \ __macro(round, Round, CudaRoundFunctor, CudaZeroGradFunctor); \ __macro(reciprocal, Reciprocal, CudaReciprocalFunctor, \ CudaReciprocalGradFunctor); \ diff --git a/paddle/fluid/operators/activation_op.h b/paddle/fluid/operators/activation_op.h index ffd3c434636444a60eeddcb074884e66303cc49b..9ba49e598ed5cb0db85e791cc8fdfb10780c50a1 100644 --- a/paddle/fluid/operators/activation_op.h +++ b/paddle/fluid/operators/activation_op.h @@ -1020,6 +1020,107 @@ struct AtanGradFunctor : public BaseActivationFunctor { static constexpr ActBwdOpFwdDeps FwdDeps() { return kDepX; } }; +template +struct Acosh { + HOSTDEVICE T operator()(const T& val) const { return acosh(val); } +}; + +template <> +struct Acosh { + HOSTDEVICE platform::float16 operator()(const platform::float16& val) const { + return platform::float16(acosh(static_cast(val))); + } +}; + +// Acosh(x) = acosh(x) +template +struct AcoshFunctor : public BaseActivationFunctor { + template + void operator()(Device d, X x, Out out) const { + out.device(d) = x.unaryExpr(Acosh()); + } +}; + +// acosh'(x) = 1/sqrt(x^2 - 1) +template +struct AcoshGradFunctor : public BaseActivationFunctor { + template + void operator()(Device d, X x, Out out, dOut dout, dX dx) const { + dx.device(d) = + dout * static_cast(1) / (x * x - static_cast(1)).sqrt(); + } + + static constexpr ActBwdOpFwdDeps FwdDeps() { return kDepX; } +}; + +template +struct Asinh { + HOSTDEVICE T operator()(const T& val) const { return asinh(val); } +}; + +template <> +struct Asinh { + HOSTDEVICE platform::float16 operator()(const platform::float16& val) const { + return platform::float16(asinh(static_cast(val))); + } +}; + +// Asinh(x) = asinh(x) +template +struct AsinhFunctor : public BaseActivationFunctor { + template + void operator()(Device d, X x, Out out) const { + out.device(d) = x.unaryExpr(Asinh()); + } +}; + +// asinh'(x) = 1/sqrt(x^2 + 1) +template +struct AsinhGradFunctor : public BaseActivationFunctor { + template + void operator()(Device d, X x, Out out, dOut dout, dX dx) const { + dx.device(d) = + dout * static_cast(1) / (x.square() + static_cast(1)).sqrt(); + } + + static constexpr ActBwdOpFwdDeps FwdDeps() { return kDepX; } +}; + +template +struct Atanh { + HOSTDEVICE T operator()(const T& val) const { return atanh(val); } +}; + +template <> +struct Atanh { + HOSTDEVICE platform::float16 operator()(const platform::float16& val) const { + return platform::float16(atanh(static_cast(val))); + } +}; + +// Atanh(x) = atanh(x) +template +struct AtanhFunctor : public BaseActivationFunctor { + template + void operator()(Device d, X x, Out out) const { + out.device(d) = x.unaryExpr(Atanh()); + } +}; + +// atanh'(x) = 1/(1 - x^2) +template +struct AtanhGradFunctor : public BaseActivationFunctor { + template + void operator()(Device d, X x, Out out, dOut dout, dX dx) const { + dx.device(d) = dout * static_cast(1) / (static_cast(1) - x.square()); + } + + static constexpr ActBwdOpFwdDeps FwdDeps() { return kDepX; } +}; + // round(x) = [x] template struct RoundFunctor : public BaseActivationFunctor { @@ -2719,6 +2820,9 @@ struct LogGradGradFunctor : public BaseActivationFunctor { __macro(asin, Asin, AsinFunctor, AsinGradFunctor); \ __macro(sinh, Sinh, SinhFunctor, SinhGradFunctor); \ __macro(cosh, Cosh, CoshFunctor, CoshGradFunctor); \ + __macro(asinh, Asinh, AsinhFunctor, AsinhGradFunctor); \ + __macro(acosh, Acosh, AcoshFunctor, AcoshGradFunctor); \ + __macro(atanh, Atanh, AtanhFunctor, AtanhGradFunctor); \ __macro(round, Round, RoundFunctor, ZeroGradFunctor); \ __macro(reciprocal, Reciprocal, ReciprocalFunctor, ReciprocalGradFunctor); \ __macro(log1p, Log1p, Log1pFunctor, Log1pGradFunctor); \ diff --git a/python/paddle/__init__.py b/python/paddle/__init__.py index 221f1cc2902a8a7a488d573c2ff845cbd6ac5691..ae287f63aef41d8024c6a5de082a71cb0977c6eb 100755 --- a/python/paddle/__init__.py +++ b/python/paddle/__init__.py @@ -228,6 +228,9 @@ from .tensor.math import trunc # noqa: F401 from .tensor.math import digamma # noqa: F401 from .tensor.math import neg # noqa: F401 from .tensor.math import lgamma # noqa: F401 +from .tensor.math import acosh # noqa: F401 +from .tensor.math import asinh # noqa: F401 +from .tensor.math import atanh # noqa: F401 from .tensor.math import lerp # noqa: F401 from .tensor.math import rad2deg # noqa: F401 from .tensor.math import deg2rad # noqa: F401 @@ -566,6 +569,9 @@ __all__ = [ # noqa 'einsum', 'set_flags', 'get_flags', + 'asinh', + 'acosh', + 'atanh', 'as_complex', 'as_real', 'diff', diff --git a/python/paddle/fluid/layers/ops.py b/python/paddle/fluid/layers/ops.py index cc5c327b974f7477df2f861169ba9b6312d3bfcd..05c0b03a025c6b6ec31966cb5c24130b9c04f33e 100755 --- a/python/paddle/fluid/layers/ops.py +++ b/python/paddle/fluid/layers/ops.py @@ -55,6 +55,9 @@ __unary_func__ = [ 'reciprocal', 'square', 'lgamma', + 'acosh', + 'asinh', + 'atanh', ] __inplace_unary_func__ = [ @@ -372,6 +375,45 @@ Examples: """) +add_sample_code(globals()["asinh"], r""" +Examples: + .. code-block:: python + + import paddle + + x = paddle.to_tensor([-0.4, -0.2, 0.1, 0.3]) + out = paddle.asinh(x) + print(out) + # [-0.39003533, -0.19869010, 0.09983408, 0.29567307] + +""") + +add_sample_code(globals()["acosh"], r""" +Examples: + .. code-block:: python + + import paddle + + x = paddle.to_tensor([1., 3., 4., 5.]) + out = paddle.acosh(x) + print(out) + # [0. , 1.76274729, 2.06343699, 2.29243159] + +""") + +add_sample_code(globals()["atanh"], r""" +Examples: + .. code-block:: python + + import paddle + + x = paddle.to_tensor([-0.4, -0.2, 0.1, 0.3]) + out = paddle.atanh(x) + print(out) + # [-0.42364895, -0.20273256, 0.10033535, 0.30951962] + +""") + add_sample_code(globals()["round"], r""" Examples: .. code-block:: python diff --git a/python/paddle/fluid/tests/unittests/test_activation_op.py b/python/paddle/fluid/tests/unittests/test_activation_op.py index cfa52535d8c4ea21f5c1c98133ff505f1b167c5f..c1d7802633eca7f15b2dbd3e12f610d7326cc3e5 100755 --- a/python/paddle/fluid/tests/unittests/test_activation_op.py +++ b/python/paddle/fluid/tests/unittests/test_activation_op.py @@ -1145,6 +1145,60 @@ class TestAsin(TestActivation): self.check_grad(['X'], 'Out') +class TestAcosh(TestActivation): + def setUp(self): + self.op_type = "acosh" + self.init_dtype() + + np.random.seed(1024) + x = np.random.uniform(2, 3, [10, 12]).astype(self.dtype) + out = np.arccosh(x) + + self.inputs = {'X': OpTest.np_dtype_to_fluid_dtype(x)} + self.outputs = {'Out': out} + + def test_check_grad(self): + if self.dtype == np.float16: + return + self.check_grad(['X'], 'Out') + + +class TestAsinh(TestActivation): + def setUp(self): + self.op_type = "asinh" + self.init_dtype() + + np.random.seed(1024) + x = np.random.uniform(1, 2, [10, 12]).astype(self.dtype) + out = np.arcsinh(x) + + self.inputs = {'X': OpTest.np_dtype_to_fluid_dtype(x)} + self.outputs = {'Out': out} + + def test_check_grad(self): + if self.dtype == np.float16: + return + self.check_grad(['X'], 'Out') + + +class TestAtanh(TestActivation): + def setUp(self): + self.op_type = "atanh" + self.init_dtype() + + np.random.seed(400) + x = np.random.uniform(-0.9, 0.9, [10, 12]).astype(self.dtype) + out = np.arctanh(x) + + self.inputs = {'X': OpTest.np_dtype_to_fluid_dtype(x)} + self.outputs = {'Out': out} + + def test_check_grad(self): + if self.dtype == np.float16: + return + self.check_grad(['X'], 'Out') + + class TestRound(TestActivation): def setUp(self): self.op_type = "round" @@ -2815,6 +2869,9 @@ create_test_error_class('sin') create_test_error_class('sqrt') create_test_error_class('tanh') create_test_error_class('tan') +create_test_error_class('acosh') +create_test_error_class('asinh') +create_test_error_class('atanh') #------------------ Test Cudnn Activation---------------------- @@ -2886,6 +2943,9 @@ create_test_act_fp16_class(TestSin) create_test_act_fp16_class(TestSinh) create_test_act_fp16_class(TestAsin) create_test_act_fp16_class(TestAtan) +create_test_act_fp16_class(TestAcosh, grad_atol=0.85) +create_test_act_fp16_class(TestAsinh, grad_atol=0.85) +create_test_act_fp16_class(TestAtanh, grad_atol=0.85) create_test_act_fp16_class(TestRound, grad_check=False) create_test_act_fp16_class(TestRelu) create_test_act_fp16_class(TestGelu) diff --git a/python/paddle/fluid/tests/unittests/test_math_op_patch_var_base.py b/python/paddle/fluid/tests/unittests/test_math_op_patch_var_base.py index 3f611a319215cc4ec59ffbad47fb4cd82b3e4499..44876c9bd577339a802157d85826f7d546ec6498 100644 --- a/python/paddle/fluid/tests/unittests/test_math_op_patch_var_base.py +++ b/python/paddle/fluid/tests/unittests/test_math_op_patch_var_base.py @@ -371,6 +371,15 @@ class TestMathOpPatchesVarBase(unittest.TestCase): np.array_equal(x.rank().numpy(), paddle.rank(x).numpy())) self.assertTrue( np.array_equal(x[0].t().numpy(), paddle.t(x[0]).numpy())) + self.assertTrue( + np.array_equal(x.asinh().numpy(), paddle.asinh(x).numpy())) + ### acosh(x) = nan, need to change input + t_np = np.random.uniform(1, 2, [2, 3]).astype(self.dtype) + t = paddle.to_tensor(t_np) + self.assertTrue( + np.array_equal(t.acosh().numpy(), paddle.acosh(t).numpy())) + self.assertTrue( + np.array_equal(x.atanh().numpy(), paddle.atanh(x).numpy())) d = paddle.to_tensor([[1.2285208, 1.3491015, 1.4899898], [1.30058, 1.0688717, 1.4928783], [1.0958099, 1.3724753, 1.8926544]]) diff --git a/python/paddle/tensor/__init__.py b/python/paddle/tensor/__init__.py index 2d35f9cd6893ae2aa83879b1d862cd7992bb31c9..7794903c1bb7b8a148764697aa3276a5ab901bee 100755 --- a/python/paddle/tensor/__init__.py +++ b/python/paddle/tensor/__init__.py @@ -194,6 +194,9 @@ from .math import digamma # noqa: F401 from .math import neg # noqa: F401 from .math import lgamma # noqa: F401 from .math import diagonal # noqa: F401 +from .math import acosh # noqa: F401 +from .math import asinh # noqa: F401 +from .math import atanh # noqa: F401 from .math import lerp # noqa: F401 from .math import lerp_ # noqa: F401 from .math import rad2deg # noqa: F401 @@ -420,6 +423,9 @@ tensor_method_func = [ #noqa 'multi_dot', 'solve', 'triangular_solve', + 'asinh', + 'atanh', + 'acosh', 'as_complex', 'as_real', 'rad2deg', diff --git a/python/paddle/tensor/math.py b/python/paddle/tensor/math.py index a322c133436d19b570a1bcf3ae2478e27aa72048..9e59fbc56ad4cde84a0ceef0fff67e6482c51c4a 100755 --- a/python/paddle/tensor/math.py +++ b/python/paddle/tensor/math.py @@ -65,6 +65,9 @@ from ..fluid.layers import sqrt # noqa: F401 from ..fluid.layers import sqrt_ # noqa: F401 from ..fluid.layers import sin # noqa: F401 from ..fluid.layers import lgamma # noqa: F401 +from ..fluid.layers import asinh # noqa: F401 +from ..fluid.layers import acosh # noqa: F401 +from ..fluid.layers import atanh # noqa: F401 from ..fluid.layers import multiplex # noqa: F401 from ..fluid import layers