未验证 提交 400c3aa7 编写于 作者: X xiemoyuan 提交者: GitHub

[2.1 API] Modified params of some APIs to support tuple and list. (#32528)

* Modified params of some APIs to support tuple and list.

* fixed bug.
上级 c40c16a9
...@@ -105,7 +105,7 @@ class Distribution(object): ...@@ -105,7 +105,7 @@ class Distribution(object):
for arg in args: for arg in args:
if isinstance(arg, float): if isinstance(arg, float):
arg = [arg] arg = [arg]
if not isinstance(arg, (list, np.ndarray, tensor.Variable)): if not isinstance(arg, (list, tuple, np.ndarray, tensor.Variable)):
raise TypeError( raise TypeError(
"Type of input args must be float, list, numpy.ndarray or Tensor, but received type {}". "Type of input args must be float, list, numpy.ndarray or Tensor, but received type {}".
format(type(arg))) format(type(arg)))
...@@ -190,8 +190,8 @@ class Uniform(Distribution): ...@@ -190,8 +190,8 @@ class Uniform(Distribution):
[broadcasting](https://www.paddlepaddle.org.cn/documentation/docs/en/develop/beginners_guide/basic_concept/broadcasting_en.html) (e.g., `high - low` is a valid operation). [broadcasting](https://www.paddlepaddle.org.cn/documentation/docs/en/develop/beginners_guide/basic_concept/broadcasting_en.html) (e.g., `high - low` is a valid operation).
Args: Args:
low(int|float|list|numpy.ndarray|Tensor): The lower boundary of uniform distribution.The data type is int, float, list, numpy.ndarray or Tensor low(int|float|list|tuple|numpy.ndarray|Tensor): The lower boundary of uniform distribution.The data type is int, float, list, numpy.ndarray or Tensor
high(int|float|list|numpy.ndarray|Tensor): The higher boundary of uniform distribution.The data type is int, float, list, numpy.ndarray or Tensor high(int|float|list|tuple|numpy.ndarray|Tensor): The higher boundary of uniform distribution.The data type is int, float, list, numpy.ndarray or Tensor
name(str, optional): Name for the operation (optional, default is None). For more information, please refer to :ref:`api_guide_Name`. name(str, optional): Name for the operation (optional, default is None). For more information, please refer to :ref:`api_guide_Name`.
Examples: Examples:
...@@ -229,10 +229,10 @@ class Uniform(Distribution): ...@@ -229,10 +229,10 @@ class Uniform(Distribution):
def __init__(self, low, high, name=None): def __init__(self, low, high, name=None):
if not in_dygraph_mode(): if not in_dygraph_mode():
check_type(low, 'low', check_type(low, 'low',
(int, float, np.ndarray, tensor.Variable, list), (int, float, np.ndarray, tensor.Variable, list, tuple),
'Uniform') 'Uniform')
check_type(high, 'high', check_type(high, 'high',
(int, float, np.ndarray, tensor.Variable, list), (int, float, np.ndarray, tensor.Variable, list, tuple),
'Uniform') 'Uniform')
self.all_arg_is_float = False self.all_arg_is_float = False
...@@ -409,8 +409,8 @@ class Normal(Distribution): ...@@ -409,8 +409,8 @@ class Normal(Distribution):
* :math:`Z`: is the normalization constant. * :math:`Z`: is the normalization constant.
Args: Args:
loc(int|float|list|numpy.ndarray|Tensor): The mean of normal distribution.The data type is int, float, list, numpy.ndarray or Tensor. loc(int|float|list|tuple|numpy.ndarray|Tensor): The mean of normal distribution.The data type is int, float, list, numpy.ndarray or Tensor.
scale(int|float|list|numpy.ndarray|Tensor): The std of normal distribution.The data type is int, float, list, numpy.ndarray or Tensor. scale(int|float|list|tuple|numpy.ndarray|Tensor): The std of normal distribution.The data type is int, float, list, numpy.ndarray or Tensor.
name(str, optional): Name for the operation (optional, default is None). For more information, please refer to :ref:`api_guide_Name`. name(str, optional): Name for the operation (optional, default is None). For more information, please refer to :ref:`api_guide_Name`.
Examples: Examples:
...@@ -451,10 +451,10 @@ class Normal(Distribution): ...@@ -451,10 +451,10 @@ class Normal(Distribution):
def __init__(self, loc, scale, name=None): def __init__(self, loc, scale, name=None):
if not in_dygraph_mode(): if not in_dygraph_mode():
check_type(loc, 'loc', check_type(loc, 'loc',
(int, float, np.ndarray, tensor.Variable, list), (int, float, np.ndarray, tensor.Variable, list, tuple),
'Normal') 'Normal')
check_type(scale, 'scale', check_type(scale, 'scale',
(int, float, np.ndarray, tensor.Variable, list), (int, float, np.ndarray, tensor.Variable, list, tuple),
'Normal') 'Normal')
self.batch_size_unknown = False self.batch_size_unknown = False
...@@ -655,7 +655,7 @@ class Categorical(Distribution): ...@@ -655,7 +655,7 @@ class Categorical(Distribution):
* :math:`[x=i]` : it evaluates to 1 if :math:`x==i` , 0 otherwise. * :math:`[x=i]` : it evaluates to 1 if :math:`x==i` , 0 otherwise.
Args: Args:
logits(list|numpy.ndarray|Tensor): The logits input of categorical distribution. The data type is float32 or float64. logits(list|tuple|numpy.ndarray|Tensor): The logits input of categorical distribution. The data type is float32 or float64.
name(str, optional): Name for the operation (optional, default is None). For more information, please refer to :ref:`api_guide_Name`. name(str, optional): Name for the operation (optional, default is None). For more information, please refer to :ref:`api_guide_Name`.
Examples: Examples:
...@@ -702,11 +702,12 @@ class Categorical(Distribution): ...@@ -702,11 +702,12 @@ class Categorical(Distribution):
def __init__(self, logits, name=None): def __init__(self, logits, name=None):
""" """
Args: Args:
logits(list|numpy.ndarray|Tensor): The logits input of categorical distribution. The data type is float32 or float64. logits(list|tuple|numpy.ndarray|Tensor): The logits input of categorical distribution. The data type is float32 or float64.
name(str, optional): Name for the operation (optional, default is None). For more information, please refer to :ref:`api_guide_Name`. name(str, optional): Name for the operation (optional, default is None). For more information, please refer to :ref:`api_guide_Name`.
""" """
if not in_dygraph_mode(): if not in_dygraph_mode():
check_type(logits, 'logits', (np.ndarray, tensor.Variable, list), check_type(logits, 'logits',
(np.ndarray, tensor.Variable, list, tuple),
'Categorical') 'Categorical')
self.name = name if name is not None else 'Categorical' self.name = name if name is not None else 'Categorical'
......
...@@ -1036,7 +1036,7 @@ def _append_backward_ops_(block, ...@@ -1036,7 +1036,7 @@ def _append_backward_ops_(block,
val(list) the op path of block(index) val(list) the op path of block(index)
""" """
if callbacks is not None: if callbacks is not None:
assert (isinstance(callbacks, list)) assert (isinstance(callbacks, (list, tuple)))
for cb in callbacks: for cb in callbacks:
if not hasattr(cb, '__call__'): if not hasattr(cb, '__call__'):
raise ValueError("'callback' must be a callable object.") raise ValueError("'callback' must be a callable object.")
...@@ -1157,7 +1157,7 @@ def _append_backward_ops_(block, ...@@ -1157,7 +1157,7 @@ def _append_backward_ops_(block,
new_op_desc._set_attr(op_role_attr_name, backward) new_op_desc._set_attr(op_role_attr_name, backward)
grad_to_var["__current_op_desc__"] = new_op_desc grad_to_var["__current_op_desc__"] = new_op_desc
if callbacks is not None: if callbacks is not None:
assert (isinstance(callbacks, list)) assert (isinstance(callbacks, (list, tuple)))
for cb in callbacks: for cb in callbacks:
cb(block=target_block, context=grad_to_var) cb(block=target_block, context=grad_to_var)
...@@ -1380,7 +1380,7 @@ def append_backward(loss, ...@@ -1380,7 +1380,7 @@ def append_backward(loss,
Parameters: Parameters:
loss(Tensor): The loss Tensor of the network. loss(Tensor): The loss Tensor of the network.
parameter_list(list[Tensor|str], optional): List of Parameters or Parameter.names parameter_list(list[Tensor|str]|tuple[Tensor|str], optional): List/Tuple of Parameters or Parameter.names
that need to be updated by optimizers. that need to be updated by optimizers.
If it is None, all parameters If it is None, all parameters
will be updated. will be updated.
...@@ -1391,7 +1391,7 @@ def append_backward(loss, ...@@ -1391,7 +1391,7 @@ def append_backward(loss,
be automatically added into this set. be automatically added into this set.
If this parameter is not None, the Tensors or Tensor.names in this set will be added to the default set. If this parameter is not None, the Tensors or Tensor.names in this set will be added to the default set.
Default: None. Default: None.
callbacks(list[callable object], optional): List of callback functions. callbacks(list[callable object]|tuple[callable object], optional): List/Tuple of callback functions.
The callbacks are used for The callbacks are used for
doing some custom jobs during doing some custom jobs during
backward part building. All backward part building. All
...@@ -1477,7 +1477,7 @@ def append_backward(loss, ...@@ -1477,7 +1477,7 @@ def append_backward(loss,
int(core.op_proto_and_checker_maker.OpRole.Loss)) int(core.op_proto_and_checker_maker.OpRole.Loss))
if callbacks is not None: if callbacks is not None:
check_type(callbacks, 'callbacks', list, check_type(callbacks, 'callbacks', (list, tuple),
'paddle.static.append_backward') 'paddle.static.append_backward')
program = loss.block.program program = loss.block.program
...@@ -1823,9 +1823,9 @@ def calc_gradient(targets, inputs, target_gradients=None, no_grad_set=None): ...@@ -1823,9 +1823,9 @@ def calc_gradient(targets, inputs, target_gradients=None, no_grad_set=None):
Backpropagate the gradients of targets to inputs. Backpropagate the gradients of targets to inputs.
Args: Args:
targets(Tensor|list[Tensor]): The target Tensors targets(Tensor|list[Tensor]|tuple[Tensor]): The target Tensors
inputs(Tensor|list[Tensor]): The input Tensors inputs(Tensor|list[Tensor]|tuple[Tensor]): The input Tensors
target_gradients (Tensor|list[Tensor], optional): The gradient Tensors target_gradients (Tensor|list[Tensor]|tuple[Tensor], optional): The gradient Tensors
of targets which has the same shape with targets, If None, ones will of targets which has the same shape with targets, If None, ones will
be created for them. be created for them.
no_grad_set(set[Tensor|str], optional): Set of Tensors or Tensor.names in the :ref:`api_guide_Block_en` 0 whose gradients no_grad_set(set[Tensor|str], optional): Set of Tensors or Tensor.names in the :ref:`api_guide_Block_en` 0 whose gradients
...@@ -1962,9 +1962,9 @@ def gradients(targets, inputs, target_gradients=None, no_grad_set=None): ...@@ -1962,9 +1962,9 @@ def gradients(targets, inputs, target_gradients=None, no_grad_set=None):
Backpropagate the gradients of targets to inputs. Backpropagate the gradients of targets to inputs.
Args: Args:
targets (Tensor|list[Tensor]): The target Tensors. targets (Tensor|list[Tensor]|tuple[Tensor]): The target Tensors.
inputs (Tensor|list[Tensor]): The input Tensors. inputs (Tensor|list[Tensor]|tuple[Tensor]): The input Tensors.
target_gradients (Tensor|list[Tensor], optional): The gradient Tensor target_gradients (Tensor|list[Tensor]|tuple[Tensor], optional): The gradient Tensor
of targets which has the same shape with targets, If None, ones will of targets which has the same shape with targets, If None, ones will
be created for them. be created for them.
no_grad_set (set[Tensor|str], optional): Set of Tensors or Tensor.names in the :ref:`api_guide_Block_en` 0 whose gradients no_grad_set (set[Tensor|str], optional): Set of Tensors or Tensor.names in the :ref:`api_guide_Block_en` 0 whose gradients
...@@ -1992,12 +1992,12 @@ def gradients(targets, inputs, target_gradients=None, no_grad_set=None): ...@@ -1992,12 +1992,12 @@ def gradients(targets, inputs, target_gradients=None, no_grad_set=None):
z = paddle.static.gradients([y], x) z = paddle.static.gradients([y], x)
print(z) # [var x@GRAD : fluid.VarType.LOD_TENSOR.shape(-1L, 2L, 8L, 8L).astype(VarType.FP32)] print(z) # [var x@GRAD : fluid.VarType.LOD_TENSOR.shape(-1L, 2L, 8L, 8L).astype(VarType.FP32)]
""" """
check_type(targets, 'targets', (framework.Variable, list), check_type(targets, 'targets', (framework.Variable, list, tuple),
'paddle.static.gradients') 'paddle.static.gradients')
check_type(inputs, 'inputs', (framework.Variable, list), check_type(inputs, 'inputs', (framework.Variable, list, tuple),
'paddle.static.gradients') 'paddle.static.gradients')
check_type(target_gradients, 'target_gradients', ( check_type(target_gradients, 'target_gradients', (
framework.Variable, list, type(None)), 'paddle.static.gradients') framework.Variable, list, tuple, type(None)), 'paddle.static.gradients')
outs = calc_gradient(targets, inputs, target_gradients, no_grad_set) outs = calc_gradient(targets, inputs, target_gradients, no_grad_set)
return _as_list(outs) return _as_list(outs)
...@@ -29,7 +29,7 @@ class Sequential(Layer): ...@@ -29,7 +29,7 @@ class Sequential(Layer):
The argument passed to the constructor can be iterable Layers or iterable name Layer pairs. The argument passed to the constructor can be iterable Layers or iterable name Layer pairs.
Parameters: Parameters:
*layers(tuple): Layers or iterable name Layer pairs. layers(Layer|list|tuple): Layer or list/tuple of iterable name Layer pair.
Examples: Examples:
.. code-block:: python .. code-block:: python
...@@ -59,7 +59,7 @@ class Sequential(Layer): ...@@ -59,7 +59,7 @@ class Sequential(Layer):
def __init__(self, *layers): def __init__(self, *layers):
super(Sequential, self).__init__() super(Sequential, self).__init__()
if len(layers) > 0 and isinstance(layers[0], tuple): if len(layers) > 0 and isinstance(layers[0], (list, tuple)):
for name, layer in layers: for name, layer in layers:
self.add_sublayer(name, layer) self.add_sublayer(name, layer)
else: else:
......
...@@ -168,7 +168,7 @@ def declarative(function=None, input_spec=None): ...@@ -168,7 +168,7 @@ def declarative(function=None, input_spec=None):
Args: Args:
function (callable): callable imperative function. function (callable): callable imperative function.
input_spec(list[InputSpec]): list of InputSpec to specific the shape/dtype/name input_spec(list[InputSpec]|tuple[InputSpec]): list/tuple of InputSpec to specific the shape/dtype/name
information of each input Tensor. information of each input Tensor.
Returns: Returns:
...@@ -525,7 +525,7 @@ def save(layer, path, input_spec=None, **configs): ...@@ -525,7 +525,7 @@ def save(layer, path, input_spec=None, **configs):
Args: Args:
layer (Layer): The Layer to be saved. layer (Layer): The Layer to be saved.
path (str): The path prefix to save model. The format is ``dirname/file_prefix`` or ``file_prefix``. path (str): The path prefix to save model. The format is ``dirname/file_prefix`` or ``file_prefix``.
input_spec (list[InputSpec|Tensor], optional): Describes the input of the saved model's forward input_spec (list[InputSpec|Tensor]|tuple[InputSpec|Tensor], optional): Describes the input of the saved model's forward
method, which can be described by InputSpec or example Tensor. If None, all input variables of method, which can be described by InputSpec or example Tensor. If None, all input variables of
the original Layer's forward method would be the inputs of the saved model. Default None. the original Layer's forward method would be the inputs of the saved model. Default None.
**configs (dict, optional): Other save configuration options for compatibility. We do not **configs (dict, optional): Other save configuration options for compatibility. We do not
...@@ -654,7 +654,7 @@ def save(layer, path, input_spec=None, **configs): ...@@ -654,7 +654,7 @@ def save(layer, path, input_spec=None, **configs):
raise ValueError( raise ValueError(
"If there are static functions other than 'forward' that need to be saved, the input 'input_spec' should be None, but received the type of 'input_spec' is %s." "If there are static functions other than 'forward' that need to be saved, the input 'input_spec' should be None, but received the type of 'input_spec' is %s."
% type(input_spec)) % type(input_spec))
if not isinstance(input_spec, list): if not isinstance(input_spec, (list, tuple)):
raise TypeError( raise TypeError(
"The input input_spec should be 'list', but received input_spec's type is %s." "The input input_spec should be 'list', but received input_spec's type is %s."
% type(input_spec)) % type(input_spec))
......
...@@ -301,6 +301,41 @@ class UniformTest9(UniformTest): ...@@ -301,6 +301,41 @@ class UniformTest9(UniformTest):
name='values', shape=[dims], dtype='float32') name='values', shape=[dims], dtype='float32')
class UniformTest10(UniformTest):
def init_numpy_data(self, batch_size, dims):
# low and high are list.
self.low_np = np.random.randn(batch_size,
dims).astype('float32').tolist()
self.high_np = np.random.uniform(
5.0, 15.0, (batch_size, dims)).astype('float32').tolist()
self.values_np = np.random.randn(batch_size, dims).astype('float32')
def init_static_data(self, batch_size, dims):
self.static_low = self.low_np
self.static_high = self.high_np
with fluid.program_guard(self.test_program):
self.static_values = layers.data(
name='values', shape=[dims], dtype='float32')
class UniformTest11(UniformTest):
def init_numpy_data(self, batch_size, dims):
# low and high are tuple.
self.low_np = tuple(
np.random.randn(batch_size, dims).astype('float32').tolist())
self.high_np = tuple(
np.random.uniform(5.0, 15.0, (batch_size, dims)).astype('float32')
.tolist())
self.values_np = np.random.randn(batch_size, dims).astype('float32')
def init_static_data(self, batch_size, dims):
self.static_low = self.low_np
self.static_high = self.high_np
with fluid.program_guard(self.test_program):
self.static_values = layers.data(
name='values', shape=[dims], dtype='float32')
class NormalNumpy(DistributionNumpy): class NormalNumpy(DistributionNumpy):
def __init__(self, loc, scale): def __init__(self, loc, scale):
self.loc = np.array(loc) self.loc = np.array(loc)
...@@ -673,6 +708,66 @@ class NormalTest8(NormalTest): ...@@ -673,6 +708,66 @@ class NormalTest8(NormalTest):
name='other_scale', shape=[dims], dtype='float64') name='other_scale', shape=[dims], dtype='float64')
class NormalTest9(NormalTest):
def init_numpy_data(self, batch_size, dims):
# loc and scale are list.
self.loc_np = np.random.randn(batch_size,
dims).astype('float32').tolist()
self.scale_np = np.random.randn(batch_size, dims).astype('float32')
while not np.all(self.scale_np > 0):
self.scale_np = np.random.randn(batch_size, dims).astype('float32')
self.scale_np = self.scale_np.tolist()
self.values_np = np.random.randn(batch_size, dims).astype('float32')
# used to construct another Normal object to calculate kl_divergence
self.other_loc_np = np.random.randn(batch_size,
dims).astype('float32').tolist()
self.other_scale_np = np.random.randn(batch_size,
dims).astype('float32')
while not np.all(self.other_scale_np > 0):
self.other_scale_np = np.random.randn(batch_size,
dims).astype('float32')
self.other_scale_np = self.other_scale_np.tolist()
def init_static_data(self, batch_size, dims):
self.static_loc = self.loc_np
self.static_scale = self.scale_np
self.static_other_loc = self.other_loc_np
self.static_other_scale = self.other_scale_np
with fluid.program_guard(self.test_program):
self.static_values = layers.data(
name='values', shape=[dims], dtype='float32')
class NormalTest10(NormalTest):
def init_numpy_data(self, batch_size, dims):
# loc and scale are tuple.
self.loc_np = tuple(
np.random.randn(batch_size, dims).astype('float32').tolist())
self.scale_np = np.random.randn(batch_size, dims).astype('float32')
while not np.all(self.scale_np > 0):
self.scale_np = np.random.randn(batch_size, dims).astype('float32')
self.scale_np = tuple(self.scale_np.tolist())
self.values_np = np.random.randn(batch_size, dims).astype('float32')
# used to construct another Normal object to calculate kl_divergence
self.other_loc_np = tuple(
np.random.randn(batch_size, dims).astype('float32').tolist())
self.other_scale_np = np.random.randn(batch_size,
dims).astype('float32')
while not np.all(self.other_scale_np > 0):
self.other_scale_np = np.random.randn(batch_size,
dims).astype('float32')
self.other_scale_np = tuple(self.other_scale_np.tolist())
def init_static_data(self, batch_size, dims):
self.static_loc = self.loc_np
self.static_scale = self.scale_np
self.static_other_loc = self.other_loc_np
self.static_other_scale = self.other_scale_np
with fluid.program_guard(self.test_program):
self.static_values = layers.data(
name='values', shape=[dims], dtype='float32')
class CategoricalNumpy(DistributionNumpy): class CategoricalNumpy(DistributionNumpy):
def __init__(self, logits): def __init__(self, logits):
self.logits = np.array(logits).astype('float32') self.logits = np.array(logits).astype('float32')
...@@ -961,6 +1056,38 @@ class CategoricalTest7(CategoricalTest): ...@@ -961,6 +1056,38 @@ class CategoricalTest7(CategoricalTest):
return np_probs return np_probs
class CategoricalTest8(CategoricalTest):
def init_dynamic_data(self, batch_size, dims):
# input logtis is 2-D list
# value used in probs and log_prob method is 1-D Tensor
self.logits = self.logits_np.tolist()
self.other_logits = self.other_logits_np.tolist()
self.value = paddle.to_tensor(self.value_np)
def init_static_data(self, batch_size, dims):
with fluid.program_guard(self.test_program):
self.logits_static = self.logits_np.tolist()
self.other_logits_static = self.other_logits_np.tolist()
self.value_static = fluid.data(
name='value', shape=self.value_shape, dtype='int64')
class CategoricalTest9(CategoricalTest):
def init_dynamic_data(self, batch_size, dims):
# input logtis is 2-D tuple
# value used in probs and log_prob method is 1-D Tensor
self.logits = tuple(self.logits_np.tolist())
self.other_logits = tuple(self.other_logits_np.tolist())
self.value = paddle.to_tensor(self.value_np)
def init_static_data(self, batch_size, dims):
with fluid.program_guard(self.test_program):
self.logits_static = tuple(self.logits_np.tolist())
self.other_logits_static = tuple(self.other_logits_np.tolist())
self.value_static = fluid.data(
name='value', shape=self.value_shape, dtype='int64')
class DistributionTestError(unittest.TestCase): class DistributionTestError(unittest.TestCase):
def test_distribution_error(self): def test_distribution_error(self):
distribution = Distribution() distribution = Distribution()
......
...@@ -303,6 +303,12 @@ class TestDropoutFAPI(unittest.TestCase): ...@@ -303,6 +303,12 @@ class TestDropoutFAPI(unittest.TestCase):
mode='downscale_in_infer') mode='downscale_in_infer')
res10 = paddle.nn.functional.dropout(x=input, p=1., training=True) res10 = paddle.nn.functional.dropout(x=input, p=1., training=True)
res11 = paddle.fluid.layers.dropout(x=input, dropout_prob=0.) res11 = paddle.fluid.layers.dropout(x=input, dropout_prob=0.)
res12 = paddle.nn.functional.dropout(
x=input,
p=0.,
axis=(0, 1),
training=False,
mode='upscale_in_train')
in_np = np.random.random([40, 40]).astype("float32") in_np = np.random.random([40, 40]).astype("float32")
res_np = in_np res_np = in_np
...@@ -310,7 +316,8 @@ class TestDropoutFAPI(unittest.TestCase): ...@@ -310,7 +316,8 @@ class TestDropoutFAPI(unittest.TestCase):
exe = fluid.Executor(place) exe = fluid.Executor(place)
res_list = [ res_list = [
res1, res2, res3, res4, res5, res6, res7, res8, res9, res11 res1, res2, res3, res4, res5, res6, res7, res8, res9, res11,
res12
] ]
for res in res_list: for res in res_list:
fetches = exe.run(fluid.default_main_program(), fetches = exe.run(fluid.default_main_program(),
...@@ -388,9 +395,16 @@ class TestDropoutFAPI(unittest.TestCase): ...@@ -388,9 +395,16 @@ class TestDropoutFAPI(unittest.TestCase):
x=input, p=1., training=True) x=input, p=1., training=True)
dropout = paddle.fluid.dygraph.Dropout(p=0, ) dropout = paddle.fluid.dygraph.Dropout(p=0, )
res11 = dropout(input) res11 = dropout(input)
res12 = paddle.nn.functional.dropout(
x=input,
p=0.,
axis=(0, 1),
training=False,
mode='upscale_in_train')
res_list = [ res_list = [
res1, res2, res3, res4, res5, res6, res7, res8, res9, res11 res1, res2, res3, res4, res5, res6, res7, res8, res9, res11,
res12
] ]
for res in res_list: for res in res_list:
self.assertTrue(np.allclose(res.numpy(), res_np)) self.assertTrue(np.allclose(res.numpy(), res_np))
......
...@@ -55,6 +55,41 @@ class TestImperativeContainerSequential(unittest.TestCase): ...@@ -55,6 +55,41 @@ class TestImperativeContainerSequential(unittest.TestCase):
loss2 = fluid.layers.reduce_mean(res2) loss2 = fluid.layers.reduce_mean(res2)
loss2.backward() loss2.backward()
def test_sequential_list_params(self):
data = np.random.uniform(-1, 1, [5, 10]).astype('float32')
with fluid.dygraph.guard():
data = fluid.dygraph.to_variable(data)
model1 = fluid.dygraph.Sequential(
fluid.Linear(10, 1), fluid.Linear(1, 2))
res1 = model1(data)
self.assertListEqual(res1.shape, [5, 2])
model1[1] = fluid.Linear(1, 3)
res1 = model1(data)
self.assertListEqual(res1.shape, [5, 3])
loss1 = fluid.layers.reduce_mean(res1)
loss1.backward()
l1 = fluid.Linear(10, 1)
l2 = fluid.Linear(1, 3)
model2 = fluid.dygraph.Sequential(['l1', l1], ['l2', l2])
self.assertEqual(len(model2), 2)
res2 = model2(data)
self.assertTrue(l1 is model2.l1)
self.assertListEqual(res2.shape, res1.shape)
self.assertEqual(len(model1.parameters()), len(model2.parameters()))
del model2['l2']
self.assertEqual(len(model2), 1)
res2 = model2(data)
self.assertListEqual(res2.shape, [5, 1])
model2.add_sublayer('l3', fluid.Linear(1, 3))
model2.add_sublayer('l4', fluid.Linear(3, 4))
self.assertEqual(len(model2), 3)
res2 = model2(data)
self.assertListEqual(res2.shape, [5, 4])
loss2 = fluid.layers.reduce_mean(res2)
loss2.backward()
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()
...@@ -718,6 +718,18 @@ class TestAssign(unittest.TestCase): ...@@ -718,6 +718,18 @@ class TestAssign(unittest.TestCase):
self.assertTrue((linear_3.weight.numpy() == [2.0, 2.0]).all(), '') self.assertTrue((linear_3.weight.numpy() == [2.0, 2.0]).all(), '')
def test_assign_initializer_dygraph_4(self):
"""Test assign initializer in dygraph model.
"""
paddle.disable_static()
weight_attr_4 = paddle.framework.ParamAttr(
name="linear_weight_4",
initializer=paddle.nn.initializer.Assign((2, 2)))
linear_4 = paddle.nn.Linear(2, 2, weight_attr=weight_attr_4)
self.assertTrue((linear_4.weight.numpy() == [2.0, 2.0]).all(), '')
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()
...@@ -158,6 +158,22 @@ class LinearNetMultiInput(fluid.dygraph.Layer): ...@@ -158,6 +158,22 @@ class LinearNetMultiInput(fluid.dygraph.Layer):
return x_out, y_out, loss return x_out, y_out, loss
class LinearNetMultiInput1(fluid.dygraph.Layer):
def __init__(self, in_size, out_size):
super(LinearNetMultiInput1, self).__init__()
self._linear1 = Linear(in_size, out_size)
self._linear2 = Linear(in_size, out_size)
@declarative(input_spec=(InputSpec(
[None, 8], dtype='float32'), InputSpec(
[None, 8], dtype='float32')))
def forward(self, x, y):
x_out = self._linear1(x)
y_out = self._linear2(y)
loss = fluid.layers.mean(x_out + y_out)
return x_out, y_out, loss
class MultiLoadingLinearNet(fluid.dygraph.Layer): class MultiLoadingLinearNet(fluid.dygraph.Layer):
def __init__(self, size, model_path): def __init__(self, size, model_path):
super(MultiLoadingLinearNet, self).__init__() super(MultiLoadingLinearNet, self).__init__()
...@@ -542,6 +558,42 @@ class TestSaveLoadWithInputSpec(unittest.TestCase): ...@@ -542,6 +558,42 @@ class TestSaveLoadWithInputSpec(unittest.TestCase):
# 4. assert pred_x == pred_xx # 4. assert pred_x == pred_xx
self.assertTrue(np.allclose(pred_x.numpy(), pred_xx.numpy())) self.assertTrue(np.allclose(pred_x.numpy(), pred_xx.numpy()))
def test_multi_in_out1(self):
net = LinearNetMultiInput1(8, 8)
model_path = "multi_inout1.output_spec1/model"
# 1. check inputs and outputs
self.assertTrue(len(net.forward.inputs) == 2)
input_x = net.forward.inputs[0]
input_y = net.forward.inputs[1]
self.assertTrue(input_x.shape == (-1, 8))
self.assertTrue(input_y.shape == (-1, 8))
# 2. prune loss
output_spec = net.forward.outputs[:2]
paddle.jit.save(net, model_path, output_spec=output_spec)
# 3. load to infer
infer_layer = paddle.jit.load(model_path)
x = fluid.dygraph.to_variable(
np.random.random((4, 8)).astype('float32'))
y = fluid.dygraph.to_variable(
np.random.random((4, 8)).astype('float32'))
# 4. predict
pred_x, pred_y = infer_layer(x, y)
# 1. prune y and loss
model_path = "multi_inout1.output_spec2/model"
output_spec = net.forward.outputs[:1]
paddle.jit.save(net, model_path, (input_x, ), output_spec=output_spec)
# 2. load again
infer_layer2 = paddle.jit.load(model_path)
# 3. predict
pred_xx = infer_layer2(x)
# 4. assert pred_x == pred_xx
self.assertTrue(np.allclose(pred_x.numpy(), pred_xx.numpy()))
class TestJitSaveLoadConfig(unittest.TestCase): class TestJitSaveLoadConfig(unittest.TestCase):
def setUp(self): def setUp(self):
......
...@@ -236,7 +236,7 @@ def _update_input_info(inputs): ...@@ -236,7 +236,7 @@ def _update_input_info(inputs):
if isinstance(inputs, Input): if isinstance(inputs, Input):
shapes = [list(inputs.shape)] shapes = [list(inputs.shape)]
dtypes = [inputs.dtype] dtypes = [inputs.dtype]
elif isinstance(inputs, list): elif isinstance(inputs, (list, tuple)):
shapes = [list(input.shape) for input in inputs] shapes = [list(input.shape) for input in inputs]
dtypes = [input.dtype for input in inputs] dtypes = [input.dtype for input in inputs]
elif isinstance(inputs, dict): elif isinstance(inputs, dict):
...@@ -895,12 +895,12 @@ class Model(object): ...@@ -895,12 +895,12 @@ class Model(object):
Args: Args:
network (paddle.nn.Layer): The network is an instance of network (paddle.nn.Layer): The network is an instance of
paddle.nn.Layer. paddle.nn.Layer.
inputs (InputSpec|list|dict|None): `inputs`, entry points of network, inputs (InputSpec|list|tuple|dict|None): `inputs`, entry points of network,
could be a InputSpec instance, or lits of InputSpec instances, could be a InputSpec instance, or list/tuple of InputSpec instances,
or dict ({name: InputSpec}), and it couldn't be None in static or dict ({name: InputSpec}), and it couldn't be None in static
graph. graph.
labels (InputSpec|list|None): `labels`, entry points of network, labels (InputSpec|list|tuple|None): `labels`, entry points of network,
could be a InputSpec instnace or lits of InputSpec instances, could be a InputSpec instnace or list/tuple of InputSpec instances,
or None. For static graph, if labels is required in loss, or None. For static graph, if labels is required in loss,
labels must be set. Otherwise, it could be None. labels must be set. Otherwise, it could be None.
...@@ -994,9 +994,10 @@ class Model(object): ...@@ -994,9 +994,10 @@ class Model(object):
self.stop_training = False self.stop_training = False
if not in_dygraph_mode(): if not in_dygraph_mode():
if not isinstance(inputs, (list, dict, Input)): if not isinstance(inputs, (list, tuple, dict, Input)):
raise TypeError( raise TypeError(
"'inputs' must be list or dict, and couldn't be None.") "'inputs' must be list or tuple or dict, and couldn't be None."
)
elif inputs: elif inputs:
self._input_info = _update_input_info(inputs) self._input_info = _update_input_info(inputs)
......
...@@ -764,8 +764,8 @@ def dropout(x, ...@@ -764,8 +764,8 @@ def dropout(x,
Args: Args:
x (Tensor): The input tensor. The data type is float32 or float64. x (Tensor): The input tensor. The data type is float32 or float64.
p (float | int): Probability of setting units to zero. Default 0.5. p (float|int): Probability of setting units to zero. Default 0.5.
axis (int | list): The axis along which the dropout is performed. Default None. axis (int|list|tuple): The axis along which the dropout is performed. Default None.
training (bool): A flag indicating whether it is in train phrase or not. Default True. training (bool): A flag indicating whether it is in train phrase or not. Default True.
mode(str): ['upscale_in_train'(default) | 'downscale_in_infer']. mode(str): ['upscale_in_train'(default) | 'downscale_in_infer'].
...@@ -896,7 +896,7 @@ def dropout(x, ...@@ -896,7 +896,7 @@ def dropout(x,
if mode not in ('downscale_in_infer', 'upscale_in_train'): if mode not in ('downscale_in_infer', 'upscale_in_train'):
raise ValueError( raise ValueError(
"mode argument should be 'downscale_in_infer' or 'upscale_in_train'") "mode argument should be 'downscale_in_infer' or 'upscale_in_train'")
if axis and not isinstance(axis, (int, list)): if axis and not isinstance(axis, (int, list, tuple)):
raise TypeError("datatype of axis argument should be int or list") raise TypeError("datatype of axis argument should be int or list")
if axis == None: # commonly used dropout if axis == None: # commonly used dropout
...@@ -955,7 +955,7 @@ def dropout(x, ...@@ -955,7 +955,7 @@ def dropout(x,
#get mask shape #get mask shape
input_shape = x.shape input_shape = x.shape
drop_axes = [axis] if isinstance(axis, int) else axis drop_axes = [axis] if isinstance(axis, int) else list(axis)
if min(drop_axes) < 0 or max(drop_axes) > len(input_shape) - 1: if min(drop_axes) < 0 or max(drop_axes) > len(input_shape) - 1:
raise ValueError("axis value should be greater than or equal to 0 and less than dimensions of x:{}, but get axis value:{} " \ raise ValueError("axis value should be greater than or equal to 0 and less than dimensions of x:{}, but get axis value:{} " \
.format(len(input_shape), max(drop_axes))) .format(len(input_shape), max(drop_axes)))
......
...@@ -26,7 +26,7 @@ class Assign(NumpyArrayInitializer): ...@@ -26,7 +26,7 @@ class Assign(NumpyArrayInitializer):
"""Init an parameter with a numpy array, list, or tensor. """Init an parameter with a numpy array, list, or tensor.
Args: Args:
value (Tensor|numpy.ndarray|list): numpy array, list, or tensor to initialize the parameter. value (Tensor|numpy.ndarray|list|tuple): numpy array, list, tuple, or tensor to initialize the parameter.
name(str, optional): The default value is None. Normally there is no need for user to set this 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`. property. For more information, please refer to :ref:`api_guide_Name`.
...@@ -87,10 +87,10 @@ class Assign(NumpyArrayInitializer): ...@@ -87,10 +87,10 @@ class Assign(NumpyArrayInitializer):
def __init__(self, value, name=None): def __init__(self, value, name=None):
import numpy import numpy
check_type(value, 'value', (numpy.ndarray, list, framework.Variable), check_type(value, 'value',
'Assign') (numpy.ndarray, list, tuple, framework.Variable), 'Assign')
if (isinstance(value, list)): if (isinstance(value, (list, tuple))):
value = numpy.array(value) value = numpy.array(value)
# TODO: value is already is a tensor, accounting efficiency maybe it does not need to convert tensor to numpy data and then initialized. # TODO: value is already is a tensor, accounting efficiency maybe it does not need to convert tensor to numpy data and then initialized.
......
...@@ -680,8 +680,8 @@ class Dropout(layers.Layer): ...@@ -680,8 +680,8 @@ class Dropout(layers.Layer):
In dygraph mode, please use ``eval()`` to switch to evaluation mode, where dropout is disabled. In dygraph mode, please use ``eval()`` to switch to evaluation mode, where dropout is disabled.
Parameters: Parameters:
p (float | int): Probability of setting units to zero. Default: 0.5 p (float|int): Probability of setting units to zero. Default: 0.5
axis (int | list): The axis along which the dropout is performed. Default None. axis (int|list|tuple): The axis along which the dropout is performed. Default None.
mode(str, optional): ['upscale_in_train'(default) | 'downscale_in_infer'] mode(str, optional): ['upscale_in_train'(default) | 'downscale_in_infer']
1. upscale_in_train(default), upscale the output at training time 1. upscale_in_train(default), upscale the output at training time
......
...@@ -172,6 +172,12 @@ class TestModel(unittest.TestCase): ...@@ -172,6 +172,12 @@ class TestModel(unittest.TestCase):
def test_fit_static(self): def test_fit_static(self):
self.fit(False) self.fit(False)
def test_fit_dynamic_with_tuple_input(self):
self.fit_with_tuple_input(True)
def test_fit_static_with_tuple_input(self):
self.fit_with_tuple_input(False)
def test_fit_dynamic_with_rank(self): def test_fit_dynamic_with_rank(self):
self.fit(True, 2, 0) self.fit(True, 2, 0)
...@@ -240,6 +246,53 @@ class TestModel(unittest.TestCase): ...@@ -240,6 +246,53 @@ class TestModel(unittest.TestCase):
model.fit(train_loader, val_loader) model.fit(train_loader, val_loader)
fluid.disable_dygraph() if dynamic else None fluid.disable_dygraph() if dynamic else None
def fit_with_tuple_input(self, dynamic, num_replicas=None, rank=None):
fluid.enable_dygraph(self.device) if dynamic else None
seed = 333
paddle.seed(seed)
paddle.framework.random._manual_program_seed(seed)
net = LeNet()
optim_new = fluid.optimizer.Adam(
learning_rate=0.001, parameter_list=net.parameters())
model = Model(net, inputs=tuple(self.inputs), labels=tuple(self.labels))
model.prepare(
optim_new,
loss=CrossEntropyLoss(reduction="sum"),
metrics=Accuracy())
model.fit(self.train_dataset, batch_size=64, shuffle=False)
result = model.evaluate(self.val_dataset, batch_size=64)
np.testing.assert_allclose(result['acc'], self.acc1)
train_sampler = DistributedBatchSampler(
self.train_dataset,
batch_size=64,
shuffle=False,
num_replicas=num_replicas,
rank=rank)
val_sampler = DistributedBatchSampler(
self.val_dataset,
batch_size=64,
shuffle=False,
num_replicas=num_replicas,
rank=rank)
train_loader = fluid.io.DataLoader(
self.train_dataset,
batch_sampler=train_sampler,
places=self.device,
return_list=True)
val_loader = fluid.io.DataLoader(
self.val_dataset,
batch_sampler=val_sampler,
places=self.device,
return_list=True)
model.fit(train_loader, val_loader)
fluid.disable_dygraph() if dynamic else None
def evaluate(self, dynamic): def evaluate(self, dynamic):
fluid.enable_dygraph(self.device) if dynamic else None fluid.enable_dygraph(self.device) if dynamic else None
model = Model(LeNet(), self.inputs, self.labels) model = Model(LeNet(), self.inputs, self.labels)
......
...@@ -454,6 +454,18 @@ class TestFunctional(unittest.TestCase): ...@@ -454,6 +454,18 @@ class TestFunctional(unittest.TestCase):
np.testing.assert_equal(rotated_np_img.shape, np.testing.assert_equal(rotated_np_img.shape,
np.array(rotated_pil_img).shape) np.array(rotated_pil_img).shape)
def test_rotate1(self):
np_img = (np.random.rand(28, 28, 3) * 255).astype('uint8')
pil_img = Image.fromarray(np_img).convert('RGB')
rotated_np_img = F.rotate(
np_img, 80, expand=True, center=[0, 0], fill=[0, 0, 0])
rotated_pil_img = F.rotate(
pil_img, 80, expand=True, center=[0, 0], fill=[0, 0, 0])
np.testing.assert_equal(rotated_np_img.shape,
np.array(rotated_pil_img).shape)
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()
...@@ -538,10 +538,10 @@ def rotate(img, ...@@ -538,10 +538,10 @@ def rotate(img,
If true, expands the output image to make it large enough to hold the entire rotated image. If true, expands the output image to make it large enough to hold the entire rotated image.
If false or omitted, make the output image the same size as the input image. If false or omitted, make the output image the same size as the input image.
Note that the expand flag assumes rotation around the center and no translation. Note that the expand flag assumes rotation around the center and no translation.
center (2-tuple, optional): Optional center of rotation. center (2-list|2-tuple, optional): Optional center of rotation.
Origin is the upper left corner. Origin is the upper left corner.
Default is the center of the image. Default is the center of the image.
fill (3-tuple or int): RGB pixel fill value for area outside the rotated image. fill (3-list|3-tuple or int): RGB pixel fill value for area outside the rotated image.
If int, it is used for all channels respectively. If int, it is used for all channels respectively.
...@@ -568,6 +568,11 @@ def rotate(img, ...@@ -568,6 +568,11 @@ def rotate(img,
'img should be PIL Image or ndarray with dim=[2 or 3]. Got {}'. 'img should be PIL Image or ndarray with dim=[2 or 3]. Got {}'.
format(type(img))) format(type(img)))
if isinstance(center, list):
center = tuple(center)
if isinstance(fill, list):
fill = tuple(fill)
if _is_pil_image(img): if _is_pil_image(img):
return F_pil.rotate(img, angle, interpolation, expand, center, fill) return F_pil.rotate(img, angle, interpolation, expand, center, fill)
else: else:
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册