ArmNN
 21.08
FullyConnectedEndToEndTestImpl.hpp
Go to the documentation of this file.
1 //
2 // Copyright © 2021 Arm Ltd and Contributors. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5 #pragma once
6 
7 #include "CommonTestUtils.hpp"
8 
9 #include <ResolveType.hpp>
10 
11 #include <armnn/INetwork.hpp>
12 
14 
15 #include <doctest/doctest.h>
16 
17 #include <vector>
18 
19 namespace
20 {
21 
22 armnn::INetworkPtr CreateFullyConnectedNetworkNonConstWeights(const armnn::TensorInfo& inputTensorInfo,
23  const armnn::TensorInfo& outputTensorInfo,
24  const armnn::TensorInfo& weightsTensorInfo,
26 {
28 
29  armnn::IConnectableLayer* inputLayer = network->AddInputLayer(0, "Input");
30  armnn::IConnectableLayer* weightsInputLayer = network->AddInputLayer(1, "Weights_Input");
31  armnn::IConnectableLayer* fullyConnectedLayer = network->AddFullyConnectedLayer(descriptor, "Fully_Connected");
32  armnn::IConnectableLayer* outputLayer = network->AddOutputLayer(0, "Output");
33 
34  Connect(inputLayer, fullyConnectedLayer, inputTensorInfo, 0, 0);
35  Connect(weightsInputLayer, fullyConnectedLayer, weightsTensorInfo, 0, 1);
36  Connect(fullyConnectedLayer, outputLayer, outputTensorInfo, 0, 0);
37 
38  return network;
39 }
40 
41 armnn::INetworkPtr CreateFullyConnectedNetworkNonConstWeightsConstBias(const armnn::TensorInfo& inputTensorInfo,
42  const armnn::TensorInfo& outputTensorInfo,
43  const armnn::TensorInfo& weightsTensorInfo,
44  const armnn::TensorInfo& biasTensorInfo,
45  const armnn::ConstTensor& biasConstantTensor,
47 {
49 
50  armnn::IConnectableLayer* inputLayer = network->AddInputLayer(0, "Input");
51  armnn::IConnectableLayer* weightsInputLayer = network->AddInputLayer(1, "Weights_Input");
52  armnn::IConnectableLayer* biasLayer = network->AddConstantLayer(biasConstantTensor, "Weights");
53  armnn::IConnectableLayer* fullyConnectedLayer = network->AddFullyConnectedLayer(descriptor, "Fully_Connected");
54  armnn::IConnectableLayer* outputLayer = network->AddOutputLayer(0, "Output");
55 
56  Connect(inputLayer, fullyConnectedLayer, inputTensorInfo, 0, 0);
57  Connect(weightsInputLayer, fullyConnectedLayer, weightsTensorInfo, 0, 1);
58  Connect(biasLayer, fullyConnectedLayer, biasTensorInfo, 0, 2);
59  Connect(fullyConnectedLayer, outputLayer, outputTensorInfo, 0, 0);
60 
61  return network;
62 }
63 
64 armnn::INetworkPtr CreateFullyConnectedNetworkConstWeightsNonConstBias(const armnn::TensorInfo& inputTensorInfo,
65  const armnn::TensorInfo& outputTensorInfo,
66  const armnn::TensorInfo& weightsTensorInfo,
67  const armnn::TensorInfo& biasTensorInfo,
68  const armnn::ConstTensor& weightsConstantTensor,
70 {
72 
73  armnn::IConnectableLayer* inputLayer = network->AddInputLayer(0, "Input");
74  armnn::IConnectableLayer* weightsLayer = network->AddConstantLayer(weightsConstantTensor, "Weights");
75  armnn::IConnectableLayer* biasLayer = network->AddInputLayer(2, "Bias_Input");
76  armnn::IConnectableLayer* fullyConnectedLayer = network->AddFullyConnectedLayer(descriptor, "Fully_Connected");
77  armnn::IConnectableLayer* outputLayer = network->AddOutputLayer(0, "Output");
78 
79  Connect(inputLayer, fullyConnectedLayer, inputTensorInfo, 0, 0);
80  Connect(weightsLayer, fullyConnectedLayer, weightsTensorInfo, 0, 1);
81  Connect(biasLayer, fullyConnectedLayer, biasTensorInfo, 0, 2);
82  Connect(fullyConnectedLayer, outputLayer, outputTensorInfo, 0, 0);
83 
84  return network;
85 }
86 
87 template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
88 void FullyConnectedWithDynamicWeightsEndToEnd(const std::vector<armnn::BackendId>& backends)
89 {
90  using namespace armnn;
91 
92  armnn::TensorInfo inputTensorInfo({ 1, 1, 2, 3 }, ArmnnType);
93  inputTensorInfo.SetQuantizationScale(0.1f);
94  inputTensorInfo.SetQuantizationOffset(63);
95 
96  armnn::TensorInfo outputTensorInfo({ 1, 2 }, ArmnnType);
97  outputTensorInfo.SetQuantizationScale(5.f);
98  outputTensorInfo.SetQuantizationOffset(10);
99 
100  armnn::TensorInfo weightsTensorInfo({ 2, 6 }, ArmnnType);
101  weightsTensorInfo.SetQuantizationScale(0.2f);
102  weightsTensorInfo.SetQuantizationOffset(93);
103 
104  FullyConnectedDescriptor descriptor;
105  descriptor.m_ConstantWeights = false;
106  descriptor.m_BiasEnabled = false;
107  descriptor.m_TransposeWeightMatrix = true;
108 
109  std::vector<T> inputData {
110  -1.2f, 6.1f, -3.5f,
111  18.8f, -5.5f, 2.9f
112  };
113 
114  std::vector<T> weightsData {
115  -8.4f, 20.0f, -10.4f, -8, 16.4f, -11.8f,
116  23.4f, 10.4f, -14.0f, -3.8f, -11.8f, 11.4f
117  };
118 
119  std::vector<T> floatExpectedOutputData {
120  -107.04f, 110.f
121  };
122  std::vector<T> expectedOutputData = armnnUtils::QuantizedVector<T>(floatExpectedOutputData);
123 
124  armnn::INetworkPtr network = CreateFullyConnectedNetworkNonConstWeights(inputTensorInfo,
125  outputTensorInfo,
126  weightsTensorInfo,
127  descriptor);
128 
129  CHECK(network);
130 
131  std::map<int, std::vector<T>> inputTensorData = {{ 0, inputData }, {1, weightsData}};
132  std::map<int, std::vector<T>> expectedOutputTensorData = {{ 0, expectedOutputData }};
133 
134  EndToEndLayerTestImpl<ArmnnType, ArmnnType>(move(network),
135  inputTensorData,
136  expectedOutputTensorData,
137  backends,
138  1.0f);
139 }
140 
141 template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
142 void FullyConnectedWithDynamicOrConstantInputsEndToEnd(const std::vector<armnn::BackendId>& backends,
143  const bool transposeWeights,
144  const bool constantWeightsOrBias)
145 {
146  unsigned int inputWidth = 1;
147  unsigned int inputHeight = 1;
148  unsigned int inputChannels = 5;
149  unsigned int inputNum = 2;
150 
151  unsigned int outputChannels = 3;
152  unsigned int outputNum = 2;
153 
154  unsigned int inputShape[] = { inputNum, inputChannels, inputHeight, inputWidth };
155  unsigned int outputShape[] = { outputNum, outputChannels };
156  unsigned int weightsShape[] = { inputChannels, outputChannels };
157 
158  if (transposeWeights)
159  {
160  std::swap(weightsShape[0], weightsShape[1]);
161  }
162 
163  unsigned int biasShape[] = { outputChannels };
164 
165  armnn::TensorInfo inputTensorInfo = armnn::TensorInfo(4, inputShape, armnn::DataType::Float32);
166  armnn::TensorInfo outputTensorInfo = armnn::TensorInfo(2, outputShape, armnn::DataType::Float32);
167  armnn::TensorInfo weightsDesc = armnn::TensorInfo(2, weightsShape, armnn::DataType::Float32);
169 
170  std::vector<float> input =
171  {
172  1.0f, 2.0f, 3.0f, 4.0f, 5.0f,
173  5.0f, 4.0f, 3.0f, 2.0f, 1.0f
174  };
175 
176  std::vector<float> weights =
177  {
178  .5f, 2.f, .5f,
179  .5f, 2.f, 1.f,
180  .5f, 2.f, 2.f,
181  .5f, 2.f, 3.f,
182  .5f, 2.f, 4.f
183  };
184 
185  if (transposeWeights)
186  {
187  weights =
188  {
189  .5f, .5f, .5f, .5f, .5f,
190  2.f, 2.f, 2.f, 2.f, 2.f,
191  .5f, 1.f, 2.f, 3.f, 4.f
192  };
193  }
194 
195  std::vector<float> biasValues = std::vector<float>({10.f, 20.f, 30.f});
196 
197  std::vector<float> expectedOutput =
198  {
199  0.5f + 1.0f + 1.5f + 2.0f + 2.5f + biasValues[0],
200  2.0f + 4.0f + 6.0f + 8.0f + 10.f + biasValues[1],
201  0.5f + 2.0f + 6.0f + 12.f + 20.f + biasValues[2],
202 
203  2.5f + 2.0f + 1.5f + 1.0f + 0.5f + biasValues[0],
204  10.0f + 8.0f + 6.0f + 4.0f + 2.f + biasValues[1],
205  2.5f + 4.0f + 6.0f + 6.f + 4.f + biasValues[2]
206  };
207 
208  FullyConnectedDescriptor descriptor;
209  descriptor.m_BiasEnabled = true;
210  descriptor.m_TransposeWeightMatrix = transposeWeights;
211  descriptor.m_ConstantWeights = constantWeightsOrBias;
212 
213  if (!constantWeightsOrBias)
214  {
215  // Tests non constant weights and constant bias.
216  ConstTensor biasConstantTensor(biasesDesc, biasValues.data());
217 
218  armnn::INetworkPtr network = CreateFullyConnectedNetworkNonConstWeightsConstBias(inputTensorInfo,
219  outputTensorInfo,
220  weightsDesc,
221  biasesDesc,
222  biasConstantTensor,
223  descriptor);
224  CHECK(network);
225 
226  std::map<int, std::vector<T>> inputTensorData = {{ 0, input }, {1, weights}};
227  std::map<int, std::vector<T>> expectedOutputTensorData = {{ 0, expectedOutput }};
228 
229  EndToEndLayerTestImpl<ArmnnType, ArmnnType>(move(network),
230  inputTensorData,
231  expectedOutputTensorData,
232  backends,
233  1.0f);
234  }
235  else
236  {
237  // Tests constant weights and non constant bias.
238  ConstTensor weightsConstantTensor(weightsDesc, weights.data());
239 
240  armnn::INetworkPtr network = CreateFullyConnectedNetworkConstWeightsNonConstBias(inputTensorInfo,
241  outputTensorInfo,
242  weightsDesc,
243  biasesDesc,
244  weightsConstantTensor,
245  descriptor);
246  CHECK(network);
247 
248  std::map<int, std::vector<T>> inputTensorData = {{ 0, input }, {2, biasValues}};
249  std::map<int, std::vector<T>> expectedOutputTensorData = {{ 0, expectedOutput }};
250 
251  EndToEndLayerTestImpl<ArmnnType, ArmnnType>(move(network),
252  inputTensorData,
253  expectedOutputTensorData,
254  backends,
255  1.0f);
256  }
257 }
258 
259 } // anonymous namespace
Interface for a layer that is connectable to other layers via InputSlots and OutputSlots.
Definition: INetwork.hpp:61
void swap(OriginsDescriptor &first, OriginsDescriptor &second)
bool m_TransposeWeightMatrix
Enable/disable transpose weight matrix.
Copyright (c) 2021 ARM Limited and Contributors.
A FullyConnectedDescriptor for the FullyConnectedLayer.
bool m_BiasEnabled
Enable/disable bias.
A tensor defined by a TensorInfo (shape and data type) and an immutable backing store.
Definition: Tensor.hpp:327
void SetQuantizationScale(float scale)
Definition: Tensor.cpp:475
void SetQuantizationOffset(int32_t offset)
Definition: Tensor.cpp:491
void Connect(armnn::IConnectableLayer *from, armnn::IConnectableLayer *to, const armnn::TensorInfo &tensorInfo, unsigned int fromIndex, unsigned int toIndex)
Definition: TestUtils.cpp:12
std::unique_ptr< INetwork, void(*)(INetwork *network)> INetworkPtr
Definition: INetwork.hpp:172
static INetworkPtr Create(NetworkOptions networkOptions={})
Definition: Network.cpp:530
bool m_ConstantWeights
Enable/disable constant weights and biases.