Publishing 2019 R1 content
[platform/upstream/dldt.git] / inference-engine / samples / calibration_tool / calibrator_processors.h
1 // Copyright (C) 2018-2019 Intel Corporation
2 // SPDX-License-Identifier: Apache-2.0
3 //
4
5 #pragma once
6
7 #include <vector>
8 #include <string>
9 #include "inference_engine.hpp"
10 #include "ClassificationProcessor.hpp"
11 #include "SSDObjectDetectionProcessor.hpp"
12 #include "data_stats.h"
13 #include <map>
14 #include <memory>
15
16 /**
17  * Calibrator class representing unified stages for calibration of any kind of networks
18 */
19 class Int8Calibrator {
20 public:
21     /**
22      * Intermediate structure storing of data for measurements of by-layer statistic of accuracy drop
23      */
24     struct SingleLayerData {
25         InferenceEngine::InferRequest _request;
26         std::string _outputName;
27         std::string _outputI8Name;
28         std::vector<float> _int8Accuracy;
29     };
30
31     /**
32      * Initializes state to collect accuracy of FP32 network and collect statistic
33      * of activations. The statistic of activations is stored in _statData and has all max/min for all
34      * layers and for all pictures
35      * The inference of all pictures and real collect of the statistic happen  during call of
36      * Processor::Process()
37      */
38     void collectFP32Statistic();
39
40     /**
41      * Initializes a state to collect intermediate numeric accuracy drop happening during quantization of
42      * certain layer to int8. The numeric accuracy drop is measured using NRMSD metric.
43      *
44      * For this purpose it creates dedicated network for certain layer, initializes this
45      * network by statistic that cause execute dedicated network in int8 mode.
46      *
47      * In addition to  original network we create full original network executed in FP32 mode, and
48      * register all layers as output ones.
49      * Information from these layers is used as
50      *  a) input to dedicated layer networks
51      *  b) comparison for NRMSD algorithm between I8 and FP32 calc
52      *
53      *  The inference of all pictures and real collect of the drop happen during call of
54      * Processor::Process()
55      * @param stat
56      */
57     void collectByLayerStatistic(const InferenceEngine::NetworkStatsMap &stat);
58
59     /**
60      * Initialize state to collect accuracy drop in int8 mode to be compared later vs FP32 accuracy
61      * metric.
62      *
63      * The inference of all pictures and real collect of the accuracy happen during call of
64      * Processor::Process()
65      *
66      * @param stat - The statistic for normalization
67      * @param layersToInt8 - list of layers planned to be executed in int8. if layer is absent in this
68      *                     map, it is assumed that it will be executed in int8
69      * @param convertFullyConnected - should the FullyConnected layers be converted into Int8 or not
70      */
71     void validateInt8Config(const InferenceEngine::NetworkStatsMap &stat,
72                                     const std::map<std::string, bool>& layersToInt8,
73                                     bool convertFullyConnected);
74
75     /**
76      * Statistic collected in the collectFP32Statistic is processed with threshold passed as a parameter
77      * for this method. All values for each layers and for all pictures are sorted and number of min/max
78      * values which  exceed threshold is thrown off
79      * @param threshold - parameter for thrown off outliers in activation statistic
80      * @return InferenceEngine::NetworkStatsMap - mapping of layer name to NetworkNodeStatsPtr
81      */
82     InferenceEngine::NetworkStatsMap getStatistic(float threshold);
83
84     /**
85      * returns by-layer accuracy drop container
86      */
87     std::map<std::string, float> layersAccuracyDrop();
88
89 protected:
90     /**
91      * This function should be called from final callibrator after and each Infer for each picture
92      * It calculates by layer accuracy drop and as well it also collect activation values statistic
93      */
94     void collectCalibrationStatistic(size_t pics);
95
96     /**
97      * This function should be called from calibration class after Infer of all picture
98      * It calculates average NRMSD based accuracy drop for each layer and fills _layersAccuracyDrop
99      */
100     void calculateLayersAccuracyDrop();
101
102     bool _collectByLayer = false;
103     bool _collectStatistic = true;
104     InferencePlugin _pluginI8C;
105     std::string _modelFileNameI8C;
106     InferenceEngine::CNNNetReader networkReaderC;
107     InferenceEngine::InferRequest _inferRequestI8C;
108     int _cBatch = 0;
109
110     size_t _nPictures;
111
112 private:
113     /**
114      * helper function for getting statistic for input layers. For getting statistic for them, we are
115      * adding scalshift just after the input with scale == 1 and shift == 0
116      */
117     CNNLayerPtr addScaleShiftBeforeLayer(std::string name, InferenceEngine::CNNLayer::Ptr beforeLayer,
118                                          size_t port, std::vector<float> scale);
119
120     /**
121      * Returns Normalized root-mean-square deviation metric for two blobs passed to the function
122      */
123     float compare_NRMSD(InferenceEngine::Blob::Ptr res, InferenceEngine::Blob::Ptr ref);
124
125     /**
126      * Creates dedicated i8 network around selected layer. Currently this network beside layer itself
127      * has to have ReLU and ScaleShift layers.
128      * Since Inference Engine API mostly directed to the loading of network from IR, we need to create
129      * such IR first, read through stream and modify network to correspond required parameters
130      */
131     InferenceEngine::CNNNetwork createICNNNetworkForLayer(InferenceEngine::CNNLayer::Ptr layerToClone,
132                                                           bool hasReLU);
133
134     std::map<std::string, float> _layersAccuracyDrop;
135     std::vector<InferenceEngine::ExecutableNetwork> _singleLayerNetworks;
136     std::map<std::string, SingleLayerData> _singleLayerRequests;
137     std::map<std::string, std::string> _inputsFromLayers;
138     AggregatedDataStats _statData;
139 };
140
141 /**
142  * This class represents the only one generalized metric which will be used for comparison of
143  * accuracy drop
144  */
145 struct CalibrationMetrics : public ClassificationProcessor::InferenceMetrics {
146 public:
147     float AccuracyResult = 0;
148 };
149
150 /**
151  * Сalibration class for classification networks.
152  * Responsible for proper post processing of results and calculate of Top1 metric which is used as
153  * universal metric for accuracy and particiapted in verification of accuracy drop
154  */
155 class ClassificationCalibrator : public ClassificationProcessor, public Int8Calibrator {
156 public:
157     ClassificationCalibrator(int nPictures, const std::string &flags_m, const std::string &flags_d,
158                              const std::string &flags_i, int flags_b,
159                               InferenceEngine::InferencePlugin plugin, CsvDumper &dumper, const std::string &flags_l,
160                               PreprocessingOptions preprocessingOptions, bool zeroBackground);
161
162     shared_ptr<InferenceMetrics> Process(bool stream_output = false) override;
163 };
164
165
166 /**
167 * Calibration class for SSD object detection networks.
168 * Responsible for proper post processing of results and calculate of mAP metric which is used as
169 * universal metric for accuracy and participated in verification of accuracy drop
170 */
171 class SSDObjectDetectionCalibrator : public SSDObjectDetectionProcessor, public Int8Calibrator {
172 public:
173     SSDObjectDetectionCalibrator(int nPictures, const std::string &flags_m, const std::string &flags_d,
174                                  const std::string &flags_i, const std::string &subdir, int flags_b,
175                                  double threshold,
176                                  InferencePlugin plugin, CsvDumper &dumper,
177                                  const std::string &flags_a, const std::string &classes_list_file);
178
179     shared_ptr<InferenceMetrics> Process(bool stream_output = false) override;
180 };