mct-nightly 2.3.0.20250331.610__py3-none-any.whl → 2.3.0.20250401.618__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mct-nightly
3
- Version: 2.3.0.20250331.610
3
+ Version: 2.3.0.20250401.618
4
4
  Summary: A Model Compression Toolkit for neural networks
5
5
  Classifier: Programming Language :: Python :: 3
6
6
  Classifier: License :: OSI Approved :: Apache Software License
@@ -1,5 +1,5 @@
1
- mct_nightly-2.3.0.20250331.610.dist-info/licenses/LICENSE.md,sha256=aYSSIb-5AFPeITTvXm1UAoe0uYBiMmSS8flvXaaFUks,10174
2
- model_compression_toolkit/__init__.py,sha256=tulTPjSjSee0ySdxccC46EZ_AbQkEIr3RvtUps-6IME,1557
1
+ mct_nightly-2.3.0.20250401.618.dist-info/licenses/LICENSE.md,sha256=aYSSIb-5AFPeITTvXm1UAoe0uYBiMmSS8flvXaaFUks,10174
2
+ model_compression_toolkit/__init__.py,sha256=sgIxUWX9jDSvUZnwMqs3nHNjXfhgFSfniDDr2vvRTuQ,1557
3
3
  model_compression_toolkit/constants.py,sha256=2ltuH-gdaLZoZV4CPUgKjC3S9ojz2z4OTVdenyVEypU,3912
4
4
  model_compression_toolkit/defaultdict.py,sha256=LSc-sbZYXENMCw3U9F4GiXuv67IKpdn0Qm7Fr11jy-4,2277
5
5
  model_compression_toolkit/logger.py,sha256=L3q7tn3Uht0i_7phnlOWMR2Te2zvzrt2HOz9vYEInts,4529
@@ -34,8 +34,8 @@ model_compression_toolkit/core/common/fusion/__init__.py,sha256=Rf1RcYmelmdZmBV5
34
34
  model_compression_toolkit/core/common/fusion/graph_fuser.py,sha256=b41_4rL_Adiza4vpWlmmqgvkpUmWVdfdx0nEIB0p2n8,6195
35
35
  model_compression_toolkit/core/common/fusion/layer_fusing.py,sha256=-2fnjyC9q2RPw9st6RxROW-gdtT2mSRz0QZ_Gz1KDz4,5579
36
36
  model_compression_toolkit/core/common/graph/__init__.py,sha256=Xr-Lt_qXMdrCnnOaUS_OJP_3iTTGfPCLf8_vSrQgCs0,773
37
- model_compression_toolkit/core/common/graph/base_graph.py,sha256=VhniLTiMqL7i1Vqg2UBQuFFTvw2cYeJayssUJwabp3E,38112
38
- model_compression_toolkit/core/common/graph/base_node.py,sha256=kZbmAMh5cPAwYzlY8KYa8w0ipL58yApB09-WXQ8plrE,33763
37
+ model_compression_toolkit/core/common/graph/base_graph.py,sha256=cSwHUqwZEiR1t2DaBfc7_qSJbtX8crpqerN4ol9v3H8,38859
38
+ model_compression_toolkit/core/common/graph/base_node.py,sha256=CJu8_r80MGVnYmlAUGOGKGRsD9xShMyaRNb3VMeRC0s,34523
39
39
  model_compression_toolkit/core/common/graph/edge.py,sha256=buoSEUZwilWBK3WeBKpJ-GeDaUA1SDdOHxDpxU_bGpk,3784
40
40
  model_compression_toolkit/core/common/graph/functional_node.py,sha256=GH5wStmw8SoAj5IdT_-ItN1Meo_P5NUTt_5bgJC4fak,3935
41
41
  model_compression_toolkit/core/common/graph/graph_matchers.py,sha256=CrDoHYq4iPaflgJWmoJ1K4ziLrRogJvFTVWg8P0UcDU,4744
@@ -75,10 +75,10 @@ model_compression_toolkit/core/common/mixed_precision/set_layer_to_bitwidth.py,s
75
75
  model_compression_toolkit/core/common/mixed_precision/solution_refinement_procedure.py,sha256=fk7PWiZ6Na5O_Z_dymk_UfDCTqW_X_4EROU7DZknQnc,9444
76
76
  model_compression_toolkit/core/common/mixed_precision/resource_utilization_tools/__init__.py,sha256=Rf1RcYmelmdZmBV5qOKvKWF575ofc06JFQSq83Jz99A,696
77
77
  model_compression_toolkit/core/common/mixed_precision/resource_utilization_tools/resource_utilization.py,sha256=PKkhc5q8pEPnNLXwo3U56EOCfYnPXIvPs0LlCGZOoKU,4426
78
- model_compression_toolkit/core/common/mixed_precision/resource_utilization_tools/resource_utilization_calculator.py,sha256=xCYL36K0nK41VSsLcy52uDA7zVfoLxhubmOrtXbqw7s,39140
78
+ model_compression_toolkit/core/common/mixed_precision/resource_utilization_tools/resource_utilization_calculator.py,sha256=MP4Q5lThvEIhfa1iBajQQM3nCUNgK-2yseqQQ8Rgiog,40624
79
79
  model_compression_toolkit/core/common/mixed_precision/resource_utilization_tools/resource_utilization_data.py,sha256=QQwtl08DiDxUOQGpYPnek_RlZjWm1Ky7tL2ESHXMK78,4050
80
80
  model_compression_toolkit/core/common/mixed_precision/search_methods/__init__.py,sha256=sw7LOPN1bM82o3SkMaklyH0jw-TLGK0-fl2Wq73rffI,697
81
- model_compression_toolkit/core/common/mixed_precision/search_methods/linear_programming.py,sha256=rSSN5MhH5BO5b58d8pe2pY9wc5HbfescoUStfg-nWfk,7263
81
+ model_compression_toolkit/core/common/mixed_precision/search_methods/linear_programming.py,sha256=TaK5NqVdmygsHw9_x5JsJ-BPvlbKA9cRyTno1R8gbnU,7269
82
82
  model_compression_toolkit/core/common/network_editors/__init__.py,sha256=vZmu55bYqiaOQs3AjfwWDXHmuKZcLHt-wm7uR5fPEqg,1307
83
83
  model_compression_toolkit/core/common/network_editors/actions.py,sha256=nid0_j-Cn10xvmztT8yCKW_6uA7JEnom9SW9syx7wc0,19594
84
84
  model_compression_toolkit/core/common/network_editors/edit_network.py,sha256=dfgawi-nB0ocAJ0xcGn9E-Zv203oUnQLuMiXpX8vTgA,1748
@@ -526,7 +526,7 @@ model_compression_toolkit/xquant/pytorch/model_analyzer.py,sha256=b93o800yVB3Z-i
526
526
  model_compression_toolkit/xquant/pytorch/pytorch_report_utils.py,sha256=UVN_S9ULHBEldBpShCOt8-soT8YTQ5oE362y96qF_FA,3950
527
527
  model_compression_toolkit/xquant/pytorch/similarity_functions.py,sha256=CERxq5K8rqaiE-DlwhZBTUd9x69dtYJlkHOPLB54vm8,2354
528
528
  model_compression_toolkit/xquant/pytorch/tensorboard_utils.py,sha256=mkoEktLFFHtEKzzFRn_jCnxjhJolK12TZ5AQeDHzUO8,9767
529
- mct_nightly-2.3.0.20250331.610.dist-info/METADATA,sha256=BSWkSPN58Xfzc8eImgBxCG3v_wXYt8c7l8oFNOOoyGw,27098
530
- mct_nightly-2.3.0.20250331.610.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
531
- mct_nightly-2.3.0.20250331.610.dist-info/top_level.txt,sha256=gsYA8juk0Z-ZmQRKULkb3JLGdOdz8jW_cMRjisn9ga4,26
532
- mct_nightly-2.3.0.20250331.610.dist-info/RECORD,,
529
+ mct_nightly-2.3.0.20250401.618.dist-info/METADATA,sha256=53LoSDV2ox7X64SeEb9OwP4UsuLi75QeSwyFLponCrQ,27098
530
+ mct_nightly-2.3.0.20250401.618.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
531
+ mct_nightly-2.3.0.20250401.618.dist-info/top_level.txt,sha256=gsYA8juk0Z-ZmQRKULkb3JLGdOdz8jW_cMRjisn9ga4,26
532
+ mct_nightly-2.3.0.20250401.618.dist-info/RECORD,,
@@ -27,4 +27,4 @@ from model_compression_toolkit import data_generation
27
27
  from model_compression_toolkit import pruning
28
28
  from model_compression_toolkit.trainable_infrastructure.keras.load_model import keras_load_quantized_model
29
29
 
30
- __version__ = "2.3.0.20250331.000610"
30
+ __version__ = "2.3.0.20250401.000618"
@@ -696,6 +696,23 @@ class Graph(nx.MultiDiGraph, GraphSearches):
696
696
  sorted_conf_activation = self.get_sorted_activation_configurable_nodes()
697
697
  return [(n, n.final_activation_quantization_cfg.activation_n_bits) for n in sorted_conf_activation]
698
698
 
699
+ def retrieve_preserved_quantization_node(self, node: BaseNode) -> BaseNode:
700
+ """
701
+ For a node with quantization_preserving == True, get the previous non-quantization_preserving node
702
+ to get activation quantization config from. If quantization_preserving is False return node.
703
+ Args:
704
+ node: quantization preserving node.
705
+
706
+ Returns:
707
+ The node that the quantization preserving node should get the activation quantization from.
708
+
709
+ """
710
+ while node.is_quantization_preserving():
711
+ prev_nodes = self.get_prev_nodes(node)
712
+ assert len(prev_nodes) == 1, "Activation preserving node should have only 1 input."
713
+ node = prev_nodes[0]
714
+ return node
715
+
699
716
  def update_fused_nodes(self, fusion: List[Any]):
700
717
  """
701
718
  Updates the graphs fusions list with a new list of nodes that have been fused.
@@ -131,6 +131,19 @@ class BaseNode:
131
131
  qc.activation_quantization_cfg.enable_activation_quantization
132
132
  return self.candidates_quantization_cfg[0].activation_quantization_cfg.enable_activation_quantization
133
133
 
134
+ def is_quantization_preserving(self) -> bool:
135
+ """
136
+ Returns: Whether node activation quantization information is preserved from its inputs.
137
+ """
138
+ if self.final_activation_quantization_cfg:
139
+ # if we have a final configuration, then we only care to check if it enables activation quantization.
140
+ return self.final_activation_quantization_cfg.quantization_preserving
141
+
142
+ for qc in self.candidates_quantization_cfg:
143
+ assert self.candidates_quantization_cfg[0].activation_quantization_cfg.quantization_preserving == \
144
+ qc.activation_quantization_cfg.quantization_preserving
145
+ return self.candidates_quantization_cfg[0].activation_quantization_cfg.quantization_preserving
146
+
134
147
  def is_weights_quantization_enabled(self, attr_name: str) -> bool:
135
148
  """
136
149
  Checks whether a node's weights attribute quantization is enabled.
@@ -335,13 +335,35 @@ class ResourceUtilizationCalculator:
335
335
  """
336
336
  return self.compute_activation_utilization_by_cut(target_criterion, bitwidth_mode, act_qcs)
337
337
 
338
+ def _extract_qc(self, n: BaseNode, act_qcs: Optional[ActivationQCfgPerNode] = None
339
+ ) -> Union[NodeActivationQuantizationConfig, None]:
340
+ """
341
+ Extract quantization config the activation configs dictionary is provided. If node is quantization
342
+ preserving, extract the quantization config from the preceding activation quantized node (i.e.
343
+ the Quantization the original node preserves).
344
+
345
+ Args:
346
+ n: Node to extract qc for.
347
+ act_qcs: custom activations quantization configuration. If not provided, the default
348
+ configuration will be extracted from the node.
349
+
350
+ Returns:
351
+ The relevant quantization config.
352
+ """
353
+ if act_qcs:
354
+ assert not (n.is_quantization_preserving() and act_qcs.get(n.name) is not None), \
355
+ f"Quantization preserving node {n.name} should not have a qc for this computation."
356
+ return act_qcs.get(self.graph.retrieve_preserved_quantization_node(n).name)
357
+ return None
358
+
338
359
  def compute_activation_utilization_by_cut(self,
339
360
  target_criterion: TargetInclusionCriterion,
340
361
  bitwidth_mode: BitwidthMode,
341
362
  act_qcs: Optional[ActivationQCfgPerNode] = None) \
342
363
  -> Tuple[float, Dict[Cut, Utilization], Dict[Cut, Dict[BaseNode, Utilization]]]:
343
364
  """
344
- Compute graph activation cuts utilization.
365
+ Compute graph activation cuts utilization. If activation quantization configs are provided, then for
366
+ quantization preserving nodes, get the previous quantized activation node bit-width.
345
367
 
346
368
  Args:
347
369
  target_criterion: criterion to include weights for computation.
@@ -369,7 +391,7 @@ class ResourceUtilizationCalculator:
369
391
  if not cut_target_nodes:
370
392
  continue
371
393
  for n in cut_target_nodes:
372
- qc = act_qcs.get(n.name) if act_qcs else None
394
+ qc = self._extract_qc(n, act_qcs)
373
395
  util_per_cut_per_node[cut][n.name] = self.compute_node_activation_tensor_utilization(n, target_criterion,
374
396
  bitwidth_mode, qc)
375
397
  util_per_cut[cut] = sum(util_per_cut_per_node[cut].values()) # type: ignore
@@ -384,7 +406,8 @@ class ResourceUtilizationCalculator:
384
406
  include_reused=False) \
385
407
  -> Tuple[float, Dict[NodeName, Utilization]]:
386
408
  """
387
- Compute resource utilization for graph's activations tensors.
409
+ Compute resource utilization for graph's activations tensors. If activation quantization configs are provided, then for
410
+ quantization preserving nodes, get the previous quantized activation node bit-width.
388
411
 
389
412
  Args:
390
413
  target_criterion: criterion to include weights for computation.
@@ -405,7 +428,7 @@ class ResourceUtilizationCalculator:
405
428
 
406
429
  util_per_node: Dict[NodeName, Utilization] = {}
407
430
  for n in self._topo_sort(nodes):
408
- qc = act_qcs.get(n.name) if act_qcs else None
431
+ qc = self._extract_qc(n, act_qcs)
409
432
  util = self.compute_node_activation_tensor_utilization(n, None, bitwidth_mode, qc)
410
433
  util_per_node[n.name] = util
411
434
 
@@ -659,7 +682,7 @@ class ResourceUtilizationCalculator:
659
682
  if target_criterion == TargetInclusionCriterion.QConfigurable:
660
683
  nodes = [n for n in nodes if n.has_configurable_activation()]
661
684
  elif target_criterion == TargetInclusionCriterion.AnyQuantized:
662
- nodes = [n for n in nodes if n.is_activation_quantization_enabled()]
685
+ nodes = [n for n in nodes if n.is_activation_quantization_enabled() or n.is_quantization_preserving()]
663
686
  elif target_criterion == TargetInclusionCriterion.QNonConfigurable:
664
687
  nodes = [n for n in nodes if n.is_activation_quantization_enabled() and not n.has_configurable_activation()]
665
688
  elif target_criterion != TargetInclusionCriterion.Any: # pragma: no cover
@@ -668,8 +691,7 @@ class ResourceUtilizationCalculator:
668
691
  nodes = [n for n in nodes if not n.reuse]
669
692
  return nodes
670
693
 
671
- @classmethod
672
- def _get_activation_nbits(cls,
694
+ def _get_activation_nbits(self,
673
695
  n: BaseNode,
674
696
  bitwidth_mode: BitwidthMode,
675
697
  act_qc: Optional[NodeActivationQuantizationConfig]) -> int:
@@ -690,21 +712,22 @@ class ResourceUtilizationCalculator:
690
712
  assert bitwidth_mode == BitwidthMode.QCustom
691
713
  return act_qc.activation_n_bits if act_qc.enable_activation_quantization else FLOAT_BITWIDTH
692
714
 
693
- if bitwidth_mode == BitwidthMode.Float or not n.is_activation_quantization_enabled():
715
+ if bitwidth_mode == BitwidthMode.Float or not (n.is_activation_quantization_enabled() or
716
+ n.is_quantization_preserving()):
694
717
  return FLOAT_BITWIDTH
695
718
 
696
719
  if bitwidth_mode == BitwidthMode.Q8Bit:
697
720
  return 8
698
721
 
699
- if bitwidth_mode in cls._bitwidth_mode_fn:
722
+ if bitwidth_mode in self._bitwidth_mode_fn:
700
723
  candidates_nbits = [c.activation_quantization_cfg.activation_n_bits for c in n.candidates_quantization_cfg]
701
- return cls._bitwidth_mode_fn[bitwidth_mode](candidates_nbits)
724
+ return self._bitwidth_mode_fn[bitwidth_mode](candidates_nbits)
702
725
 
703
726
  if bitwidth_mode in [BitwidthMode.QCustom, BitwidthMode.QDefaultSP]:
704
- qcs = n.get_unique_activation_candidates()
727
+ qcs = self.graph.retrieve_preserved_quantization_node(n).get_unique_activation_candidates()
705
728
  if len(qcs) != 1:
706
729
  raise ValueError(f'Could not retrieve the activation quantization candidate for node {n} '
707
- f'as it has {len(qcs)}!=1 unique candidates .')
730
+ f'as it has {len(qcs)}!=1 unique candidates.')
708
731
  return qcs[0].activation_quantization_cfg.activation_n_bits
709
732
 
710
733
  raise ValueError(f'Unknown mode {bitwidth_mode}') # pragma: no cover
@@ -14,7 +14,7 @@
14
14
  # ==============================================================================
15
15
  import numpy as np
16
16
  from pulp import *
17
- from typing import Dict, Tuple
17
+ from typing import Dict, Tuple, List
18
18
 
19
19
  from model_compression_toolkit.core.common.mixed_precision.resource_utilization_tools.resource_utilization import RUTarget
20
20