# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ math functions """ from __future__ import print_function from paddle.common_ops_import import * from ..fluid.framework import core from ..fluid.layers.layer_function_generator import _generate_doc_string_ # TODO: define math functions # yapf: disable __all__ = [ # 'abs', # 'acos', # 'asin', 'atan', # 'ceil', # 'cos', # 'cumsum', # 'elementwise_add', # 'elementwise_div', # 'elementwise_floordiv', # 'elementwise_max', # 'elementwise_min', # 'elementwise_mod', # 'elementwise_mul', # 'elementwise_pow', # 'elementwise_sub', # 'exp', # 'floor', # 'increment', # 'log', # 'mul', # 'multiplex', # 'pow', # 'reciprocal', # 'reduce_max', # 'reduce_min', # 'reduce_prod', # 'reduce_sum', # 'round', # 'rsqrt', # 'scale', # 'sign', 'sin', 'sqrt', # 'square', # 'stanh', # 'sum', # 'sums', 'tanh', # 'elementwise_sum', # 'max', # 'min', # 'mm', 'div', 'add', # 'atan', # 'logsumexp', # 'inverse', # 'log1p', # 'erf', # 'addcmul', # 'addmm'] ] # yapf: enable. def generate_op_noattr(op_type): """Register the Python layer for an Operator without Attribute.. Args: op_type: The name of the operator to be created. This function takes in the operator type (sin, tanh etc) and creates the operator functionality. """ op_proto = OpProtoHolder.instance().get_op_proto(op_type) def func(x, name=None, out=None): if in_dygraph_mode(): op = getattr(core.ops, op_type) return op(x) check_variable_and_dtype(x, 'x', ['float16', 'float32', 'float64'], op_type) helper = LayerHelper(op_type, **locals()) if name and out: warnings.warn( "Both name and out parameters have been set in fluid.tensor.math.%s(), only out will take effect to specify the result storage. " "You can discard either one to solve this warning." % op_type, category=UserWarning, stacklevel=2) if not out: out = helper.create_variable_for_type_inference(dtype=x.dtype) helper.append_op(type=op_type, inputs={"X": x}, outputs={"Out": out}) return out func.__name__ = op_type func.__doc__ = _generate_doc_string_( op_proto, additional_args_lines=[ "name(str, optional): The default value is None. Normally there is no need for user to set this property. For more information, please refer to :ref:`api_guide_Name`.\n " "out(Variable, optional): The default value is None. Optional output can be any created Variable that meets the requirements to store the result of operation. if out is None, a new Varibale will be create to store the result." ]) func.__doc__ = func.__doc__ + """ Return type Variable Examples: .. code-block:: python import numpy as np import paddle import paddle.fluid as fluid inputs = fluid.data(name="x", shape = [None, 4], dtype='float32') output = paddle.%s(inputs) exe = fluid.Executor(fluid.CPUPlace()) exe.run(fluid.default_startup_program()) #input.shape=1X4, batch_size=1 img = np.array([[1.0, 2.0, 3.0, 4.0]]).astype(np.float32) res = exe.run(fluid.default_main_program(), feed={'x':img}, fetch_list=[output]) print(res) """ % op_type return func __ops__noattr__ = [ 'atan', 'sin', 'sqrt', 'tanh', ] for _OP in set(__ops__noattr__): globals()[_OP] = generate_op_noattr(_OP) @dygraph_only def _elementwise_op_in_dygraph(x, y, axis=-1, act=None, use_mkldnn=False, op_name=None): op = getattr(core.ops, op_name) out = op(x, y, 'axis', axis, 'use_mkldnn', use_mkldnn) return dygraph_utils._append_activation_in_dygraph( out, act, use_mkldnn=use_mkldnn) def _elementwise_op(helper): op_type = helper.layer_type original_op_type = helper.kwargs.get('original_op_type', op_type) x = helper.kwargs.get('x', None) y = helper.kwargs.get('y', None) assert x is not None, 'x cannot be None in {}'.format(original_op_type) assert y is not None, 'y cannot be None in {}'.format(original_op_type) check_variable_and_dtype( x, 'x', ['float16', 'float32', 'float64', 'int32', 'int64'], original_op_type) check_variable_and_dtype( y, 'y', ['float16', 'float32', 'float64', 'int32', 'int64'], original_op_type) axis = helper.kwargs.get('axis', -1) use_mkldnn = helper.kwargs.get('use_mkldnn', False) name = helper.kwargs.get('name', None) out = helper.kwargs.get('out', None) if out is None: if name is None: out = helper.create_variable_for_type_inference(dtype=x.dtype) else: out = helper.create_variable( name=name, dtype=x.dtype, persistable=False) helper.append_op( type=op_type, inputs={'X': x, 'Y': y}, outputs={'Out': out}, attrs={'axis': axis, 'use_mkldnn': use_mkldnn}) return helper.append_activation(out) def add(x, y, alpha=1, out=None, name=None): """ Examples: .. code-block:: python import paddle import paddle.fluid as fluid import numpy as np def gen_data(): return { "x": np.array([2, 3, 4]).astype('float32'), "y": np.array([1, 5, 2]).astype('float32') } x = fluid.data(name="x", shape=[3], dtype='float32') y = fluid.data(name="y", shape=[3], dtype='float32') z1 = paddle.add(x, y) z2 = paddle.add(x, y, alpha=10) # z = x + y place = fluid.CPUPlace() exe = fluid.Executor(place) z_value = exe.run(feed=gen_data(), fetch_list=[z1.name, z2.name]) print(z_value[0]) # [3., 8., 6.] print(z_value[1]) # [12. 53. 24.] .. code-block:: python import paddle import paddle.fluid as fluid import numpy as np def gen_data(): return { "x": np.ones((2, 3, 4, 5)).astype('float32'), "y": np.zeros((4, 5)).astype('float32') } x = fluid.data(name="x", shape=[2, 3, 4, 5], dtype='float32') y = fluid.data(name="y", shape=[4, 5], dtype='float32') z = paddle.add(x, y, name='z') # z = x + y place = fluid.CPUPlace() exe = fluid.Executor(place) z_value = exe.run(feed=gen_data(), fetch_list=[z.name]) print(z_value[0]) print(z_value[0].shape) # z.shape=[2,3,4,5] .. code-block:: python import paddle import paddle.fluid as fluid import numpy as np def gen_data(): return { "x": np.random.randint(1, 5, size=[2, 3, 4, 5]).astype('float32'), "y": np.random.randint(1, 5, size=[5]).astype('float32') } x = fluid.data(name="x", shape=[2,3,4,5], dtype='float32') y = fluid.data(name="y", shape=[5], dtype='float32') z = paddle.add(x, y) # z = x / y place = fluid.CPUPlace() exe = fluid.Executor(place) z_value = exe.run(feed=gen_data(), fetch_list=[z.name]) print(z_value[0]) print(z_value[0].shape) # z.shape=[2,3,4,5] .. code-block:: python import paddle import paddle.fluid as fluid import numpy as np x = fluid.data(name="x", shape=[3], dtype="float32") y = fluid.data(name='y', shape=[3], dtype='float32') output = fluid.data(name="output", shape=[3], dtype="float32") z = paddle.add(x, y, out=output) place = fluid.CPUPlace() exe = fluid.Executor(place) data1 = np.array([2, 3, 4], dtype='float32') data2 = np.array([1, 5, 2], dtype='float32') z_value = exe.run(feed={'x': data1, 'y': data2}, fetch_list=[z]) print(z_value[0]) # [3. 8. 6.] .. code-block:: python import paddle import paddle.fluid as fluid import numpy as np with fluid.dygraph.guard(): np_x = np.array([2, 3, 4]).astype('float64') np_y = np.array([1, 5, 2]).astype('float64') x = fluid.dygraph.to_variable(np_x) y = fluid.dygraph.to_variable(np_y) z = paddle.add(x, y, alpha=-0.5) np_z = z.numpy() print(np_z) # [1.5, 0.5, 3. ] """ op_type = 'elementwise_add' axis = -1 act = None if alpha != 1: y = scale(y, scale=alpha) if in_dygraph_mode(): return _elementwise_op_in_dygraph( x, y, axis=axis, act=act, op_name=op_type) original_op_type = 'add' if name and out: warnings.warn( "Both name and out parameters have been set in paddle.tensor.%s, only out will take effect to specify the result storage. " "You can discard either one to solve this warning." % original_op_type, category=UserWarning, stacklevel=2) return _elementwise_op(LayerHelper(op_type, **locals())) def div(x, y, out=None, name=None): """ Examples: .. code-block:: python import paddle import paddle.fluid as fluid import numpy as np def gen_data(): return { "x": np.array([2, 3, 4]).astype('float32'), "y": np.array([1, 5, 2]).astype('float32') } x = fluid.data(name="x", shape=[3], dtype='float32') y = fluid.data(name="y", shape=[3], dtype='float32') z = paddle.div(x, y) # z = x / y place = fluid.CPUPlace() exe = fluid.Executor(place) z_value = exe.run(feed=gen_data(), fetch_list=[z.name]) print(z_value) # [2., 0.6, 2.] .. code-block:: python import paddle import paddle.fluid as fluid import numpy as np def gen_data(): return { "x": np.ones((2, 3, 4, 5)).astype('float32'), "y": np.zeros((4, 5)).astype('float32') } x = fluid.data(name="x", shape=[2, 3, 4, 5], dtype='float32') y = fluid.data(name="y", shape=[4, 5], dtype='float32') z = paddle.div(x, y, name='z') # z = x / y place = fluid.CPUPlace() exe = fluid.Executor(place) z_value = exe.run(feed=gen_data(), fetch_list=[z.name]) print(z_value[0]) print(z_value[0].shape) # z.shape=[2,3,4,5] .. code-block:: python import paddle import paddle.fluid as fluid import numpy as np def gen_data(): return { "x": np.random.randint(1, 5, size=[2, 3, 4, 5]).astype('float32'), "y": np.random.randint(1, 5, size=[5]).astype('float32') } x = fluid.data(name="x", shape=[2,3,4,5], dtype='float32') y = fluid.data(name="y", shape=[5], dtype='float32') output = fluid.data(name="output", shape=[2,3,4,5], dtype="float32") z = paddle.div(x, y, out=output) # z = x / y place = fluid.CPUPlace() exe = fluid.Executor(place) z_value = exe.run(feed=gen_data(), fetch_list=[z.name]) print(z_value[0]) print(z_value[0].shape) # z.shape=[2,3,4,5] .. code-block:: python import paddle import paddle.fluid as fluid import numpy as np with fluid.dygraph.guard(fluid.CPUPlace()): np_x = np.array([2, 3, 4]).astype('float64') np_y = np.array([1, 5, 2]).astype('float64') x = fluid.dygraph.to_variable(np_x) y = fluid.dygraph.to_variable(np_y) z = paddle.div(x, y) np_z = z.numpy() print(np_z) # [2., 0.6, 2.] """ op_type = 'elementwise_div' axis = -1 act = None if in_dygraph_mode(): return _elementwise_op_in_dygraph( x, y, axis=axis, act=act, op_name=op_type) original_op_type = 'div' if name and out: warnings.warn( "Both name and out parameters have been set in paddle.tensor.%s, only out will take effect to specify the result storage. " "You can discard either one to solve this warning." % original_op_type, category=UserWarning, stacklevel=2) return _elementwise_op(LayerHelper(op_type, **locals())) for func in [ add, div, ]: proto_dict = {'add': 'elementwise_add', 'div': 'elementwise_div'} op_proto = OpProtoHolder.instance().get_op_proto(proto_dict[func.__name__]) if func.__name__ in ['add']: additional_args_lines = [ "alpha (int|float, optional): The alpha factor of the input. Default is 1. If alpha is not 1, the equation becomes Out = X + alpha * Y.", "out (Variable, optinal): The Variable that stores results of the operation. Default is None. If out is None, \ a new Variable will be created to store the results." , "name (string, optional): Name of the output. \ Default is None. It's used to print debug info for developers. Details: \ :ref:`api_guide_Name` " ] else: additional_args_lines = [ "out (Variable, optinal): The Variable that stores results of the operation. If out is None, \ a new Variable will be created to store the results." , "name (string, optional): Name of the output. \ Default is None. It's used to print debug info for developers. Details: \ :ref:`api_guide_Name` " ] func.__doc__ = _generate_doc_string_( op_proto, additional_args_lines=additional_args_lines, skip_attrs_set={"x_data_format", "y_data_format", "axis" }) + """\n""" + str(func.__doc__)