0b5ca96bf4050d1df8d93a47457efa14ae1bfa84
[platform/upstream/dldt.git] / inference-engine / tools / calibration_tool / statistics_collector / data_stats.cpp
1 // Copyright (C) 2019 Intel Corporation
2 // SPDX-License-Identifier: Apache-2.0
3 //
4
5 #include <stdlib.h>
6 #include <cfloat>
7 #include <cmath>
8 #include <iostream>
9 #include <limits>
10 #include <vector>
11 #include <algorithm>
12 #include <stdint.h>
13 #include <string>
14
15 #include "data_stats.hpp"
16
17 //----- dataStats -----//
18 void dataStats::registerLayer(const std::string& name, size_t batch, size_t channels) {
19     _registeredLayers.push_back({name, batch, channels});
20 }
21
22 void dataStats::addStatistics(const std::string &name, size_t channel, uint8_t *data, size_t count) {
23     float* dst = new float[count];
24     for (size_t i = 0lu; i < count; i++) {
25         dst[i] = static_cast<float>(data[i]);
26     }
27     addStatistics(name, channel, dst, count);
28     delete[] dst;
29 }
30
31 void dataStats::addStatistics(const std::string &name, size_t channel, short *data, size_t count) {
32     float* dst = new float[count];
33     for (size_t i = 0lu; i < count; i++) {
34         dst[i] = static_cast<float>(data[i]);
35     }
36     addStatistics(name, channel, dst, count);
37     delete[] dst;
38 }
39
40 //----- simpleDataStats -----//
41 void simpleDataStats::registerLayer(const std::string& name, size_t batch, size_t channels) {
42     dataStats::registerLayer(name, batch, channels);
43     _data[name];
44 }
45
46 size_t simpleDataStats::getNumberChannels(const std::string& name) const {
47     auto it = _data.find(name);
48     if (it != _data.end()) {
49         return it->second.size();
50     }
51     return 0lu;
52 }
53
54 void simpleDataStats::addStatistics(const std::string& name, size_t channel, float* data, size_t count) {
55     auto& byChannel = _data[name][channel];
56     // TODO: Investigate synchronization of _data usage
57     // add_mutex.lock();
58     for (size_t i = 0lu; i < count; i++) {
59         if (byChannel._min > data[i]) {
60             byChannel._min = data[i];
61         }
62
63         if (byChannel._max < data[i]) {
64             byChannel._max = data[i];
65         }
66     }
67     // add_mutex.unlock();
68 }
69
70 void simpleDataStats::getDataMinMax(const std::string& name, size_t channel, float& min, float& max, float threshold) {
71     auto it = _data.find(name);
72     if (it != _data.end()) {
73         min = it->second[channel]._min;
74         max = it->second[channel]._max;
75     } else {
76         min = max = 0.f;
77     }
78 }
79
80 //----- TensorStatistic -----//
81 TensorStatistic::TensorStatistic(float* data, size_t count, size_t nbuckets) {
82     _min = std::numeric_limits<float>::max();
83     _max = std::numeric_limits<float>::min();
84     for (size_t i = 0; i < count; i++) {
85         float val = static_cast<float>(data[i]);
86         if (_min > val) {
87             _min = val;
88         }
89
90         if (_max < val) {
91             _max = val;
92         }
93     }
94
95     if (_min == _max) {
96         return;
97     }
98 }
99
100 float TensorStatistic::getMaxValue() const {
101     return _max;
102 }
103
104 float TensorStatistic::getMinValue() const {
105     return _min;
106 }
107 //----- AggregatedDataStats -----//
108 void AggregatedDataStats::registerLayer(const std::string& name, size_t batch, size_t channels) {
109     dataStats::registerLayer(name , batch, channels);
110     _data[name];
111 }
112
113 void AggregatedDataStats::addStatistics(const std::string& name, size_t channel, float* data, size_t count) {
114     auto&& byChannel = _data[name];
115     byChannel[channel].push_back(TensorStatistic(data, count));
116 }
117
118 size_t AggregatedDataStats::getNumberChannels(const std::string& name) const {
119     auto it = _data.find(name);
120     if (it != _data.end()) {
121         return it->second.size();
122     }
123     return 0lu;
124 }
125
126 void AggregatedDataStats::getDataMinMax(const std::string& name, size_t channel, float& min, float& max, float threshold) {
127     // take data by name
128     auto it = _data.find(name);
129     if (it != _data.end()) {
130         auto stats = it->second[channel];
131         // having absolute min/max values, we can create new statistic
132         std::vector<float> maxValues;
133         std::vector<float> minValues;
134         for (size_t i = 0; i < stats.size(); i++) {
135             const TensorStatistic& tsS = stats[i];
136             maxValues.push_back(tsS.getMaxValue());
137             minValues.push_back(tsS.getMinValue());
138         }
139         // define number of elements to throw out
140         size_t elementToTake = static_cast<size_t>(maxValues.size() * (threshold / 100));
141         int elementsToThrow = maxValues.size() - elementToTake;
142         std::sort(maxValues.begin(), maxValues.end());
143         std::sort(minValues.begin(), minValues.end());
144
145         min = minValues[elementsToThrow];
146         max = maxValues[elementToTake - 1];
147     } else {
148         min = max = 0.f;
149     }
150 }