From afbc5ffb0b567ae93fa2765066bd136d72be88ff Mon Sep 17 00:00:00 2001 From: Michalis Spyrou Date: Wed, 3 Oct 2018 14:18:19 +0100 Subject: COMPMID-1621 Deconvolution wrong output calculation Change-Id: Ida71312bcf6dbd854f2ab1efc65f74910c79e152 Reviewed-on: https://eu-gerrit-1.euhpc.arm.com/151510 Tested-by: bsgcomp Reviewed-by: Michele DiGiorgio --- tests/validation/reference/DeconvolutionLayer.cpp | 44 ++++++++++++++++++----- 1 file changed, 35 insertions(+), 9 deletions(-) (limited to 'tests/validation/reference') diff --git a/tests/validation/reference/DeconvolutionLayer.cpp b/tests/validation/reference/DeconvolutionLayer.cpp index ba28b46d3a..5ca3b44baa 100644 --- a/tests/validation/reference/DeconvolutionLayer.cpp +++ b/tests/validation/reference/DeconvolutionLayer.cpp @@ -38,11 +38,23 @@ SimpleTensor deconvolution_layer(const SimpleTensor &src, const SimpleTens const PadStrideInfo &info, const std::pair &a) { // Create reference - const int stride_x = info.stride().first; - const int stride_y = info.stride().second; + const int stride_x = info.stride().first; + const int stride_y = info.stride().second; + const int weights_width = weights.shape().x(); + const int weights_height = weights.shape().y(); + const int weights_upper_dims = weights.shape().total_size() / (weights_width * weights_height); + + // Find the upsampled dimensions + unsigned int out_x = (src.shape().x() - 1) * stride_x + a.first + 1; + unsigned int out_y = (src.shape().y() - 1) * stride_y + a.second + 1; + + // Find the padding needed for the convolution with stride 1 in order to match output shape + unsigned int padx = output_shape.x() - (out_x - weights_width + 1); + unsigned int pady = output_shape.y() - (out_y - weights_height + 1); + out_x += padx; + out_y += pady; + TensorShape scaled_shape = src.shape(); - int out_x = src.shape().x() + (src.shape().x() - 1) * (stride_x - 1) + a.first + 2 * info.pad().first; - int out_y = src.shape().y() + (src.shape().y() - 1) * (stride_y - 1) + a.second + 2 * info.pad().second; scaled_shape.set(0, out_x); scaled_shape.set(1, out_y); SimpleTensor scaled{ scaled_shape, src.data_type(), 1, src.quantization_info() }; @@ -69,14 +81,28 @@ SimpleTensor deconvolution_layer(const SimpleTensor &src, const SimpleTens std::fill_n(scaled.data(), scaled.num_elements(), T(0)); } + // Flip weights by 180 degrees + SimpleTensor weights_flipped{ weights.shape(), weights.data_type(), 1, weights.quantization_info() }; + for(int ud = 0; ud < weights_upper_dims; ++ud) + { + const int offset = ud * weights_width * weights_height; + for(int y = 0; y < weights_height; ++y) + { + for(int x = 0; x < weights_width; ++x) + { + weights_flipped[offset + (weights_height - 1 - y) * weights_width + (weights_width - 1 - x)] = weights[offset + y * weights_width + x]; + } + } + } + for(int slice = 0; slice < num_2d_slices; ++slice) { const int offset_slice_in = slice * width_in * height_in; const int offset_slice_out = slice * width_scaled * height_scaled; - const int start_x = info.pad().first; - const int start_y = ay + info.pad().second; - const int end_y = height_scaled - info.pad().second; - const int end_x = width_scaled - ax - info.pad().first; + const int start_x = padx / 2; + const int start_y = ay + pady / 2; + const int end_y = height_scaled - pady / 2; + const int end_x = width_scaled - ax - padx / 2; for(int yi = start_y, in_y = 0; yi < end_y; yi += stride_y, in_y++) { @@ -90,7 +116,7 @@ SimpleTensor deconvolution_layer(const SimpleTensor &src, const SimpleTens } const PadStrideInfo conv_info(1, 1, 0, 0, 0, 0, DimensionRoundingType::CEIL); - return convolution_layer(scaled, weights, bias, output_shape, conv_info); + return convolution_layer(scaled, weights_flipped, bias, output_shape, conv_info); } template SimpleTensor deconvolution_layer(const SimpleTensor &src, const SimpleTensor &weights, const SimpleTensor &bias, const TensorShape &output_shape, -- cgit v1.2.1