From 8ee091fb92ef9d57d348d6ac3989a118a491172a Mon Sep 17 00:00:00 2001 From: jiangjinsheng Date: Wed, 15 Jul 2020 10:14:55 +0800 Subject: [PATCH] fix Conv2d --- mindspore/nn/layer/conv.py | 40 ++++++++++++++++++++++++------ mindspore/ops/operations/nn_ops.py | 4 +-- 2 files changed, 34 insertions(+), 10 deletions(-) diff --git a/mindspore/nn/layer/conv.py b/mindspore/nn/layer/conv.py index 05570ea19bc..fc837f60ebd 100644 --- a/mindspore/nn/layer/conv.py +++ b/mindspore/nn/layer/conv.py @@ -19,7 +19,7 @@ from mindspore.common.parameter import Parameter from mindspore.common.initializer import initializer from mindspore._checkparam import ParamValidator as validator, Rel from mindspore._checkparam import Validator -from mindspore._checkparam import check_bool, twice, check_int_positive, check_int_non_negative +from mindspore._checkparam import check_bool, twice, check_int_positive from mindspore._extends import cell_attr_register from ..cell import Cell @@ -48,7 +48,16 @@ class _Conv(Cell): self.kernel_size = kernel_size self.stride = stride self.pad_mode = pad_mode - self.padding = check_int_non_negative(padding) + if isinstance(padding, int): + Validator.check_integer('padding', padding, 0, Rel.GE, self.cls_name) + self.padding = padding + elif isinstance(padding, tuple): + for pad in padding: + Validator.check_integer('padding item', pad, 0, Rel.GE, self.cls_name) + self.padding = padding + else: + raise TypeError("padding type must be int/tuple(int) cannot be {}!".format(type(padding))) + self.dilation = dilation self.group = check_int_positive(group) self.has_bias = has_bias @@ -142,7 +151,10 @@ class Conv2d(_Conv): - pad: Implicit paddings on both sides of the input. The number of `padding` will be padded to the input Tensor borders. `padding` should be greater than or equal to 0. - padding (int): Implicit paddings on both sides of the input. Default: 0. + padding (Union[int, tuple[int]]): Implicit paddings on both sides of the input. If `padding` is one integer, + the padding of top, bottom, left and right is same, equal to padding. If `padding` is tuple with + four integer, the padding of top, bottom, left and right equal to padding[0], padding[1], + padding[2], padding[3] with corresponding. Default: 0. dilation (Union[int, tuple[int]]): The data type is int or tuple with 2 integers. Specifies the dilation rate to use for dilated convolution. If set to be :math:`k > 1`, there will be :math:`k - 1` pixels skipped for each sampling location. Its value should @@ -437,7 +449,10 @@ class Conv2dTranspose(_Conv): - same: Adopted the way of completion. - valid: Adopted the way of discarding. - padding (int): Implicit paddings on both sides of the input. Default: 0. + padding (Union[int, tuple[int]]): Implicit paddings on both sides of the input. If `padding` is one integer, + the padding of top, bottom, left and right is same, equal to padding. If `padding` is tuple with + four integer, the padding of top, bottom, left and right equal to padding[0], padding[1], + padding[2], padding[3] with corresponding. Default: 0. dilation (Union[int, tuple[int]]): The data type is int or tuple with 2 integers. Specifies the dilation rate to use for dilated convolution. If set to be :math:`k > 1`, there will be :math:`k - 1` pixels skipped for each sampling location. Its value should @@ -482,6 +497,9 @@ class Conv2dTranspose(_Conv): kernel_size = twice(kernel_size) stride = twice(stride) dilation = twice(dilation) + Validator.check_value_type('padding', padding, (int, tuple), self.cls_name) + if isinstance(padding, tuple): + Validator.check_integer('padding size', len(padding), 4, Rel.EQ, self.cls_name) # out_channels and in_channels swap. # cause Conv2DBackpropInput's out_channel refers to Conv2D's out_channel, # then Conv2dTranspose's out_channel refers to Conv2DBackpropInput's in_channel. @@ -521,12 +539,16 @@ class Conv2dTranspose(_Conv): dilation=dilation, group=group) self.bias_add = P.BiasAdd() + if isinstance(self.padding, int): + self.padding_top, self.padding_bottom, self.padding_left, self.padding_right = (self.padding,) * 4 + else: + self.padding_top, self.padding_bottom, self.padding_left, self.padding_right = self.padding def set_strategy(self, strategy): self.conv2d_transpose.set_strategy(strategy) return self - def _deconv_output_length(self, input_length, filter_size, stride_size, dilation_size): + def _deconv_output_length(self, input_length, filter_size, stride_size, dilation_size, padding): """Calculate the width and height of output.""" length = 0 filter_size = filter_size + (filter_size - 1) * (dilation_size - 1) @@ -538,14 +560,16 @@ class Conv2dTranspose(_Conv): elif self.is_same: length = input_length * stride_size elif self.is_pad: - length = input_length * stride_size - 2 * self.padding + filter_size - stride_size + length = input_length * stride_size - padding + filter_size - stride_size return length def construct(self, x): n, _, h, w = self.shape(x) - h_out = self._deconv_output_length(h, self.kernel_size[0], self.stride[0], self.dilation[0]) - w_out = self._deconv_output_length(w, self.kernel_size[1], self.stride[1], self.dilation[1]) + h_out = self._deconv_output_length(h, self.kernel_size[0], self.stride[0], self.dilation[0], + self.padding_top + self.padding_bottom) + w_out = self._deconv_output_length(w, self.kernel_size[1], self.stride[1], self.dilation[1], + self.padding_left + self.padding_right) if self.has_bias: return self.bias_add(self.conv2d_transpose(x, self.weight, (n, self.out_channels, h_out, w_out)), self.bias) diff --git a/mindspore/ops/operations/nn_ops.py b/mindspore/ops/operations/nn_ops.py index 560f6a1988c..9acd75d8e42 100644 --- a/mindspore/ops/operations/nn_ops.py +++ b/mindspore/ops/operations/nn_ops.py @@ -1330,7 +1330,7 @@ class Conv2DBackpropInput(PrimitiveWithInfer): validator.check_value_type('pad', pad, (int, tuple), self.name) if isinstance(pad, int): pad = (pad,) * 4 - self.pad = pad + self.padding = pad else: validator.check_integer('pad size', len(pad), 4, Rel.EQ, self.name) @@ -1382,7 +1382,7 @@ class Conv2DBackpropInput(PrimitiveWithInfer): pad_right = pad_needed_w - pad_left pad_list = (pad_top, pad_bottom, pad_left, pad_right) elif self.pad_mode == 'PAD': - pad_list = self.pad + pad_list = self.padding self.add_prim_attr('pad_list', pad_list) out = { 'value': None,