|
26 | 26 | from nncf.common.quantization.structs import QuantizerGroup |
27 | 27 | from nncf.common.tensor_statistics.statistic_point import StatisticPoint |
28 | 28 | from nncf.common.tensor_statistics.statistic_point import StatisticPointsContainer |
| 29 | +from nncf.experimental.common.tensor_statistics.collectors import HistogramAggregator |
29 | 30 | from nncf.experimental.common.tensor_statistics.collectors import MaxAggregator |
30 | 31 | from nncf.experimental.common.tensor_statistics.collectors import MeanAggregator |
31 | 32 | from nncf.experimental.common.tensor_statistics.collectors import MinAggregator |
| 33 | +from nncf.experimental.common.tensor_statistics.collectors import RawReducer |
32 | 34 | from nncf.experimental.common.tensor_statistics.collectors import TensorCollector |
33 | 35 | from nncf.experimental.common.tensor_statistics.statistics import MinMaxTensorStatistic |
34 | 36 | from nncf.parameters import ModelType |
35 | 37 | from nncf.quantization.advanced_parameters import OverflowFix |
36 | 38 | from nncf.quantization.algorithms.min_max.algorithm import MinMaxQuantization |
37 | 39 | from nncf.quantization.passes import transform_to_inference_graph |
| 40 | +from nncf.quantization.range_estimator import AggregatorType |
38 | 41 | from nncf.quantization.range_estimator import RangeEstimatorParametersSet |
39 | 42 | from nncf.scopes import IgnoredScope |
40 | 43 | from nncf.tensor import Tensor |
@@ -154,6 +157,14 @@ def check_is_mean_min_max_statistic_collector(self, tensor_collector: TensorColl |
154 | 157 | assert MeanAggregator in aggrs |
155 | 158 | assert aggrs[0].__class__ == aggrs[1].__class__ |
156 | 159 |
|
| 160 | + def check_is_histogram_statistic_collector(self, tensor_collector: TensorCollector): |
| 161 | + reducers = [r.__class__ for r in tensor_collector.reducers] |
| 162 | + assert len(reducers) == 1 |
| 163 | + assert RawReducer in reducers |
| 164 | + aggrs = [aggr.__class__ for aggr in tensor_collector.aggregators.values()] |
| 165 | + assert len(aggrs) == 1 |
| 166 | + assert HistogramAggregator in aggrs |
| 167 | + |
157 | 168 | @abstractmethod |
158 | 169 | def check_quantize_outputs_fq_num(self, quantize_outputs, act_num_q, weight_num_q): |
159 | 170 | pass |
@@ -193,32 +204,71 @@ def nncf_graph_cls(self): |
193 | 204 | def get_backend_tensor(self, value): |
194 | 205 | pass |
195 | 206 |
|
196 | | - @pytest.mark.parametrize( |
197 | | - "range_estimator_params", [RangeEstimatorParametersSet.MINMAX, RangeEstimatorParametersSet.MEAN_MINMAX, None] |
198 | | - ) |
| 207 | + RANGE_ESTIMATOR_TEST_PARAMS = [ |
| 208 | + RangeEstimatorParametersSet.MINMAX, |
| 209 | + RangeEstimatorParametersSet.MEAN_MINMAX, |
| 210 | + None, |
| 211 | + RangeEstimatorParametersSet.HISTOGRAM, |
| 212 | + ] |
| 213 | + |
| 214 | + @pytest.mark.parametrize("range_estimator_params", RANGE_ESTIMATOR_TEST_PARAMS) |
199 | 215 | def test_range_estimator_per_tensor(self, test_params, range_estimator_params): |
| 216 | + for stat_point_, tensor_collector in self._get_stat_points( |
| 217 | + test_params, range_estimator_params, "test_range_estimator_per_tensor" |
| 218 | + ): |
| 219 | + if stat_point_.target_point.is_weight_target_point(): |
| 220 | + # default tensor_collector for weights |
| 221 | + self.check_is_min_max_statistic_collector(tensor_collector) |
| 222 | + continue |
| 223 | + if range_estimator_params in [None, RangeEstimatorParametersSet.MEAN_MINMAX]: |
| 224 | + # default tensor_collector for per-tensor |
| 225 | + self.check_is_mean_min_max_statistic_collector(tensor_collector) |
| 226 | + elif range_estimator_params == RangeEstimatorParametersSet.MINMAX: |
| 227 | + self.check_is_min_max_statistic_collector(tensor_collector) |
| 228 | + elif range_estimator_params == RangeEstimatorParametersSet.HISTOGRAM: |
| 229 | + self.check_is_histogram_statistic_collector(tensor_collector) |
| 230 | + |
| 231 | + @pytest.mark.parametrize("range_estimator_params", RANGE_ESTIMATOR_TEST_PARAMS) |
| 232 | + def test_range_estimator_per_channel(self, test_params, range_estimator_params): |
| 233 | + for stat_point_, tensor_collector in self._get_stat_points( |
| 234 | + test_params, range_estimator_params, "test_range_estimator_per_channel" |
| 235 | + ): |
| 236 | + if stat_point_.target_point.is_weight_target_point(): |
| 237 | + # default tensor_collector for weights |
| 238 | + self.check_is_min_max_statistic_collector(tensor_collector) |
| 239 | + continue |
| 240 | + if range_estimator_params in [ |
| 241 | + None, |
| 242 | + RangeEstimatorParametersSet.MINMAX, |
| 243 | + RangeEstimatorParametersSet.HISTOGRAM, |
| 244 | + ]: |
| 245 | + # default tensor_collector for per-tensor |
| 246 | + self.check_is_min_max_statistic_collector(tensor_collector) |
| 247 | + elif range_estimator_params == RangeEstimatorParametersSet.MEAN_MINMAX: |
| 248 | + self.check_is_mean_min_max_statistic_collector(tensor_collector) |
| 249 | + |
| 250 | + def _get_stat_points(self, test_params, range_estimator_params, test_params_key): |
200 | 251 | min_max_algo = MinMaxQuantization(activations_range_estimator_params=range_estimator_params) |
201 | 252 | min_max_algo._backend_entity = self.get_algo_backend() |
202 | 253 | assert min_max_algo._range_estimator_params[QuantizerGroup.ACTIVATIONS] == range_estimator_params |
203 | 254 |
|
204 | | - params = test_params["test_range_estimator_per_tensor"] |
| 255 | + params = test_params[test_params_key] |
205 | 256 | stat_points = min_max_algo.get_statistic_points(params["model"], params["nncf_graph"]) |
206 | 257 | assert len(stat_points) == params["stat_points_num"] |
207 | | - |
208 | 258 | for stat_point in stat_points.values(): |
209 | 259 | for stat_point_ in stat_point: |
210 | 260 | for tensor_collector in stat_point_.algorithm_to_tensor_collectors[min_max_algo._algorithm_key]: |
211 | | - if stat_point_.target_point.is_weight_target_point(): |
212 | | - # default tensor_collector for weights |
213 | | - self.check_is_min_max_statistic_collector(tensor_collector) |
214 | | - continue |
215 | | - if range_estimator_params is None: |
216 | | - # default tensor_collector for per-tensor |
217 | | - self.check_is_mean_min_max_statistic_collector(tensor_collector) |
218 | | - if range_estimator_params == RangeEstimatorParametersSet.MINMAX: |
219 | | - self.check_is_min_max_statistic_collector(tensor_collector) |
220 | | - elif range_estimator_params == RangeEstimatorParametersSet.MEAN_MINMAX: |
221 | | - self.check_is_mean_min_max_statistic_collector(tensor_collector) |
| 261 | + yield stat_point_, tensor_collector |
| 262 | + |
| 263 | + def test_unsupported_params(self, test_params): |
| 264 | + range_estimator_params = deepcopy(RangeEstimatorParametersSet.HISTOGRAM) |
| 265 | + range_estimator_params.min.aggregator_type = AggregatorType.MAX |
| 266 | + |
| 267 | + params = test_params["test_range_estimator_per_tensor"] |
| 268 | + min_max_algo = MinMaxQuantization(activations_range_estimator_params=range_estimator_params) |
| 269 | + min_max_algo._backend_entity = self.get_algo_backend() |
| 270 | + with pytest.raises(nncf.ParameterNotSupportedError): |
| 271 | + min_max_algo.get_statistic_points(params["model"], params["nncf_graph"]) |
222 | 272 |
|
223 | 273 | @pytest.mark.parametrize("quantize_outputs", [False, True]) |
224 | 274 | def test_quantize_outputs(self, test_params, quantize_outputs): |
|
0 commit comments