aboutsummaryrefslogtreecommitdiff
path: root/tests/validation
diff options
context:
space:
mode:
authorMichalis Spyrou <michalis.spyrou@arm.com>2018-10-03 14:18:19 +0100
committerAnthony Barbier <anthony.barbier@arm.com>2018-11-02 16:55:45 +0000
commitafbc5ffb0b567ae93fa2765066bd136d72be88ff (patch)
tree328005d70d5526609a9d84173a317fd1f10b4ed2 /tests/validation
parent67d94d29c154a376d12e582421323c1d250da20c (diff)
downloadComputeLibrary-afbc5ffb0b567ae93fa2765066bd136d72be88ff.tar.gz
COMPMID-1621 Deconvolution wrong output calculation
Change-Id: Ida71312bcf6dbd854f2ab1efc65f74910c79e152 Reviewed-on: https://eu-gerrit-1.euhpc.arm.com/151510 Tested-by: bsgcomp <bsgcomp@arm.com> Reviewed-by: Michele DiGiorgio <michele.digiorgio@arm.com>
Diffstat (limited to 'tests/validation')
-rw-r--r--tests/validation/CL/DeconvolutionLayer.cpp4
-rw-r--r--tests/validation/NEON/DeconvolutionLayer.cpp2
-rw-r--r--tests/validation/fixtures/DeconvolutionLayerFixture.h4
-rw-r--r--tests/validation/reference/DeconvolutionLayer.cpp44
4 files changed, 40 insertions, 14 deletions
diff --git a/tests/validation/CL/DeconvolutionLayer.cpp b/tests/validation/CL/DeconvolutionLayer.cpp
index 2aa7cfe7c1..84a2b01797 100644
--- a/tests/validation/CL/DeconvolutionLayer.cpp
+++ b/tests/validation/CL/DeconvolutionLayer.cpp
@@ -48,7 +48,7 @@ RelativeTolerance<half_float::half> tolerance_f16(half_float::half(0.2)); /**< T
constexpr AbsoluteTolerance<float> tolerance_qasymm8(1.0); /**< Tolerance value for comparing reference's output against implementation's output for quantized data types */
constexpr float tolerance_num = 0.07f; /**< Tolerance number */
-const auto data4x4 = datasets::SmallDeconvolutionShapes() * framework::dataset::make("StrideX", 1, 4) * framework::dataset::make("StrideY", 1, 4) * framework::dataset::make("PadX", 0, 3)
+const auto data4x4 = datasets::SmallDeconvolutionShapes() * framework::dataset::make("StrideX", 1, 5) * framework::dataset::make("StrideY", 1, 5) * framework::dataset::make("PadX", 0, 3)
* framework::dataset::make("PadY", 0, 3) * framework::dataset::make("ax", 0) * framework::dataset::make("ay", 0) * framework::dataset::make("NumKernels", { 1, 3 });
const auto data3x3 = datasets::SmallDeconvolutionShapes() * framework::dataset::make("StrideX", 1, 4) * framework::dataset::make("StrideY", 1, 4) * framework::dataset::make("PadX", 0, 2)
@@ -71,7 +71,7 @@ DATA_TEST_CASE(Configuration, framework::DatasetMode::ALL, (combine(datasets::Sm
const unsigned int num_kernels = 1;
const TensorShape weights_shape(kernel_size_x, kernel_size_y, input_shape.z(), num_kernels);
const TensorShape bias_shape(num_kernels);
- auto out_dim = deconvolution_output_dimensions(input_shape.x(), input_shape.y(), kernel_size_x, kernel_size_y, 1, 1, 0, 0, 1, 1);
+ auto out_dim = deconvolution_output_dimensions(input_shape.x(), input_shape.y(), kernel_size_x, kernel_size_y, 1, 1, 1, 1);
TensorShape output_shape = deconvolution_output_shape(out_dim, input_shape, weights_shape);
// Create tensors
diff --git a/tests/validation/NEON/DeconvolutionLayer.cpp b/tests/validation/NEON/DeconvolutionLayer.cpp
index 277953badb..eb643b8e7c 100644
--- a/tests/validation/NEON/DeconvolutionLayer.cpp
+++ b/tests/validation/NEON/DeconvolutionLayer.cpp
@@ -67,7 +67,7 @@ DATA_TEST_CASE(Configuration, framework::DatasetMode::ALL, (combine(datasets::Sm
const unsigned int num_kernels = 1;
const TensorShape weights_shape(kernel_size_x, kernel_size_y, input_shape.z(), num_kernels);
const TensorShape bias_shape(num_kernels);
- auto out_dim = deconvolution_output_dimensions(input_shape.x(), input_shape.y(), kernel_size_x, kernel_size_y, 1, 1, 0, 0, 1, 1);
+ auto out_dim = deconvolution_output_dimensions(input_shape.x(), input_shape.y(), kernel_size_x, kernel_size_y, 1, 1, 1, 1);
TensorShape output_shape = deconvolution_output_shape(out_dim, input_shape, weights_shape);
// Create tensors
diff --git a/tests/validation/fixtures/DeconvolutionLayerFixture.h b/tests/validation/fixtures/DeconvolutionLayerFixture.h
index 6a8b4f220c..d3a7be74b0 100644
--- a/tests/validation/fixtures/DeconvolutionLayerFixture.h
+++ b/tests/validation/fixtures/DeconvolutionLayerFixture.h
@@ -160,7 +160,7 @@ public:
const TensorShape bias_shape(num_kernels);
const PadStrideInfo info(sx, sy, padx, pady, DimensionRoundingType::CEIL);
const std::pair<unsigned int, unsigned int> inner_border(inner_border_right, inner_border_top);
- auto out_dim = deconvolution_output_dimensions(input_shape.x(), input_shape.y(), kernel_size_x, kernel_size_y, padx, pady, inner_border.first, inner_border.second, sx, sy);
+ auto out_dim = deconvolution_output_dimensions(input_shape.x(), input_shape.y(), kernel_size_x, kernel_size_y, padx, pady, sx, sy);
TensorShape output_shape = deconvolution_output_shape(out_dim, input_shape, weights_shape);
DeconvolutionLayerFixtureBase<TensorType, AccessorType, FunctionType, T>::setup(input_shape, weights_shape, bias_shape, output_shape, info, inner_border, data_type, QuantizationInfo());
}
@@ -179,7 +179,7 @@ public:
const TensorShape bias_shape(num_kernels);
const PadStrideInfo info(sx, sy, padx, pady, DimensionRoundingType::CEIL);
const std::pair<unsigned int, unsigned int> inner_border(inner_border_right, inner_border_top);
- auto out_dim = deconvolution_output_dimensions(input_shape.x(), input_shape.y(), kernel_size_x, kernel_size_y, padx, pady, inner_border.first, inner_border.second, sx, sy);
+ auto out_dim = deconvolution_output_dimensions(input_shape.x(), input_shape.y(), kernel_size_x, kernel_size_y, padx, pady, sx, sy);
TensorShape output_shape = deconvolution_output_shape(out_dim, input_shape, weights_shape);
DeconvolutionLayerFixtureBase<TensorType, AccessorType, FunctionType, T>::setup(input_shape, weights_shape, bias_shape, output_shape, info, inner_border, data_type, quantization_info);
}
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<T> deconvolution_layer(const SimpleTensor<T> &src, const SimpleTens
const PadStrideInfo &info, const std::pair<unsigned int, unsigned int> &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<T> scaled{ scaled_shape, src.data_type(), 1, src.quantization_info() };
@@ -69,14 +81,28 @@ SimpleTensor<T> deconvolution_layer(const SimpleTensor<T> &src, const SimpleTens
std::fill_n(scaled.data(), scaled.num_elements(), T(0));
}
+ // Flip weights by 180 degrees
+ SimpleTensor<T> 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<T> deconvolution_layer(const SimpleTensor<T> &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<uint8_t> deconvolution_layer(const SimpleTensor<uint8_t> &src, const SimpleTensor<uint8_t> &weights, const SimpleTensor<int32_t> &bias, const TensorShape &output_shape,