ai-edge-quantizer-nightly 0.1.0.dev20250519__py3-none-any.whl → 0.1.0.dev20250521__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.
- ai_edge_quantizer/algorithms/uniform_quantize/hadamard_rotation.py +17 -15
- ai_edge_quantizer/algorithms/uniform_quantize/hadamard_rotation_test.py +32 -2
- {ai_edge_quantizer_nightly-0.1.0.dev20250519.dist-info → ai_edge_quantizer_nightly-0.1.0.dev20250521.dist-info}/METADATA +1 -1
- {ai_edge_quantizer_nightly-0.1.0.dev20250519.dist-info → ai_edge_quantizer_nightly-0.1.0.dev20250521.dist-info}/RECORD +7 -7
- {ai_edge_quantizer_nightly-0.1.0.dev20250519.dist-info → ai_edge_quantizer_nightly-0.1.0.dev20250521.dist-info}/LICENSE +0 -0
- {ai_edge_quantizer_nightly-0.1.0.dev20250519.dist-info → ai_edge_quantizer_nightly-0.1.0.dev20250521.dist-info}/WHEEL +0 -0
- {ai_edge_quantizer_nightly-0.1.0.dev20250519.dist-info → ai_edge_quantizer_nightly-0.1.0.dev20250521.dist-info}/top_level.txt +0 -0
@@ -58,19 +58,19 @@ def _rotate_with_diagonal_hadamard(
|
|
58
58
|
|
59
59
|
Args:
|
60
60
|
tensor_content: The float array to quantize.
|
61
|
-
axis: The axis of the tensor to
|
61
|
+
axis: The axis of the tensor to rotate.
|
62
62
|
|
63
63
|
Returns:
|
64
64
|
A tuple containing the quantized array and the recovered array.
|
65
65
|
|
66
66
|
Raises:
|
67
|
-
ValueError: If the axis is not
|
68
|
-
support to the matrix multiplication.
|
67
|
+
ValueError: If the axis is not the last axis of tensor_content. To support
|
68
|
+
other axes, please add support to the matrix multiplication.
|
69
69
|
"""
|
70
|
-
if axis != 1:
|
70
|
+
if axis != tensor_content.ndim - 1:
|
71
71
|
raise ValueError(
|
72
|
-
"Hadamard rotation is only supported for
|
73
|
-
" dimension 0."
|
72
|
+
"Hadamard rotation is only supported for tensors with quantized"
|
73
|
+
" dimension 0 (rotate last dimension)."
|
74
74
|
)
|
75
75
|
|
76
76
|
# Use the largest power of 2 that is a factor of the dimension and then
|
@@ -78,15 +78,15 @@ def _rotate_with_diagonal_hadamard(
|
|
78
78
|
# of 2 to calculate this factor.
|
79
79
|
hadamard_size = np.gcd(tensor_content.shape[axis], 2 ** 30)
|
80
80
|
diagonal_size = tensor_content.shape[axis] // hadamard_size
|
81
|
-
|
81
|
+
# Output size is the product of all dimensions except the one being rotated.
|
82
|
+
output_size = np.prod(np.delete(tensor_content.shape, axis))
|
82
83
|
random_vector = np.ones(hadamard_size, dtype=np.int8)
|
83
84
|
|
84
85
|
# Use a canonical Hadamard matrix.
|
85
86
|
hadamard = _make_hadamard_matrix(hadamard_size)
|
86
87
|
reshaped_tensor = tensor_content.reshape(
|
87
|
-
diagonal_size
|
88
|
-
)
|
89
|
-
w_rotated = np.einsum("jk,ilk->ilj", hadamard, reshaped_tensor)
|
88
|
+
diagonal_size * output_size, hadamard_size)
|
89
|
+
w_rotated = np.matmul(hadamard, reshaped_tensor.mT).mT
|
90
90
|
return w_rotated.reshape(tensor_content.shape), hadamard_size, random_vector
|
91
91
|
|
92
92
|
|
@@ -122,8 +122,10 @@ def get_tensor_quant_params(
|
|
122
122
|
"Hadamard rotation is not supported for static quantization."
|
123
123
|
)
|
124
124
|
|
125
|
-
if tensor_content.ndim
|
126
|
-
raise ValueError(
|
125
|
+
if tensor_content.ndim < 2:
|
126
|
+
raise ValueError(
|
127
|
+
"Hadamard rotation is only supported for tensors with rank >= 2."
|
128
|
+
)
|
127
129
|
|
128
130
|
if tensor_quant_config.granularity != qtyping.QuantGranularity.CHANNELWISE:
|
129
131
|
raise ValueError(
|
@@ -140,9 +142,9 @@ def get_tensor_quant_params(
|
|
140
142
|
" supported."
|
141
143
|
)
|
142
144
|
|
143
|
-
# Reduction axis is the non-quantized dimension. Since we only support
|
144
|
-
#
|
145
|
-
reduce_axis = 1
|
145
|
+
# Reduction axis is the last non-quantized dimension. Since we only support
|
146
|
+
# quantized_dim of 0, the reduction axis is the last axis.
|
147
|
+
reduce_axis = tensor_content.ndim - 1
|
146
148
|
|
147
149
|
# Rotate the tensor with a Hadamard matrix.
|
148
150
|
w_rotated, hadamard_size, random_vector = _rotate_with_diagonal_hadamard(
|
@@ -168,6 +168,36 @@ class HadamardRotationFullyConnectedTest(parameterized.TestCase):
|
|
168
168
|
np.array(qparams.quantized_data), expected
|
169
169
|
)
|
170
170
|
|
171
|
+
def test_get_tensor_quant_params_golden_3(self):
|
172
|
+
# test_data:
|
173
|
+
# [[[1 2 1 2 1 2]
|
174
|
+
# [3 4 3 4 3 4]
|
175
|
+
# [1 2 1 2 1 2]]
|
176
|
+
# [[3 4 3 4 3 4]
|
177
|
+
# [1 2 1 2 1 2]
|
178
|
+
# [3 4 3 4 3 4]]]
|
179
|
+
test_data = np.tile([[1, 2], [3, 4]], [3, 3])
|
180
|
+
test_data = np.reshape(test_data, (2, 3, 6))
|
181
|
+
# expected:
|
182
|
+
# [[[ 54 -18 54 -18 54 -18]
|
183
|
+
# [127 -18 127 -18 127 -18]
|
184
|
+
# [ 54 -18 54 -18 54 -18]]
|
185
|
+
# [[127 -18 127 -18 127 -18]
|
186
|
+
# [ 54 -18 54 -18 54 -18]
|
187
|
+
# [127 -18 127 -18 127 -18]]]
|
188
|
+
expected = np.tile([[54, -18], [127, -18]], [3, 3])
|
189
|
+
expected = np.reshape(expected, (2, 3, 6))
|
190
|
+
qparams = hadamard_rotation.get_tensor_quant_params(
|
191
|
+
self._op_info,
|
192
|
+
self._op_info.op_quant_config.weight_tensor_config,
|
193
|
+
test_data,
|
194
|
+
self._tensor_name_to_qsv,
|
195
|
+
)
|
196
|
+
self.assertIsNotNone(qparams.quantized_data)
|
197
|
+
np.testing.assert_array_equal(
|
198
|
+
np.array(qparams.quantized_data), expected
|
199
|
+
)
|
200
|
+
|
171
201
|
def test_raise_missing_tensor_content(self):
|
172
202
|
with self.assertRaisesWithPredicateMatch(
|
173
203
|
ValueError, lambda err: "weight tensor" in str(err)
|
@@ -190,9 +220,9 @@ class HadamardRotationFullyConnectedTest(parameterized.TestCase):
|
|
190
220
|
self._graph_info.buffers[self._fc_buffer_id],
|
191
221
|
)
|
192
222
|
|
193
|
-
def
|
223
|
+
def test_raise_1d_constant(self):
|
194
224
|
with self.assertRaisesWithPredicateMatch(
|
195
|
-
ValueError, lambda err: "
|
225
|
+
ValueError, lambda err: "rank >= 2" in str(err)
|
196
226
|
):
|
197
227
|
hadamard_rotation.get_tensor_quant_params(
|
198
228
|
self._op_info,
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: ai-edge-quantizer-nightly
|
3
|
-
Version: 0.1.0.
|
3
|
+
Version: 0.1.0.dev20250521
|
4
4
|
Summary: A quantizer for advanced developers to quantize converted AI Edge models.
|
5
5
|
Home-page: https://github.com/google-ai-edge/ai-edge-quantizer
|
6
6
|
Keywords: On-Device ML,AI,Google,TFLite,Quantization,LLMs,GenAI
|
@@ -32,8 +32,8 @@ ai_edge_quantizer/algorithms/uniform_quantize/common_quantize.py,sha256=NpZ-JvZt
|
|
32
32
|
ai_edge_quantizer/algorithms/uniform_quantize/common_quantize_test.py,sha256=GGf_n3wIeg3GB_eGsmyNJ0fTcxgpeMMbugTMRONK6TQ,3553
|
33
33
|
ai_edge_quantizer/algorithms/uniform_quantize/dequantized_weight_recovery.py,sha256=BDdn_uBZakfHyzdMJPKadsOqxqyC-s6W2ZzFH99L4fE,8652
|
34
34
|
ai_edge_quantizer/algorithms/uniform_quantize/dequantized_weight_recovery_test.py,sha256=sT5eX5TLZEHTtPfnSkCPDlS0sQxlTFWbCsbvOuj--yY,8889
|
35
|
-
ai_edge_quantizer/algorithms/uniform_quantize/hadamard_rotation.py,sha256=
|
36
|
-
ai_edge_quantizer/algorithms/uniform_quantize/hadamard_rotation_test.py,sha256=
|
35
|
+
ai_edge_quantizer/algorithms/uniform_quantize/hadamard_rotation.py,sha256=U3h5scCHSOdqHA-pb1C3pNgwumT4ydGbtkCSM0ORhrs,12740
|
36
|
+
ai_edge_quantizer/algorithms/uniform_quantize/hadamard_rotation_test.py,sha256=5VUxlaKP1jz4HV-LcKxXMMtmb6eWamq0A6qWJd63cR4,10179
|
37
37
|
ai_edge_quantizer/algorithms/uniform_quantize/naive_min_max_quantize.py,sha256=8_tNLTbOWTKId4DfHBjkOR9RvELUyIpxlGxKu7tv5Ko,7556
|
38
38
|
ai_edge_quantizer/algorithms/uniform_quantize/naive_min_max_quantize_test.py,sha256=zoF_EHjYqsKkuev8wfuutIITEmp_maa70IpJI_Df3ck,7431
|
39
39
|
ai_edge_quantizer/algorithms/uniform_quantize/octav.py,sha256=Umxh4kJyeHddZf-Wd4aXE5MTI1XWFa5KRuM17uYU714,6922
|
@@ -70,8 +70,8 @@ ai_edge_quantizer/utils/tfl_interpreter_utils.py,sha256=WoewyiZpaua80oP0tpgyrw5W
|
|
70
70
|
ai_edge_quantizer/utils/tfl_interpreter_utils_test.py,sha256=6fjkM-rycZ95L4yfvlr0TN6RlrhfPzxNUYrZaYO_F0A,12013
|
71
71
|
ai_edge_quantizer/utils/validation_utils.py,sha256=oYw33Sg547AqtGw-choPUJmp9SAKkV46J_ddqSsum2Q,3950
|
72
72
|
ai_edge_quantizer/utils/validation_utils_test.py,sha256=V_qNDikPD4OPB-siOLQCWNVWTAu87h2IgNYt7teFd-o,2934
|
73
|
-
ai_edge_quantizer_nightly-0.1.0.
|
74
|
-
ai_edge_quantizer_nightly-0.1.0.
|
75
|
-
ai_edge_quantizer_nightly-0.1.0.
|
76
|
-
ai_edge_quantizer_nightly-0.1.0.
|
77
|
-
ai_edge_quantizer_nightly-0.1.0.
|
73
|
+
ai_edge_quantizer_nightly-0.1.0.dev20250521.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
74
|
+
ai_edge_quantizer_nightly-0.1.0.dev20250521.dist-info/METADATA,sha256=RBpATRDheE6-5ohVAasX_rrpKfQiRhFWu2aEsc4bsJg,1528
|
75
|
+
ai_edge_quantizer_nightly-0.1.0.dev20250521.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
|
76
|
+
ai_edge_quantizer_nightly-0.1.0.dev20250521.dist-info/top_level.txt,sha256=8QTfPnFXNVUhScFLaa-NWZMFWMn72M50DVPubpwWB1g,18
|
77
|
+
ai_edge_quantizer_nightly-0.1.0.dev20250521.dist-info/RECORD,,
|
File without changes
|
File without changes
|