blob: 4935a18b51d55e87f7ea3a3e1c8466ec48de4e91 [file] [log] [blame]
Aron Virginas-Tar98180ef2019-06-26 15:02:47 +01001//
2// Copyright © 2017 Arm Ltd. All rights reserved.
3// SPDX-License-Identifier: MIT
4//
5#pragma once
6
7#include "QuantizeHelper.hpp"
8
9#include <armnn/ArmNN.hpp>
10
11#include <Permute.hpp>
Aron Virginas-Tar48623a02019-10-22 10:00:28 +010012#include <QuantizeHelper.hpp>
Aron Virginas-Tar98180ef2019-06-26 15:02:47 +010013#include <ResolveType.hpp>
14
15#include <backendsCommon/test/CommonTestUtils.hpp>
16
17#include <boost/test/unit_test.hpp>
18
19#include <map>
20#include <vector>
21
22namespace
23{
24
25INetworkPtr CreateTransposeConvolution2dNetwork(const armnn::TransposeConvolution2dDescriptor& descriptor,
26 const armnn::TensorInfo& inputInfo,
27 const armnn::TensorInfo& outputInfo,
28 const armnn::ConstTensor& weights,
29 const armnn::Optional<armnn::ConstTensor>& biases)
30{
31 using namespace armnn;
32
33 INetworkPtr network(INetwork::Create());
34 IConnectableLayer* input = network->AddInputLayer(0, "input");
35 IConnectableLayer* transposeConvolution2d =
36 network->AddTransposeConvolution2dLayer(descriptor, weights, biases, "transposeConvolution2d");
37 IConnectableLayer* output = network->AddOutputLayer(0, "output");
38
39 Connect(input, transposeConvolution2d, inputInfo, 0, 0);
40 Connect(transposeConvolution2d, output, outputInfo, 0, 0);
41
42 return network;
43}
44
45} // anonymous namespace
46
47template<armnn::DataType ArmnnType, armnn::DataType ArmnnBType>
48void TransposeConvolution2dEndToEnd(const std::vector<armnn::BackendId>& backends,
49 armnn::DataLayout dataLayout)
50{
51 using namespace armnn;
52 using T = ResolveType<ArmnnType>;
53
54 constexpr unsigned int batches = 1u;
55 constexpr unsigned int channels = 1u;
56
57 constexpr unsigned int wInput = 3u;
58 constexpr unsigned int hInput = wInput;
59
60 constexpr unsigned int wOutput = 5u;
61 constexpr unsigned int hOutput = wOutput;
62
63 constexpr unsigned int wWeights = 3u;
64 constexpr unsigned int hWeights = wWeights;
65
66 TensorShape inputShape = MakeTensorShape(batches, channels, hInput, wInput, dataLayout);
67 TensorShape outputShape = MakeTensorShape(batches, channels, hOutput, wOutput, dataLayout);
68 TensorShape weightsShape = MakeTensorShape(batches, channels, hWeights, wWeights, dataLayout);
69
70 const float qScale = IsQuantizedType<T>() ? 0.25f : 1.0f;
71 const int32_t qOffset = IsQuantizedType<T>() ? 50 : 0;
72
73 TensorInfo inputInfo(inputShape, ArmnnType, qScale, qOffset);
74 TensorInfo outputInfo(outputShape, ArmnnType, qScale, qOffset);
75 TensorInfo weightsInfo(weightsShape, ArmnnType, qScale, qOffset);
76 TensorInfo biasesInfo({ channels }, ArmnnBType, qScale * qScale, 0);
77
78 std::vector<float> inputData =
79 {
80 1.f, 1.f, 1.f,
81 1.f, 1.f, 1.f,
82 1.f, 1.f, 1.f
83 };
84
85 std::vector<float> weightsData =
86 {
87 1.f, 2.f, 3.f,
88 4.f, 5.f, 6.f,
89 7.f, 8.f, 9.f
90 };
91
92 std::vector<float> biasesData = { 1.f };
93
94 std::vector<float> expectedOutputData =
95 {
96 6.f, 11.f, 6.f, 11.f, 6.f,
97 11.f, 21.f, 11.f, 21.f, 11.f,
98 6.f, 11.f, 6.f, 11.f, 6.f,
99 11.f, 21.f, 11.f, 21.f, 11.f,
100 6.f, 11.f, 6.f, 11.f, 6.f
101 };
102
103 TransposeConvolution2dDescriptor descriptor;
104 descriptor.m_PadLeft = 1;
105 descriptor.m_PadRight = 1;
106 descriptor.m_PadTop = 1;
107 descriptor.m_PadBottom = 1;
108 descriptor.m_StrideX = 2;
109 descriptor.m_StrideY = 2;
110 descriptor.m_BiasEnabled = true;
111 descriptor.m_DataLayout = dataLayout;
112
113 // swizzle data if needed
114 if (dataLayout == armnn::DataLayout::NHWC)
115 {
116 constexpr size_t dataTypeSize = sizeof(float);
117 const armnn::PermutationVector nchwToNhwc = { 0, 3, 1, 2 };
118
119 std::vector<float> tmp(inputData.size());
120 armnnUtils::Permute(inputInfo.GetShape(), nchwToNhwc, inputData.data(), tmp.data(), dataTypeSize);
121 inputData = tmp;
122
123 tmp.resize(weightsData.size());
124 armnnUtils::Permute(weightsInfo.GetShape(), nchwToNhwc, weightsData.data(), tmp.data(), dataTypeSize);
125 weightsData = tmp;
126
127 tmp.resize(expectedOutputData.size());
128 armnnUtils::Permute(outputInfo.GetShape(), nchwToNhwc, expectedOutputData.data(), tmp.data(), dataTypeSize);
129 expectedOutputData = tmp;
130 }
131
132 // quantize data
Aron Virginas-Tar48623a02019-10-22 10:00:28 +0100133 std::vector<T> qInputData = armnnUtils::QuantizedVector<T>(inputData, qScale, qOffset);
134 std::vector<T> qWeightsData = armnnUtils::QuantizedVector<T>(weightsData, qScale, qOffset);
135 std::vector<T> qExpectedOutputData = armnnUtils::QuantizedVector<T>(expectedOutputData, qScale, qOffset);
Aron Virginas-Tar98180ef2019-06-26 15:02:47 +0100136
137 using BT = ResolveType<ArmnnBType>;
Aron Virginas-Tar48623a02019-10-22 10:00:28 +0100138 std::vector<BT> qBiasesData = armnnUtils::QuantizedVector<BT>(biasesData, qScale * qScale, 0);
Aron Virginas-Tar98180ef2019-06-26 15:02:47 +0100139
140 ConstTensor weights(weightsInfo, qWeightsData);
141 ConstTensor biases(biasesInfo, qBiasesData);
142
143 INetworkPtr network = CreateTransposeConvolution2dNetwork(descriptor,
144 inputInfo,
145 outputInfo,
146 weights,
147 Optional<ConstTensor>(biases));
148
149
150 EndToEndLayerTestImpl<ArmnnType, ArmnnType>(std::move(network),
151 { { 0, qInputData } },
152 { { 0, qExpectedOutputData } },
153 backends);
Aron Virginas-Tar48623a02019-10-22 10:00:28 +0100154}