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.
- {mct_nightly-2.2.0.20241012.448.dist-info → mct_nightly-2.2.0.20241018.449.dist-info}/METADATA +1 -1
- {mct_nightly-2.2.0.20241012.448.dist-info → mct_nightly-2.2.0.20241018.449.dist-info}/RECORD +22 -14
- model_compression_toolkit/__init__.py +1 -1
- model_compression_toolkit/qat/keras/quantizer/{base_keras_qat_quantizer.py → base_keras_qat_weight_quantizer.py} +3 -13
- model_compression_toolkit/qat/keras/quantizer/lsq/symmetric_lsq.py +5 -126
- model_compression_toolkit/qat/keras/quantizer/lsq/uniform_lsq.py +4 -121
- model_compression_toolkit/qat/keras/quantizer/quantization_builder.py +7 -6
- model_compression_toolkit/qat/keras/quantizer/ste_rounding/symmetric_ste.py +4 -119
- model_compression_toolkit/qat/keras/quantizer/ste_rounding/uniform_ste.py +5 -95
- model_compression_toolkit/trainable_infrastructure/keras/activation_quantizers/__init__.py +20 -0
- model_compression_toolkit/trainable_infrastructure/keras/activation_quantizers/base_activation_quantizer.py +22 -0
- model_compression_toolkit/trainable_infrastructure/keras/activation_quantizers/lsq/__init__.py +14 -0
- model_compression_toolkit/trainable_infrastructure/keras/activation_quantizers/lsq/symmetric_lsq.py +127 -0
- model_compression_toolkit/trainable_infrastructure/keras/activation_quantizers/lsq/uniform_lsq.py +129 -0
- model_compression_toolkit/trainable_infrastructure/keras/activation_quantizers/ste/__init__.py +14 -0
- model_compression_toolkit/trainable_infrastructure/keras/activation_quantizers/ste/symmetric_ste.py +148 -0
- model_compression_toolkit/trainable_infrastructure/keras/activation_quantizers/ste/uniform_ste.py +122 -0
- model_compression_toolkit/trainable_infrastructure/keras/base_keras_quantizer.py +12 -10
- model_compression_toolkit/trainable_infrastructure/keras/quantizer_utils.py +60 -0
- {mct_nightly-2.2.0.20241012.448.dist-info → mct_nightly-2.2.0.20241018.449.dist-info}/LICENSE.md +0 -0
- {mct_nightly-2.2.0.20241012.448.dist-info → mct_nightly-2.2.0.20241018.449.dist-info}/WHEEL +0 -0
- {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.
|
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(
|
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
|
model_compression_toolkit/trainable_infrastructure/keras/activation_quantizers/lsq/__init__.py
ADDED
@@ -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
|
+
# ==============================================================================
|
model_compression_toolkit/trainable_infrastructure/keras/activation_quantizers/lsq/symmetric_lsq.py
ADDED
@@ -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)
|
model_compression_toolkit/trainable_infrastructure/keras/activation_quantizers/lsq/uniform_lsq.py
ADDED
@@ -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
|
+
|
model_compression_toolkit/trainable_infrastructure/keras/activation_quantizers/ste/__init__.py
ADDED
@@ -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
|
+
# ==============================================================================
|
model_compression_toolkit/trainable_infrastructure/keras/activation_quantizers/ste/symmetric_ste.py
ADDED
@@ -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)
|