arm_compute v18.03
[platform/upstream/armcl.git] / examples / graph_vgg19.cpp
1 /*
2  * Copyright (c) 2017-2018 ARM Limited.
3  *
4  * SPDX-License-Identifier: MIT
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to
8  * deal in the Software without restriction, including without limitation the
9  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10  * sell copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in all
14  * copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22  * SOFTWARE.
23  */
24 #include "arm_compute/graph/Graph.h"
25 #include "arm_compute/graph/Nodes.h"
26 #include "support/ToolchainSupport.h"
27 #include "utils/GraphUtils.h"
28 #include "utils/Utils.h"
29
30 #include <cstdlib>
31
32 using namespace arm_compute::utils;
33 using namespace arm_compute::graph;
34 using namespace arm_compute::graph_utils;
35
36 /** Example demonstrating how to implement VGG19's network using the Compute Library's graph API
37  *
38  * @param[in] argc Number of arguments
39  * @param[in] argv Arguments ( [optional] Target (0 = NEON, 1 = OpenCL), [optional] Path to the weights folder, [optional] image, [optional] labels )
40  */
41 class GraphVGG19Example : public Example
42 {
43 public:
44     void do_setup(int argc, char **argv) override
45     {
46         std::string data_path; /* Path to the trainable data */
47         std::string image;     /* Image data */
48         std::string label;     /* Label data */
49
50         // Create a preprocessor object
51         const std::array<float, 3> mean_rgb{ { 123.68f, 116.779f, 103.939f } };
52         std::unique_ptr<IPreprocessor> preprocessor = arm_compute::support::cpp14::make_unique<CaffePreproccessor>(mean_rgb);
53
54         // Set target. 0 (NEON), 1 (OpenCL), 2 (OpenCL with Tuner). By default it is NEON
55         const int             int_target_hint  = argc > 1 ? std::strtol(argv[1], nullptr, 10) : 0;
56         TargetHint            target_hint      = set_target_hint(int_target_hint);
57         ConvolutionMethodHint convolution_hint = ConvolutionMethodHint::DIRECT;
58
59         // Parse arguments
60         if(argc < 2)
61         {
62             // Print help
63             std::cout << "Usage: " << argv[0] << " [target] [path_to_data] [image] [labels]\n\n";
64             std::cout << "No data folder provided: using random values\n\n";
65         }
66         else if(argc == 2)
67         {
68             std::cout << "Usage: " << argv[0] << " " << argv[1] << " [path_to_data] [image] [labels]\n\n";
69             std::cout << "No data folder provided: using random values\n\n";
70         }
71         else if(argc == 3)
72         {
73             data_path = argv[2];
74             std::cout << "Usage: " << argv[0] << " " << argv[1] << " " << argv[2] << " [image] [labels]\n\n";
75             std::cout << "No image provided: using random values\n\n";
76         }
77         else if(argc == 4)
78         {
79             data_path = argv[2];
80             image     = argv[3];
81             std::cout << "Usage: " << argv[0] << " " << argv[1] << " " << argv[2] << " " << argv[3] << " [labels]\n\n";
82             std::cout << "No text file with labels provided: skipping output accessor\n\n";
83         }
84         else
85         {
86             data_path = argv[2];
87             image     = argv[3];
88             label     = argv[4];
89         }
90
91         graph << target_hint
92               << convolution_hint
93               << Tensor(TensorInfo(TensorShape(224U, 224U, 3U, 1U), 1, DataType::F32),
94                         get_input_accessor(image, std::move(preprocessor)))
95               // Layer 1
96               << ConvolutionLayer(
97                   3U, 3U, 64U,
98                   get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv1_1_w.npy"),
99                   get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv1_1_b.npy"),
100                   PadStrideInfo(1, 1, 1, 1))
101               << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
102               << ConvolutionLayer(
103                   3U, 3U, 64U,
104                   get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv1_2_w.npy"),
105                   get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv1_2_b.npy"),
106                   PadStrideInfo(1, 1, 1, 1))
107               << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
108               << PoolingLayer(PoolingLayerInfo(PoolingType::MAX, 2, PadStrideInfo(2, 2, 0, 0)))
109               // Layer 2
110               << ConvolutionLayer(
111                   3U, 3U, 128U,
112                   get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv2_1_w.npy"),
113                   get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv2_1_b.npy"),
114                   PadStrideInfo(1, 1, 1, 1))
115               << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
116               << ConvolutionLayer(
117                   3U, 3U, 128U,
118                   get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv2_2_w.npy"),
119                   get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv2_2_b.npy"),
120                   PadStrideInfo(1, 1, 1, 1))
121               << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
122               << PoolingLayer(PoolingLayerInfo(PoolingType::MAX, 2, PadStrideInfo(2, 2, 0, 0)))
123               // Layer 3
124               << ConvolutionLayer(
125                   3U, 3U, 256U,
126                   get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv3_1_w.npy"),
127                   get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv3_1_b.npy"),
128                   PadStrideInfo(1, 1, 1, 1))
129               << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
130               << ConvolutionLayer(
131                   3U, 3U, 256U,
132                   get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv3_2_w.npy"),
133                   get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv3_2_b.npy"),
134                   PadStrideInfo(1, 1, 1, 1))
135               << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
136               << ConvolutionLayer(
137                   3U, 3U, 256U,
138                   get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv3_3_w.npy"),
139                   get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv3_3_b.npy"),
140                   PadStrideInfo(1, 1, 1, 1))
141               << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
142               << ConvolutionLayer(
143                   3U, 3U, 256U,
144                   get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv3_4_w.npy"),
145                   get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv3_4_b.npy"),
146                   PadStrideInfo(1, 1, 1, 1))
147               << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
148               << PoolingLayer(PoolingLayerInfo(PoolingType::MAX, 2, PadStrideInfo(2, 2, 0, 0)))
149               // Layer 4
150               << ConvolutionLayer(
151                   3U, 3U, 512U,
152                   get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv4_1_w.npy"),
153                   get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv4_1_b.npy"),
154                   PadStrideInfo(1, 1, 1, 1))
155               << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
156               << ConvolutionLayer(
157                   3U, 3U, 512U,
158                   get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv4_2_w.npy"),
159                   get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv4_2_b.npy"),
160                   PadStrideInfo(1, 1, 1, 1))
161               << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
162               << ConvolutionLayer(
163                   3U, 3U, 512U,
164                   get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv4_3_w.npy"),
165                   get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv4_3_b.npy"),
166                   PadStrideInfo(1, 1, 1, 1))
167               << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
168               << ConvolutionLayer(
169                   3U, 3U, 512U,
170                   get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv4_4_w.npy"),
171                   get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv4_4_b.npy"),
172                   PadStrideInfo(1, 1, 1, 1))
173               << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
174               << PoolingLayer(PoolingLayerInfo(PoolingType::MAX, 2, PadStrideInfo(2, 2, 0, 0)))
175               // Layer 5
176               << ConvolutionLayer(
177                   3U, 3U, 512U,
178                   get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv5_1_w.npy"),
179                   get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv5_1_b.npy"),
180                   PadStrideInfo(1, 1, 1, 1))
181               << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
182               << ConvolutionLayer(
183                   3U, 3U, 512U,
184                   get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv5_2_w.npy"),
185                   get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv5_2_b.npy"),
186                   PadStrideInfo(1, 1, 1, 1))
187               << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
188               << ConvolutionLayer(
189                   3U, 3U, 512U,
190                   get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv5_3_w.npy"),
191                   get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv5_3_b.npy"),
192                   PadStrideInfo(1, 1, 1, 1))
193               << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
194               << ConvolutionLayer(
195                   3U, 3U, 512U,
196                   get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv5_4_w.npy"),
197                   get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv5_4_b.npy"),
198                   PadStrideInfo(1, 1, 1, 1))
199               << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
200               << PoolingLayer(PoolingLayerInfo(PoolingType::MAX, 2, PadStrideInfo(2, 2, 0, 0)))
201               // Layer 6
202               << FullyConnectedLayer(
203                   4096U,
204                   get_weights_accessor(data_path, "/cnn_data/vgg19_model/fc6_w.npy"),
205                   get_weights_accessor(data_path, "/cnn_data/vgg19_model/fc6_b.npy"))
206               << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
207               // Layer 7
208               << FullyConnectedLayer(
209                   4096U,
210                   get_weights_accessor(data_path, "/cnn_data/vgg19_model/fc7_w.npy"),
211                   get_weights_accessor(data_path, "/cnn_data/vgg19_model/fc7_b.npy"))
212               << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
213               // Layer 8
214               << FullyConnectedLayer(
215                   1000U,
216                   get_weights_accessor(data_path, "/cnn_data/vgg19_model/fc8_w.npy"),
217                   get_weights_accessor(data_path, "/cnn_data/vgg19_model/fc8_b.npy"))
218               // Softmax
219               << SoftmaxLayer()
220               << Tensor(get_output_accessor(label, 5));
221
222         // In order to enable the OpenCL tuner, graph_init() has to be called only when all nodes have been instantiated
223         graph.graph_init(int_target_hint == 2);
224     }
225     void do_run() override
226     {
227         // Run graph
228         graph.run();
229     }
230
231 private:
232     Graph graph{};
233 };
234
235 /** Main program for VGG19
236  *
237  * @param[in] argc Number of arguments
238  * @param[in] argv Arguments ( [optional] Target (0 = NEON, 1 = OpenCL), [optional] Path to the weights folder, [optional] image, [optional] labels )
239  */
240 int main(int argc, char **argv)
241 {
242     return arm_compute::utils::run_example<GraphVGG19Example>(argc, argv);
243 }