diff --git a/paddle/fluid/operators/fold_op.cc b/paddle/fluid/operators/fold_op.cc index 40ec9aef190ff4bacd52b19a1c0b12300a35b61e..92f59e118c3b7bb66a2c5c76d66109ddf04ee076 100644 --- a/paddle/fluid/operators/fold_op.cc +++ b/paddle/fluid/operators/fold_op.cc @@ -95,6 +95,17 @@ class FoldOp : public framework::OperatorWithKernel { "but recieved strides_height: %d strides_width: %d.", strides[0], strides[1])); // check dilations + PADDLE_ENFORCE_GT(output_height, 1, + platform::errors::InvalidArgument( + "The `output_height` should be greater than one, " + "but recieved output_height: %d .", + output_height)); + PADDLE_ENFORCE_GT(output_width, 1, + platform::errors::InvalidArgument( + "The `output_width` should be greater than one, " + "but recieved output_width: %d .", + output_width)); + // check output size PADDLE_ENFORCE_GT( dilation_height, 0, platform::errors::InvalidArgument( @@ -146,7 +157,7 @@ class FoldOp : public framework::OperatorWithKernel { output_width)); PADDLE_ENFORCE_EQ( - blocks_height * blocks_width, in_dims[1], + blocks_height * blocks_width, in_dims[2], platform::errors::InvalidArgument( "Given input output_size (%d, %d), " "kernel_sizes (%d, %d), strides (%d, %d), dilations (%d, %d), " @@ -156,6 +167,15 @@ class FoldOp : public framework::OperatorWithKernel { strides[0], strides[1], dilations[0], dilations[1], blocks_height, blocks_width, blocks_height * blocks_width, in_dims[2])); + PADDLE_ENFORCE_EQ( + in_dims[1] % (kernel_sizes[0] * kernel_sizes[1]), 0, + platform::errors::InvalidArgument( + "Expected size of input's dimension 1 to be divisible by the" + "product of kernel_size, but got input.size(1)=%d and " + "kernel_size=( %d" + ", %d).", + in_dims[1], kernel_sizes[0], kernel_sizes[1])); + out_dims.push_back(output_height); out_dims.push_back(output_width); ctx->SetOutputDim("Y", phi::make_ddim(out_dims)); diff --git a/python/paddle/fluid/tests/unittests/test_fold_op.py b/python/paddle/fluid/tests/unittests/test_fold_op.py index 14a59b413383f81959e9854d5735a87f7ff728cc..44b94cd3b66eec55841760a14fd95df0e930f36e 100644 --- a/python/paddle/fluid/tests/unittests/test_fold_op.py +++ b/python/paddle/fluid/tests/unittests/test_fold_op.py @@ -174,6 +174,15 @@ class TestFoldOpError(unittest.TestCase): x, output_sizes=[6, 6], kernel_sizes=[2, 2], strides=[1, 1]) + def test_output_size_2(): + # out_size must GT 1 + x = paddle.randn(shape=[2, 6, 6], dtype="float32") + out = fold( + x, + output_sizes=[0.1, 0.2], + kernel_sizes=[2, 2], + strides=[1, 1]) + def test_block_h_w(): # test_block_h_w GT 0 x = paddle.randn(shape=[2, 1, 1], dtype="float32") @@ -196,6 +205,7 @@ class TestFoldOpError(unittest.TestCase): self.assertRaises(AssertionError, test_dilations_shape) self.assertRaises(AssertionError, test_strides_shape) self.assertRaises(ValueError, test_output_size) + self.assertRaises(ValueError, test_output_size_2) self.assertRaises(ValueError, test_block_h_w) self.assertRaises(ValueError, test_GT_0) diff --git a/python/paddle/nn/functional/common.py b/python/paddle/nn/functional/common.py index ed668ed124c2318c88cde2bd4acb31ce2b2e4f7c..9e78ca6be3f2749e43963f63cdb8b6983f651697 100644 --- a/python/paddle/nn/functional/common.py +++ b/python/paddle/nn/functional/common.py @@ -351,7 +351,6 @@ def interpolate(x, out_shape = size scale = scale_factor - if out_shape is not None and scale is not None: raise ValueError("Only one of size or scale_factor should be defined.") if out_shape is not None: @@ -362,6 +361,8 @@ def interpolate(x, if in_dynamic_mode(): if isinstance(out_shape, Variable): out_shape = list(out_shape.numpy()) + else: + out_shape = list(out_shape) for i, dim in enumerate(out_shape): if isinstance(dim, Variable): out_shape[i] = dim.numpy()[0] @@ -1818,7 +1819,6 @@ def fold(x, can be calculated as following. .. math:: - H_out &= output_size[0] W_out &= output_size[1] C_out &= C_in / kernel\_sizes[0] / kernel\_sizes[1] @@ -1826,21 +1826,21 @@ def fold(x, Parameters: x(Tensor): 3-D Tensor, input tensor of format [N, C, L], data type can be float32 or float64 - output_sizes(list): The size of output size, should be [output_size_h, output_size_w] + output_sizes(int|list|tuple): The size of output size, should be [output_size_h, output_size_w] or an interger o treated as [o, o]. - kernel_sizes(int|list): The size of convolution kernel, should be [k_h, k_w] + kernel_sizes(int|list|tuple): The size of convolution kernel, should be [k_h, k_w] or an integer k treated as [k, k]. - strides(int|list): The strides, should be [stride_h, stride_w] + strides(int|list|tuple): The strides, should be [stride_h, stride_w] or an integer stride treated as [sride, stride]. For default, strides will be [1, 1]. - paddings(int|list): The paddings of each dimension, should be + paddings(int|list|tuple): The paddings of each dimension, should be [padding_top, padding_left, padding_bottom, padding_right] or [padding_h, padding_w] or an integer padding. If [padding_h, padding_w] was given, it will expanded to [padding_h, padding_w, padding_h, padding_w]. If an integer padding was given, [padding, padding, padding, padding] will be used. For default, paddings will be [0, 0, 0, 0] - dilations(int|list): the dilations of convolution kernel, should be + dilations(int|list|tuple): the dilations of convolution kernel, should be [dilation_h, dilation_w], or an integer dilation treated as [dilation, dilation]. For default, it will be [1, 1]. name(str, optional): The default value is None. @@ -1859,9 +1859,9 @@ def fold(x, import paddle import paddle.nn.functional as F - x = paddle.randn([2,12,9]) - y = F.fold(x, output_sizes=(4, 4), kernel_sizes=2) - # y.shape = [2,3,4,4] + x = paddle.randn([2,3*2*2,12]) + y = F.fold(x, output_sizes=[4, 5], kernel_sizes=2) + # y.shape = [2,3,4,5] """ @@ -1872,29 +1872,32 @@ def fold(x, assert len(x.shape) == 3, \ "input should be the format of [N, C, L]" + def _is_list_or_turple_(data): + return (isinstance(data, list) or isinstance(data, tuple)) + if isinstance(output_sizes, int): output_sizes = [output_sizes, output_sizes] else: - assert isinstance(output_sizes, list) and (len(output_sizes) == 2), \ - "output_sizes should either be an integer or a list of two integers" + assert _is_list_or_turple_(output_sizes) and (len(output_sizes) == 2), \ + "output_sizes should either be an integer or a list/tuple of two integers" if isinstance(kernel_sizes, int): kernel_sizes = [kernel_sizes, kernel_sizes] else: - assert isinstance(kernel_sizes, list) and (len(kernel_sizes) == 2), \ - "kernel_sizes should either be an integer or a list of two integers" + assert _is_list_or_turple_(kernel_sizes) and (len(kernel_sizes) == 2), \ + "kernel_sizes should either be an integer or a list/tuple of two integers" if isinstance(strides, int): strides = [strides, strides] else: - assert isinstance(strides, list) and (len(strides) == 2), \ - "strides should either be an integer or a list of two integers" + assert _is_list_or_turple_(strides) and (len(strides) == 2), \ + "strides should either be an integer or a list/tuple of two integers" if isinstance(dilations, int): dilations = [dilations, dilations] else: - assert isinstance(dilations, list) and (len(dilations) == 2), \ - "dilations should either be an integer or a list of two integers" + assert _is_list_or_turple_(dilations) and (len(dilations) == 2), \ + "dilations should either be an integer or a list/tuple of two integers" if isinstance(paddings, int): paddings = [paddings] * 4 @@ -1912,16 +1915,21 @@ def fold(x, "Unexpected type of paddings, it should be either an integer or a list" "of 2 or 4 integers") - out = helper.create_variable_for_type_inference(dtype=x.dtype) - helper.append_op( - type="fold", - inputs={"X": x}, - outputs={"Y": out}, - attrs={ - "output_sizes": output_sizes, - "kernel_sizes": kernel_sizes, - "strides": strides, - "paddings": paddings, - "dilations": dilations - }) + if in_dynamic_mode(): + out = _C_ops.fold(x, "output_sizes", output_sizes, "kernel_sizes", + kernel_sizes, "strides", strides, "paddings", + paddings, "dilations", dilations) + else: + out = helper.create_variable_for_type_inference(dtype=x.dtype) + helper.append_op( + type="fold", + inputs={"X": x}, + outputs={"Y": out}, + attrs={ + "output_sizes": output_sizes, + "kernel_sizes": kernel_sizes, + "strides": strides, + "paddings": paddings, + "dilations": dilations + }) return out diff --git a/python/paddle/nn/layer/common.py b/python/paddle/nn/layer/common.py index 19fbcd5b6f85691e57530a442d9f72ce7935692d..dac4cf5f2725333952d3710df3c5629d6566197f 100644 --- a/python/paddle/nn/layer/common.py +++ b/python/paddle/nn/layer/common.py @@ -1565,7 +1565,6 @@ class Fold(Layer): can be calculated as following. .. math:: - H_out &= output_size[0] W_out &= output_size[1] C_out &= C_in / kernel\_sizes[0] / kernel\_sizes[1] @@ -1573,19 +1572,19 @@ class Fold(Layer): Parameters: output_sizes(list): The size of output size, should be [output_size_h, output_size_w] or an interger o treated as [o, o]. - kernel_sizes(int|list): The size of convolution kernel, should be [k_h, k_w] + kernel_sizes(int|list|tuple): The size of convolution kernel, should be [k_h, k_w] or an integer k treated as [k, k]. - strides(int|list): The strides, should be [stride_h, stride_w] + strides(int|list|tuple): The strides, should be [stride_h, stride_w] or an integer stride treated as [sride, stride]. For default, strides will be [1, 1]. - paddings(int|list): The paddings of each dimension, should be + paddings(int|list|tuple): The paddings of each dimension, should be [padding_top, padding_left, padding_bottom, padding_right] or [padding_h, padding_w] or an integer padding. If [padding_h, padding_w] was given, it will expanded to [padding_h, padding_w, padding_h, padding_w]. If an integer padding was given, [padding, padding, padding, padding] will be used. For default, paddings will be [0, 0, 0, 0] - dilations(int|list): the dilations of convolution kernel, should be + dilations(int|list|tuple): the dilations of convolution kernel, should be [dilation_h, dilation_w], or an integer dilation treated as [dilation, dilation]. For default, it will be [1, 1]. name(str, optional): The default value is None. @@ -1604,10 +1603,10 @@ class Fold(Layer): import paddle import paddle.nn as nn - x = paddle.randn([2,12,9]) - fold = nn.Fold(output_sizes=(4, 4), kernel_sizes=2) + x = paddle.randn([2,3*2*2,12]) + fold = nn.Fold(output_sizes=[4, 5], kernel_sizes=2) y = fold(x) - # y.shape = [2,3,4,4] + # y.shape = [2,3,4,5] """ def __init__(self,