mct-nightly 2.2.0.20241012.448__py3-none-any.whl → 2.2.0.20241018.449__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (22) hide show
  1. {mct_nightly-2.2.0.20241012.448.dist-info → mct_nightly-2.2.0.20241018.449.dist-info}/METADATA +1 -1
  2. {mct_nightly-2.2.0.20241012.448.dist-info → mct_nightly-2.2.0.20241018.449.dist-info}/RECORD +22 -14
  3. model_compression_toolkit/__init__.py +1 -1
  4. model_compression_toolkit/qat/keras/quantizer/{base_keras_qat_quantizer.py → base_keras_qat_weight_quantizer.py} +3 -13
  5. model_compression_toolkit/qat/keras/quantizer/lsq/symmetric_lsq.py +5 -126
  6. model_compression_toolkit/qat/keras/quantizer/lsq/uniform_lsq.py +4 -121
  7. model_compression_toolkit/qat/keras/quantizer/quantization_builder.py +7 -6
  8. model_compression_toolkit/qat/keras/quantizer/ste_rounding/symmetric_ste.py +4 -119
  9. model_compression_toolkit/qat/keras/quantizer/ste_rounding/uniform_ste.py +5 -95
  10. model_compression_toolkit/trainable_infrastructure/keras/activation_quantizers/__init__.py +20 -0
  11. model_compression_toolkit/trainable_infrastructure/keras/activation_quantizers/base_activation_quantizer.py +22 -0
  12. model_compression_toolkit/trainable_infrastructure/keras/activation_quantizers/lsq/__init__.py +14 -0
  13. model_compression_toolkit/trainable_infrastructure/keras/activation_quantizers/lsq/symmetric_lsq.py +127 -0
  14. model_compression_toolkit/trainable_infrastructure/keras/activation_quantizers/lsq/uniform_lsq.py +129 -0
  15. model_compression_toolkit/trainable_infrastructure/keras/activation_quantizers/ste/__init__.py +14 -0
  16. model_compression_toolkit/trainable_infrastructure/keras/activation_quantizers/ste/symmetric_ste.py +148 -0
  17. model_compression_toolkit/trainable_infrastructure/keras/activation_quantizers/ste/uniform_ste.py +122 -0
  18. model_compression_toolkit/trainable_infrastructure/keras/base_keras_quantizer.py +12 -10
  19. model_compression_toolkit/trainable_infrastructure/keras/quantizer_utils.py +60 -0
  20. {mct_nightly-2.2.0.20241012.448.dist-info → mct_nightly-2.2.0.20241018.449.dist-info}/LICENSE.md +0 -0
  21. {mct_nightly-2.2.0.20241012.448.dist-info → mct_nightly-2.2.0.20241018.449.dist-info}/WHEEL +0 -0
  22. {mct_nightly-2.2.0.20241012.448.dist-info → mct_nightly-2.2.0.20241018.449.dist-info}/top_level.txt +0 -0
@@ -16,28 +16,26 @@ import numpy as np
16
16
  import tensorflow as tf
17
17
  from tensorflow.python.framework.tensor_shape import TensorShape
18
18
  from model_compression_toolkit.constants import RANGE_MIN, RANGE_MAX
19
+ from model_compression_toolkit.qat.keras.quantizer.base_keras_qat_weight_quantizer import \
20
+ BaseKerasQATWeightTrainableQuantizer
19
21
  from model_compression_toolkit.trainable_infrastructure.common.constants import FQ_MIN, FQ_MAX
20
22
  from model_compression_toolkit.trainable_infrastructure import KerasTrainableQuantizationWrapper
21
23
  from model_compression_toolkit.trainable_infrastructure import TrainingMethod
22
24
 
23
25
  from mct_quantizers import mark_quantizer, QuantizationMethod, QuantizationTarget
24
- from mct_quantizers.keras.quantizers import \
25
- BaseKerasInferableQuantizer, WeightsUniformInferableQuantizer, ActivationUniformInferableQuantizer
26
+ from mct_quantizers.keras.quantizers import BaseKerasInferableQuantizer, WeightsUniformInferableQuantizer
26
27
 
27
28
  from model_compression_toolkit.qat.keras.quantizer.quant_utils import adjust_range_to_include_zero
28
29
  from model_compression_toolkit.core.common.quantization.quantizers.quantizers_helpers import fix_range_to_include_zero
29
- from model_compression_toolkit import constants as C
30
30
 
31
- from model_compression_toolkit.qat.keras.quantizer.base_keras_qat_quantizer import BaseKerasQATTrainableQuantizer
32
- from model_compression_toolkit.trainable_infrastructure import TrainableQuantizerWeightsConfig, \
33
- TrainableQuantizerActivationConfig
31
+ from model_compression_toolkit.trainable_infrastructure import TrainableQuantizerWeightsConfig
34
32
  from model_compression_toolkit.trainable_infrastructure.common.base_trainable_quantizer import VariableGroup
35
33
 
36
34
 
37
35
  @mark_quantizer(quantization_target=QuantizationTarget.Weights,
38
36
  quantization_method=[QuantizationMethod.UNIFORM],
39
37
  identifier=TrainingMethod.STE)
40
- class STEUniformWeightQATQuantizer(BaseKerasQATTrainableQuantizer):
38
+ class STEUniformWeightQATQuantizer(BaseKerasQATWeightTrainableQuantizer):
41
39
  """
42
40
  Trainable constrained quantizer to quantize a layer inputs.
43
41
  """
@@ -148,91 +146,3 @@ class STEUniformWeightQATQuantizer(BaseKerasQATTrainableQuantizer):
148
146
  input_rank=len(self.min_max_shape))
149
147
 
150
148
 
151
- @mark_quantizer(quantization_target=QuantizationTarget.Activation,
152
- quantization_method=[QuantizationMethod.UNIFORM],
153
- identifier=TrainingMethod.STE)
154
- class STEUniformActivationQATQuantizer(BaseKerasQATTrainableQuantizer):
155
- """
156
- Trainable constrained quantizer to quantize a layer outputs.
157
- """
158
-
159
- def __init__(self, quantization_config: TrainableQuantizerActivationConfig):
160
- """
161
- Initialize a STEUniformActivationQATQuantizer object with parameters to use
162
- for the quantization.
163
-
164
- Args:
165
- quantization_config: trainable quantizer config class
166
- """
167
- super().__init__(quantization_config)
168
-
169
- self.num_bits = quantization_config.activation_n_bits
170
- self.min_range = quantization_config.activation_quantization_params[C.RANGE_MIN]
171
- self.max_range = quantization_config.activation_quantization_params[C.RANGE_MAX]
172
-
173
- def initialize_quantization(self,
174
- tensor_shape: TensorShape,
175
- name: str,
176
- layer: KerasTrainableQuantizationWrapper):
177
- """
178
- Add quantizer parameters to the quantizer parameters dictionary
179
-
180
- Args:
181
- tensor_shape: tensor shape of the quantized tensor.
182
- name: Tensor name.
183
- layer: Layer to quantize.
184
- """
185
- fq_min = layer.add_weight(
186
- name + FQ_MIN,
187
- shape=(),
188
- initializer=tf.keras.initializers.Constant(-1.0),
189
- trainable=False)
190
- fq_min.assign(self.min_range)
191
-
192
- fq_max = layer.add_weight(
193
- name + FQ_MAX,
194
- shape=(),
195
- initializer=tf.keras.initializers.Constant(1.0),
196
- trainable=False)
197
- fq_max.assign(self.max_range)
198
-
199
- # save the quantizer added parameters for later calculations
200
- self.add_quantizer_variable(FQ_MIN, fq_min, VariableGroup.QPARAMS)
201
- self.add_quantizer_variable(FQ_MAX, fq_max, VariableGroup.QPARAMS)
202
-
203
- def __call__(self,
204
- inputs: tf.Tensor,
205
- training: bool):
206
- """
207
- Quantize a tensor.
208
- Args:
209
- inputs: Input tensor to quantize.
210
- training: Whether the graph is in training mode.
211
-
212
- Returns:
213
- The quantized tensor.
214
- """
215
-
216
- _min = self.get_quantizer_variable(FQ_MIN)
217
- _max = self.get_quantizer_variable(FQ_MAX)
218
- _min, _max = adjust_range_to_include_zero(_min, _max, self.num_bits)
219
- q_tensor = tf.quantization.fake_quant_with_min_max_vars(inputs, _min, _max,
220
- num_bits=self.num_bits)
221
-
222
- return q_tensor
223
-
224
- def convert2inferable(self) -> BaseKerasInferableQuantizer:
225
- """
226
- Convert quantizer to inferable quantizer.
227
-
228
- Returns:
229
- BaseKerasInferableQuantizer object.
230
- """
231
- min_range, max_range = fix_range_to_include_zero(self.get_quantizer_variable(FQ_MIN).numpy(),
232
- self.get_quantizer_variable(FQ_MAX).numpy(),
233
- self.num_bits)
234
- return ActivationUniformInferableQuantizer(num_bits=self.num_bits,
235
- # In activation quantization is per-tensor only - thus we pass
236
- # the min/max as lists with a len of 1
237
- min_range=[min_range],
238
- max_range=[max_range])
@@ -0,0 +1,20 @@
1
+ # Copyright 2024 Sony Semiconductor Israel, Inc. All rights reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ # ==============================================================================
15
+
16
+ from .base_activation_quantizer import BaseKerasActivationTrainableQuantizer
17
+ from .ste.symmetric_ste import STESymmetricActivationTrainableQuantizer
18
+ from .ste.uniform_ste import STEUniformActivationTrainableQuantizer
19
+ from .lsq.symmetric_lsq import LSQSymmetricActivationTrainableQuantizer
20
+ from .lsq.uniform_lsq import LSQUniformActivationTrainableQuantizer
@@ -0,0 +1,22 @@
1
+ # Copyright 2024 Sony Semiconductor Israel, Inc. All rights reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ # ==============================================================================
15
+ from abc import ABC
16
+
17
+ from model_compression_toolkit.trainable_infrastructure import BaseKerasTrainableQuantizer
18
+
19
+
20
+ class BaseKerasActivationTrainableQuantizer(BaseKerasTrainableQuantizer, ABC):
21
+ """ Base class for Keras trainable activation quantizers """
22
+ pass
@@ -0,0 +1,14 @@
1
+ # Copyright 2024 Sony Semiconductor Israel, Inc. All rights reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ # ==============================================================================
@@ -0,0 +1,127 @@
1
+ # Copyright 2024 Sony Semiconductor Israel, Inc. All rights reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ # ==============================================================================
15
+ from model_compression_toolkit.trainable_infrastructure.keras.quantizer_utils import symmetric_lsq_quantizer
16
+ from model_compression_toolkit.trainable_infrastructure.keras.activation_quantizers import BaseKerasActivationTrainableQuantizer
17
+ from typing import Union
18
+
19
+ import numpy as np
20
+ import tensorflow as tf
21
+ from tensorflow.python.framework.tensor_shape import TensorShape
22
+ from model_compression_toolkit.constants import SIGNED
23
+
24
+ from model_compression_toolkit.trainable_infrastructure import TrainingMethod
25
+
26
+ from model_compression_toolkit.target_platform_capabilities.target_platform import QuantizationMethod
27
+ from model_compression_toolkit.trainable_infrastructure import KerasTrainableQuantizationWrapper
28
+ from mct_quantizers import QuantizationTarget, mark_quantizer
29
+ from model_compression_toolkit.qat.common import THRESHOLD_TENSOR
30
+ from model_compression_toolkit import constants as C
31
+
32
+ from model_compression_toolkit.trainable_infrastructure import TrainableQuantizerActivationConfig
33
+ from mct_quantizers.keras.quantizers import ActivationPOTInferableQuantizer, ActivationSymmetricInferableQuantizer
34
+ from model_compression_toolkit.trainable_infrastructure.common.base_trainable_quantizer import VariableGroup
35
+
36
+ @mark_quantizer(quantization_target=QuantizationTarget.Activation,
37
+ quantization_method=[QuantizationMethod.POWER_OF_TWO, QuantizationMethod.SYMMETRIC],
38
+ identifier=TrainingMethod.LSQ)
39
+ class LSQSymmetricActivationTrainableQuantizer(BaseKerasActivationTrainableQuantizer):
40
+ """
41
+ Trainable constrained quantizer to quantize layer activations.
42
+ """
43
+
44
+ def __init__(self, quantization_config: TrainableQuantizerActivationConfig):
45
+ """
46
+ Initialize a LSQActivationQATQuantizer object with parameters to use
47
+ for the quantization.
48
+
49
+ Args:
50
+ quantization_config: trainable quantizer config class
51
+ """
52
+ super().__init__(quantization_config)
53
+ self.power_of_two = quantization_config.activation_quantization_method == QuantizationMethod.POWER_OF_TWO
54
+ self.threshold_values = float(quantization_config.activation_quantization_params[C.THRESHOLD])
55
+ self.threshold_shape = np.asarray(self.threshold_values).shape
56
+ self.sign = quantization_config.activation_quantization_params[SIGNED]
57
+ self.num_bits = quantization_config.activation_n_bits
58
+ n_pos_bits = self.num_bits - int(self.sign)
59
+ self.min_int = -int(self.sign) * (2 ** n_pos_bits)
60
+ self.max_int = (2 ** n_pos_bits) - 1
61
+ if self.power_of_two:
62
+ self.threshold_values = np.power(2.0, np.ceil(np.log2(np.maximum(self.threshold_values, C.MIN_THRESHOLD))))
63
+
64
+
65
+ def initialize_quantization(self,
66
+ tensor_shape: TensorShape,
67
+ name: str,
68
+ layer: KerasTrainableQuantizationWrapper):
69
+ """
70
+ Add quantizer parameters to the quantizer parameters dictionary
71
+
72
+ Args:
73
+ tensor_shape: tensor shape of the quantized tensor.
74
+ name: Tensor name.
75
+ layer: Layer to quantize.
76
+ """
77
+ ptq_threshold_tensor = layer.add_weight(
78
+ name + THRESHOLD_TENSOR,
79
+ shape=(),
80
+ initializer=tf.keras.initializers.Constant(1.0),
81
+ trainable=True)
82
+ ptq_threshold_tensor.assign(self.threshold_values)
83
+
84
+ # save the quantizer added parameters for later calculations
85
+ self.add_quantizer_variable(THRESHOLD_TENSOR, ptq_threshold_tensor, VariableGroup.QPARAMS)
86
+
87
+ def __call__(self,
88
+ inputs: tf.Tensor,
89
+ training: bool):
90
+ """
91
+ Quantize a tensor.
92
+ Args:
93
+ inputs: Input tensor to quantize.
94
+ training: Whether the graph is in training mode.
95
+
96
+ Returns:
97
+ The quantized tensor.
98
+ """
99
+
100
+ thresholds = self.get_quantizer_variable(THRESHOLD_TENSOR)
101
+ n_channels = inputs.shape[-1]
102
+ scale_factor = 1.0 / np.sqrt(self.max_int * n_channels)
103
+ q_tensor = symmetric_lsq_quantizer(inputs, thresholds, self.num_bits, self.sign, self.min_int, self.max_int, scale_factor)
104
+ return q_tensor
105
+
106
+ def convert2inferable(self) -> Union[ActivationPOTInferableQuantizer, ActivationSymmetricInferableQuantizer]:
107
+ """
108
+ Convert quantizer to inferable quantizer.
109
+
110
+ Returns:
111
+ BaseKerasInferableQuantizer object.
112
+ """
113
+
114
+ if self.power_of_two:
115
+ thresholds = 2 ** np.ceil(np.log2(self.get_quantizer_variable(THRESHOLD_TENSOR).numpy()))
116
+ return ActivationPOTInferableQuantizer(num_bits=self.num_bits,
117
+ # In activation quantization is per-tensor only - thus we pass
118
+ # the threshold as a list with a len of 1
119
+ threshold=[thresholds],
120
+ signed=self.sign)
121
+ else:
122
+ thresholds = self.get_quantizer_variable(THRESHOLD_TENSOR).numpy()
123
+ return ActivationSymmetricInferableQuantizer(num_bits=self.num_bits,
124
+ # In activation quantization is per-tensor only - thus we
125
+ # pass the threshold as a list with a len of 1
126
+ threshold=[thresholds],
127
+ signed=self.sign)
@@ -0,0 +1,129 @@
1
+ # Copyright 2024 Sony Semiconductor Israel, Inc. All rights reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ # ==============================================================================
15
+
16
+ import numpy as np
17
+ import tensorflow as tf
18
+ from tensorflow.python.framework.tensor_shape import TensorShape
19
+ from model_compression_toolkit.constants import RANGE_MIN, RANGE_MAX
20
+ from model_compression_toolkit.trainable_infrastructure.keras.quantizer_utils import uniform_lsq_quantizer
21
+ from model_compression_toolkit.trainable_infrastructure.common.constants import FQ_MIN, FQ_MAX
22
+ from model_compression_toolkit.trainable_infrastructure import KerasTrainableQuantizationWrapper
23
+ from model_compression_toolkit.trainable_infrastructure import TrainingMethod
24
+
25
+ from mct_quantizers import mark_quantizer, QuantizationMethod, QuantizationTarget
26
+ from mct_quantizers.keras.quantizers import \
27
+ BaseKerasInferableQuantizer, WeightsUniformInferableQuantizer, ActivationUniformInferableQuantizer
28
+
29
+ from model_compression_toolkit import constants as C
30
+
31
+ from model_compression_toolkit.trainable_infrastructure import TrainableQuantizerWeightsConfig, \
32
+ TrainableQuantizerActivationConfig
33
+ from model_compression_toolkit.trainable_infrastructure.common.base_trainable_quantizer import VariableGroup
34
+ from model_compression_toolkit.core.common.quantization.quantizers.quantizers_helpers import fix_range_to_include_zero
35
+ from model_compression_toolkit.trainable_infrastructure.keras.activation_quantizers import \
36
+ BaseKerasActivationTrainableQuantizer
37
+
38
+
39
+ @mark_quantizer(quantization_target=QuantizationTarget.Activation,
40
+ quantization_method=[QuantizationMethod.UNIFORM],
41
+ identifier=TrainingMethod.LSQ)
42
+ class LSQUniformActivationTrainableQuantizer(BaseKerasActivationTrainableQuantizer):
43
+ """
44
+ Trainable constrained quantizer to quantize layer activations.
45
+ """
46
+
47
+ def __init__(self, quantization_config: TrainableQuantizerActivationConfig):
48
+ """
49
+ Initialize a LSQUniformActivationQATQuantizer object with parameters to use
50
+ for the quantization.
51
+
52
+ Args:
53
+ quantization_config: trainable quantizer config class
54
+ """
55
+ super().__init__(quantization_config)
56
+
57
+ self.num_bits = quantization_config.activation_n_bits
58
+ self.min_range = np.array(quantization_config.activation_quantization_params[C.RANGE_MIN])
59
+ self.max_range = np.array(quantization_config.activation_quantization_params[C.RANGE_MAX])
60
+ self.min_int = 0
61
+ self.max_int = 2**self.num_bits - 1
62
+
63
+ def initialize_quantization(self,
64
+ tensor_shape: TensorShape,
65
+ name: str,
66
+ layer: KerasTrainableQuantizationWrapper):
67
+ """
68
+ Add quantizer parameters to the quantizer parameters dictionary
69
+
70
+ Args:
71
+ tensor_shape: tensor shape of the quantized tensor.
72
+ name: Tensor name.
73
+ layer: Layer to quantize.
74
+ """
75
+ fq_min = layer.add_weight(
76
+ name + FQ_MIN,
77
+ shape=(),
78
+ initializer=tf.keras.initializers.Constant(-1.0),
79
+ trainable=True)
80
+ fq_min.assign(self.min_range)
81
+
82
+ fq_max = layer.add_weight(
83
+ name + FQ_MAX,
84
+ shape=(),
85
+ initializer=tf.keras.initializers.Constant(1.0),
86
+ trainable=True)
87
+ fq_max.assign(self.max_range)
88
+
89
+ # save the quantizer added parameters for later calculations
90
+ self.add_quantizer_variable(FQ_MIN, fq_min, VariableGroup.QPARAMS)
91
+ self.add_quantizer_variable(FQ_MAX, fq_max, VariableGroup.QPARAMS)
92
+
93
+ def __call__(self,
94
+ inputs: tf.Tensor,
95
+ training: bool):
96
+ """
97
+ Quantize a tensor.
98
+ Args:
99
+ inputs: Input tensor to quantize.
100
+ training: Whether the graph is in training mode.
101
+
102
+ Returns:
103
+ The quantized tensor.
104
+ """
105
+
106
+ min_range = self.get_quantizer_variable(FQ_MIN)
107
+ max_range = self.get_quantizer_variable(FQ_MAX)
108
+ n_channels = inputs.shape[-1]
109
+ scale_factor = 1.0 / np.sqrt(self.max_int * n_channels)
110
+ q_tensor = uniform_lsq_quantizer(inputs, min_range, max_range, self.num_bits, self.min_int, self.max_int, scale_factor)
111
+ return q_tensor
112
+
113
+ def convert2inferable(self) -> BaseKerasInferableQuantizer:
114
+ """
115
+ Convert quantizer to inferable quantizer.
116
+
117
+ Returns:
118
+ BaseKerasInferableQuantizer object.
119
+ """
120
+ min_range, max_range = fix_range_to_include_zero(self.get_quantizer_variable(FQ_MIN).numpy(),
121
+ self.get_quantizer_variable(FQ_MAX).numpy(),
122
+ self.num_bits)
123
+ return ActivationUniformInferableQuantizer(num_bits=self.num_bits,
124
+ # In activation quantization is per-tensor only - thus we pass
125
+ # the min/max as lists with a len of 1
126
+ min_range=[min_range],
127
+ max_range=[max_range])
128
+
129
+
@@ -0,0 +1,14 @@
1
+ # Copyright 2024 Sony Semiconductor Israel, Inc. All rights reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ # ==============================================================================
@@ -0,0 +1,148 @@
1
+ # Copyright 2024 Sony Semiconductor Israel, Inc. All rights reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ # ==============================================================================
15
+ from typing import Union
16
+
17
+ import numpy as np
18
+ import tensorflow as tf
19
+
20
+ from mct_quantizers import mark_quantizer, QuantizationTarget, QuantizationMethod
21
+ from mct_quantizers.keras.quantizers import ActivationPOTInferableQuantizer, ActivationSymmetricInferableQuantizer
22
+ from model_compression_toolkit import constants as C
23
+ from model_compression_toolkit.trainable_infrastructure import TrainingMethod, TrainableQuantizerActivationConfig
24
+ from model_compression_toolkit.trainable_infrastructure.common.base_trainable_quantizer import VariableGroup
25
+ from model_compression_toolkit.trainable_infrastructure.common.constants import THRESHOLD_TENSOR
26
+ from model_compression_toolkit.trainable_infrastructure.keras.activation_quantizers import BaseKerasActivationTrainableQuantizer
27
+ from model_compression_toolkit.constants import SIGNED
28
+ from tensorflow.python.framework.tensor_shape import TensorShape
29
+ from model_compression_toolkit.trainable_infrastructure import KerasTrainableQuantizationWrapper
30
+ from model_compression_toolkit.trainable_infrastructure.common.constants import FQ_MIN, FQ_MAX
31
+
32
+
33
+ # moved (and renamed) from model_compression_toolkit/qat/keras/quantizer/ste_rounding/symmetric_ste.py
34
+ @mark_quantizer(quantization_target=QuantizationTarget.Activation,
35
+ quantization_method=[QuantizationMethod.POWER_OF_TWO, QuantizationMethod.SYMMETRIC],
36
+ identifier=TrainingMethod.STE)
37
+ class STESymmetricActivationTrainableQuantizer(BaseKerasActivationTrainableQuantizer):
38
+
39
+ """
40
+ Trainable constrained quantizer to quantize a layer outputs.
41
+ """
42
+
43
+ def __init__(self, quantization_config: TrainableQuantizerActivationConfig, freeze_quant_params: bool = False):
44
+ """
45
+ Initialize a STESymmetricActivationTrainableQuantizer object with parameters to use
46
+ for the quantization.
47
+
48
+ Args:
49
+ quantization_config: trainable quantizer config class
50
+ freeze_quant_params: whether to freeze learnable quantization parameters. This is unused here, since there is not any quantizaiton params that are learned.
51
+ """
52
+ super().__init__(quantization_config, freeze_quant_params)
53
+ self.power_of_two = quantization_config.activation_quantization_method == QuantizationMethod.POWER_OF_TWO
54
+ self.threshold_values = quantization_config.activation_quantization_params[C.THRESHOLD]
55
+ self.threshold_shape = np.asarray(self.threshold_values).shape
56
+ self.np_threshold_values = float(self.threshold_values)
57
+ self.signed = quantization_config.activation_quantization_params[SIGNED]
58
+ if self.power_of_two:
59
+ self.np_threshold_values = np.power(2.0,
60
+ np.ceil(
61
+ np.log2(np.maximum(self.np_threshold_values, C.MIN_THRESHOLD))))
62
+ self.num_bits = quantization_config.activation_n_bits
63
+ delta = self.np_threshold_values / np.power(2.0, self.num_bits - int(self.signed))
64
+ min_int = -int(self.signed) * (2 ** (self.num_bits - int(self.signed)))
65
+ max_int = (2 ** (self.num_bits - int(self.signed))) - 1
66
+ self.min = delta * min_int
67
+ self.max = delta * max_int
68
+
69
+ def initialize_quantization(self,
70
+ tensor_shape: TensorShape,
71
+ name: str,
72
+ layer: KerasTrainableQuantizationWrapper):
73
+ """
74
+ Add quantizer parameters to the quantizer parameters dictionary
75
+
76
+ Args:
77
+ tensor_shape: tensor shape of the quantized tensor.
78
+ name: Tensor name.
79
+ layer: Layer to quantize.
80
+ """
81
+ ptq_threshold_tensor = layer.add_weight(
82
+ name + THRESHOLD_TENSOR,
83
+ shape=(),
84
+ initializer=tf.keras.initializers.Constant(1.0),
85
+ trainable=False)
86
+ ptq_threshold_tensor.assign(self.np_threshold_values)
87
+
88
+ fq_min = layer.add_weight(
89
+ name + FQ_MIN,
90
+ shape=(),
91
+ initializer=tf.keras.initializers.Constant(-1.0),
92
+ trainable=False)
93
+ fq_min.assign(self.min)
94
+
95
+ fq_max = layer.add_weight(
96
+ name + FQ_MAX,
97
+ shape=(),
98
+ initializer=tf.keras.initializers.Constant(1.0),
99
+ trainable=False)
100
+ fq_max.assign(self.max)
101
+
102
+ # save the quantizer added parameters for later calculations
103
+ self.add_quantizer_variable(THRESHOLD_TENSOR, ptq_threshold_tensor, VariableGroup.QPARAMS)
104
+ self.add_quantizer_variable(FQ_MIN, fq_min, VariableGroup.QPARAMS)
105
+ self.add_quantizer_variable(FQ_MAX, fq_max, VariableGroup.QPARAMS)
106
+
107
+ def __call__(self,
108
+ inputs: tf.Tensor,
109
+ training: bool):
110
+ """
111
+ Quantize a tensor.
112
+ Args:
113
+ inputs: Input tensor to quantize.
114
+ training: Whether the graph is in training mode.
115
+
116
+ Returns:
117
+ The quantized tensor.
118
+ """
119
+
120
+ _min = self.get_quantizer_variable(FQ_MIN)
121
+ _max = self.get_quantizer_variable(FQ_MAX)
122
+ q_tensor = tf.quantization.fake_quant_with_min_max_vars(inputs, _min, _max,
123
+ num_bits=self.num_bits)
124
+
125
+ return q_tensor
126
+
127
+ def convert2inferable(self) -> Union[ActivationPOTInferableQuantizer, ActivationSymmetricInferableQuantizer]:
128
+ """
129
+ Convert quantizer to inferable quantizer.
130
+
131
+ Returns:
132
+ BaseKerasInferableQuantizer object.
133
+ """
134
+
135
+ if self.power_of_two:
136
+ pot_threshold = 2 ** np.ceil(np.log2(self.get_quantizer_variable(THRESHOLD_TENSOR)))
137
+ return ActivationPOTInferableQuantizer(num_bits=self.num_bits,
138
+ # In activation quantization is per-tensor only - thus we pass
139
+ # the threshold as a list with a len of 1
140
+ threshold=[pot_threshold],
141
+ signed=self.signed)
142
+ else:
143
+ return ActivationSymmetricInferableQuantizer(num_bits=self.num_bits,
144
+ # In activation quantization is per-tensor only - thus we
145
+ # pass the threshold as a list with a len of 1
146
+ threshold=[
147
+ self.get_quantizer_variable(THRESHOLD_TENSOR).numpy()],
148
+ signed=self.signed)