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