+
    G-jP<  ã                   óL  € R t ^ RIt^ RIt^ RIt^ RIHtHt ^ RIHt ^ RI	t	^ RI
t
^ RI
HtHt ^ RIt^RIHtHt ^RIHt ^RIHtHtHtHtHtHt Rt]! ]4      tRR	 R
 lltRR R llt]R,           tR R lt RR R llt!R R lt"R R lt#R R lt$]$3R R llt%]$3R R llt&R# )aÇ  Utilities to run a given ONNX model, while saving input/output tensors of
eligible operator nodes.

A use case is to debug quantization induced accuracy drop. An AI engineer can
run the original float32 model and the quantized model with the same inputs,
then compare the corresponding activations between the two models to find
where the divergence is.

Example Usage:

```python
    class ExampleDataReader(CalibrationDataReader):
        def __init__(self):
            ...
        def get_next(self):
            ...

    input_data_reader = ExampleDataReader()

    augmented_model_path = str(Path(self._tmp_model_dir.name).joinpath("augmented_model.onnx"))
    modify_model_output_intermediate_tensors (path_to_onnx_model, augmented_model_path)

    tensor_dict = collect_activations(augmented_model_path, input_data_reader)
```

`tensor_dict` points to a dictionary where the keys are tensor names and each value
is a list of tensors, one from each model run

N)ÚCallableÚSequence)ÚPath)ÚhelperÚnumpy_helper)ÚCalibraterBaseÚCalibrationDataReader)Ú	ONNXModel)ÚDEQUANT_OP_NAMEÚDEQUANT_OUTPUT_SUFFIXÚQUANT_INPUT_SUFFIXÚTENSOR_NAME_QUANT_SUFFIXÚfind_by_nameÚload_model_with_shape_inferÚ_ReshapedSavedOutputc          
      óœ   € V ^8„  d   QhR\         \        ,          R\         \        ,          R\        \         ,          R,          R\        RR/# )é   Úinput_model_pathÚoutput_model_pathÚop_types_for_savingNÚsave_as_external_dataÚreturn)Ústrr   r   Úbool)Úformats   "Úx/Volumes/fast/ai/experiments/nudenet-smoke/.venv/lib/python3.14/site-packages/onnxruntime/quantization/qdq_loss_debug.pyÚ__annotate__r   @   sK   € ÷ 0ñ 0ÜœD•jð0äœT•zð0ô "¤#�¨Õ-ð0ô  ð	0ð
 
ñ0ó    c                ó*  € Vf   . p\        WR7      pVP                  pVP                  V4      w  rgR\        \        P                  ! 4       4      ,           p\
        P                  ! \        P                  ! R.\        P                  R7      V4      p	VP                  P                  P                  V	4       V F¼  p
V
\        ,           p\        P                  P!                  RW¨.V.VR7      pVP                  P"                  P                  V4       \        P$                  ! W·V
,          P&                  P(                  P*                  R.4      pVP                  P,                  P                  V4       K¾  	  \        P.                  ! VVVR7       R# )	a¸  Augment a given ONNX model to save node input/output tensors.

Add all input/output tensors of operator nodes to model outputs
so that their values can be retrieved for debugging purposes.

Args:
    input_model: the path to load the model.
    op_types_for_saving: Operator types for which the
            input/output should be saved. By default, saving all the
            float32/float16 tensors.

Returns:
    The augmented ONNX model
N)Úop_types_to_calibrateÚLinearReshape_©ÚdtypeÚReshape)ÚinputsÚoutputsÚname)r   éÿÿÿÿ)r   ÚmodelÚselect_tensors_to_calibrater   Útimer   Ú
from_arrayÚnumpyÚarrayÚint64ÚgraphÚinitializerÚappendÚ_TENSOR_SAVE_POSTFIXÚonnxr   Ú	make_nodeÚnodeÚmake_tensor_value_infoÚtypeÚtensor_typeÚ	elem_typeÚoutputÚsave)r   r   r   r   ÚsaverÚmodel_to_augmentÚtensorsÚvalue_infosÚreshape_shape_nameÚreshape_shapeÚtensor_nameÚreshape_outputÚreshape_nodeÚreshape_output_value_infos   &&&&          r   Ú(modify_model_output_intermediate_tensorsrF   @   sN  € ð* Ò"Ø ÐÜÐ+ÔW€EØ—{‘{ÐØ ×<Ñ<Ð=MÓNÑ€GØ)¬C´·	²	³Ó,<Õ<ÐÜ ×+Ò+¬E¯KªK¸¸ÄEÇKÁKÔ,PÐRdÓe€MØ×Ñ×&Ñ&×-Ñ-¨mÔ<ãˆØ$Ô';Õ;ˆÜ—{‘{×,Ñ,ØØÐ4Ø#Ð$Øð	 -ó 
ˆð 	×Ñ×#Ñ#×*Ñ*¨<Ô8Ü$*×$AÒ$AØ¨Õ4×9Ñ9×EÑE×OÑOÐRTÐQUó%
Ð!ð 	×Ñ×%Ñ%×,Ñ,Ð-FÖGñ ô 	‡I‚IØØØ3÷r   c                ó¸   € V ^8„  d   QhR\         R\        R\        \         ,          R,          R\        \         \        \
        P                  ,          3,          /# )r   Úaugmented_modelÚinput_readerÚexecution_providersNr   )r   r   r   ÚdictÚlistr,   Úndarray)r   s   "r   r   r   s   sL   € ÷ /ñ /Üð/ä'ð/ô "¤#�¨Õ-ð	/ô
 
Œ#Œt”E—M‘MÕ"Ð
"Õ#ñ/r   c                óN  € Vf5   \         P                  ! 4       p\         P                  P                  Vn        Vf   R.p\         P
                  ! V VVR7      p. pV F$  pVP                  VP                  RV4      4       K&  	  V'       g   \        R4      h/ pVP                  4       pV Fu  p	\        W‰RR7       Fa  w  r«V
P                  P                  \        4      '       g   K,  V
P                  R\        )  pVP                  V. 4      P                  V4       Kc  	  Kw  	  V# )aˆ  Run augmented model and collect activations tensors.

Args:
    augmented_model: Path to augmented model created by modify_model_output_intermediate_tensors ()
    input_reader: Logic for reading input for the model, augmented model have the same
        input with the original model.
    session_options: Optional OnnxRuntime session options for controlling model run.
        By default graph optimization is turned off
    execution_providers: Collection of execution providers for running the model.
        Only CPU EP is used by default.

Returns:
    A dictionary where the key is tensor name and values are list of tensors from each batch
NÚCPUExecutionProvider)Úsess_optionsÚ	providersz3No data is collected while running augmented model!F)Ústrict)ÚonnxruntimeÚSessionOptionsÚGraphOptimizationLevelÚORT_DISABLE_ALLÚgraph_optimization_levelÚInferenceSessionr1   ÚrunÚRuntimeErrorÚget_outputsÚzipr&   Úendswithr2   Ú_TENSOR_SAVE_POSTFIX_LENÚ
setdefault)rH   rI   Úsession_optionsrJ   Úinference_sessionÚintermediate_outputsÚinput_dÚoutput_dictÚoutput_infoÚbatchr:   Úoutput_dataÚoutput_names   &&&&         r   Úcollect_activationsri   s   s  € ð* ÒÜ%×4Ò4Ó6ˆÜ3>×3UÑ3U×3eÑ3eˆÔ0ØÒ"Ø5Ð6Ðä#×4Ò4ØØ$Ø%ôÐð ÐÛˆØ×#Ñ#Ð$5×$9Ñ$9¸$ÀÓ$HÖIñ  çÜÐPÓQÐQà€KØ#×/Ñ/Ó1€KÛ%ˆÜ#& {À%×#HÑˆFØ�{‰{×#Ñ#Ô$8×9Ô9Ø$Ÿk™kÐ*DÔ,DÐ+DÐE�Ø×&Ñ& {°BÓ7×>Ñ>¸{ÖKó $Iñ &ð Ðr   Ú_1c          
      ó*  € V ^8„  d   QhR\         \        \         \        \        \        P                  ,          3,          3,          R\        R\        \        P                  ,          R,          R\        \        P                  ,          R,          RR/# )r   Úqdq_cmpÚactivation_nameÚpre_qdq_tensorsNÚpost_qdq_tensorsr   ©rK   r   r   r,   rM   )r   s   "r   r   r   ¨   sz   € ÷ 	@ñ 	@Ü”#”tœC¤¬%¯-©-Õ!8Ð8Õ9Ð9Õ:ð	@äð	@ô œeŸm™mÕ,¨tÕ3ð	@ô œuŸ}™}Õ-°Õ4ð		@ð
 
ñ	@r   c                 óR   € Ve#   Ve   / W&   W V,          R&   W0V,          R&   R # R # R # )NÚpre_qdqÚpost_qdq© )rl   rm   rn   ro   s   &&&&r   Ú_add_pre_post_qdq_pairru   ¨   s:   € ð Ò#¨Ò(CØ#%ˆÑ Ø.=�Õ  Ñ+Ø/?�Õ  Ó,ñ )DÑ#r   c                óP  € V ^8„  d   QhR\         \        \        \        P                  ,          3,          R\         \        \        \        P                  ,          3,          R,          R\         \        \         \        \        \        P                  ,          3,          3,          /# )r   Úqdq_activationsÚfloat_activationsNr   rp   )r   s   "r   r   r   ´   sn   € ÷ ;ñ ;Üœ#œx¬¯©Õ6Ð6Õ7ð;äœC¤¬%¯-©-Õ!8Ð8Õ9¸DÕ@ð;ô 
Œ#Œt”Cœ¤%§-¡-Õ0Ð0Õ1Ð
1Õ2ñ;r   c                ó’  € / pV P                  4        Fò  w  r4VP                  \        4      '       d5   VR\        \        4      )  pV P	                  V4      pTp\        W%Wv4       KT  VP                  \        4      '       d5   VR\        \        4      )  pV P	                  V4      pTp\        W%Wv4       K£  VP                  \        4      '       g   KÀ  VR\        \        4      )  pV P	                  V4      pTp\        W%Wv4       Kô  	  V'       g   V# VP                  4        F   w  r‰VP	                  V4      p
V
f   K  W©R&   K"  	  V# )aQ  Comparing activation values to help debugging accuracy loss due to quantization.

This functions takes saved activations from the QDQ model and (optionally) the
float point model, and provides a data structure for comparing:
    * from the qdq model, activation values before and after QDQ operation
    * across both models, activations from the orignal model vs the corresponding
      activations in the QDQ model

Arg:
    qdq_activations: Output of `collect_activations`. This must be from a quantized
        model with QDQ format.
    float_activations: Output of `collect_activations`. This must be from the float
        point model.

Returns:
    Dict for comparing pre and post quantized activation tensors. E.g.
    ```
    qdq_cmp = cmp_qdq_input_output(qdq_activations)
    print(qdq_cmp['activation1']['pre_qdq'][0])
    print(qdq_cmp['activation1'][`post_qdq'][0])


    qdq_cmp = cmp_qdq_input_output(qdq_activations, float_activations)
    print(qdq_cmp['activation1']['float'][0])
    print(qdq_cmp['activation1']['pre_qdq'][0])
    print(qdq_cmp['activation1'][`post_qdq'][0])
    ```
NÚfloat)Úitemsr]   r   ÚlenÚgetru   r   Ú_POST_QDQ_POSTFIX1)rw   rx   rl   rB   r>   Úpre_namero   rn   Úact_nameÚ
act_valuesÚ
float_actss   &&         r   Úcreate_activation_matchingrƒ   ´   s;  € ðB >@€GØ /× 5Ñ 5Ö 7ÑˆØ×ÑÔ 2×3Ò3Ø"Ð#=¤cÔ*<Ó&=Ð%=Ð>ˆHØ.×2Ñ2°8Ó<ÐØ%ˆOÜ" 7°oÖXØ×!Ñ!Ô"7×8Ò8Ø"Ð#@¤cÔ*?Ó&@Ð%@ÐAˆHØ-×1Ñ1°(Ó;ˆOØ&ÐÜ" 7°oÖXØ×!Ñ!Ô"4×5Ô5Ø"Ð#=¤cÔ*<Ó&=Ð%=Ð>ˆHØ-×1Ñ1°(Ó;ˆOØ&ÐÜ" 7°oÖXñ !8÷" Øˆà '§¡¦ÑˆØ&×*Ñ*¨8Ó4ˆ
ØÔ!Ø",�wÓñ !0ð
 €Nr   c                ó²   € V ^8„  d   QhR\         P                  R\         P                  R\         P                  R\        R\         P                  R,          /# )r   Úweight_tensorÚweight_scaleÚ	weight_zpÚchannel_axisr   N)r,   rM   Úint)r   s   "r   r   r   ò   sI   € ÷ ñ Ü—=‘=ðÜ05·±ðÜJOÏ-É-ðÜgjðä
‡]�]�TÕñr   c                 ó˜  € VP                   VP                   8X  g   Q hVP                  ^8X  d   W,
          V,          # VP                  ^8X  g   Q h\        V P                   4      p^WC&   V P                   V,          pRp\	        V4       F›  pV P                  Ws4      pW‚V,          ,
          W,          ,          p	V^ 8X  d(   \        P                  ! V	4      P                  V4      pK^  \        P                  ! V	4      P                  V4      p
\        P                  ! Wj3V4      pK�  	  Vf   R# VP                  V P                   4       V# )é   N)
ÚshapeÚsizeÚndimrL   ÚrangeÚtaker,   ÚasarrayÚreshapeÚconcatenate)r…   r†   r‡   rˆ   Úreshape_dimsÚchannel_countÚdequantized_weightsÚiÚper_channel_dataÚdequantized_per_channel_dataÚchannel_weightss   &&&&       r   Ú_run_dequantize_linearr›   ò   s%  € ð ×Ñ §¡Ô0Ð0Ð0Ø‡~�~˜ÔØÕ)¨\Õ9Ð9à�>‰>˜QÔÐÐÜ˜×+Ñ+Ó,€LØ!"€LÑØ!×'Ñ'¨Õ5€MØÐÜ�=Ö!ˆØ(×-Ñ-¨aÓ>ÐØ(8ÀQ½<Õ(GÈ<Í?Õ'ZÐ$Ø�Œ6Ü"'§-¢-Ð0LÓ"M×"UÑ"UÐVbÓ"cÒä#ŸmšmÐ,HÓI×QÑQÐR^Ó_ˆOÜ"'×"3Ò"3Ð5HÐ4ZÐ\hÓ"iÒñ "ð Ò"Ùà×Ñ × 3Ñ 3Ô4ØÐr   c          
      ó”   € V ^8„  d   QhR\         R\         R\        \         \        \         \        P                  3,          3,          /# )r   Úfloat_model_pathÚqdq_model_pathr   )r   rK   r,   rM   )r   s   "r   r   r     sC   € ÷ Dñ D¬Sð DÄ#ð DÌ$ÌsÔTXÔY\Ô^c×^kÑ^kÐYkÕTlÐOlÕJmñ Dr   c                ó  € \        \        \        V 4      4      4      p\        \        \        V4      4      4      p/ pVP                  4       pVP	                  4        EFŸ  pVP
                  \        8w  d   K  VP                  ^ ,          p\        Wu4      pV'       g   KC  VP                  \        4      '       g    \        P                  ! RV RV R24       K}  Rp	VP                   F"  p
V
P                  R8X  g   K  V
P                  p	K$  	  \         P"                  ! V4      p\         P"                  ! \        VP                  ^,          V4      4      p\%        VP                  4      ^8”  d3   \         P"                  ! \        VP                  ^,          V4      4      pM0\&        P(                  ! VP*                  \&        P,                  R7      pVP.                  VP.                  u;8X  d   ^8X  d&   M M"VP1                  R4      pVP1                  R4      pVP*                  VP*                  8w  d&   \3        RVP*                   RVP*                   24      h\5        W¼WÙR7      pVR	\%        \        4      )  pVf!   \        P                  ! RV R
V R24       EK@  \        WrP                  4       4      pV'       g!   \        P                  ! RV  RV R24       EK�  \         P"                  ! V4      pRVRV/WG&   EK¢  	  V# )aT  Comparing weight values to help debugging accuracy loss due to quantization.

This functions takes the float model and the qdq model, and provides a data structure for comparing
their corresponding weights to locate quantization errors

Arg:
    float_model_path: Path points to the float point model.
    qdq_model_path: Path points to the qdq model.

Returns:
    Dict for comparing weight tensors. E.g.
    ```
    qdq_weight_cmp = create_weight_matching(float_model, qdq_model)
    print(qdq_weight_cmp['activation1']['float'])
    print(qdq_weight_cmp['activation1']['dequantized'])
    ```
zModel Error in 'z': Dequantized tensor name 'z' not recognized!Úaxisr!   z2scale and zero_point must have the same shape but z != )rˆ   Nz': 'z'' per-channel quantization on 0 channelz': weight tensor 'z' not found!rz   Údequantizedr'   rt   )r	   r   r   r0   ÚnodesÚop_typer
   Úinputr   r]   r   ÚloggingÚerrorÚ	attributer&   r—   r   Úto_arrayr|   r,   ÚzerosrŒ   Úint32r�   r’   rZ   r›   )r�   rž   Úfloat_onnx_modelÚqdq_onnx_modelÚmatched_weightsÚinitializersr5   Úweight_nameÚweight_valuesr    Úattrr…   r†   r‡   Úweight_quantÚfloat_valuesÚweight_floats   &&               r   Úcreate_weight_matchingrµ     sƒ  € ô$ !Ô!<¼TÐBRÓ=SÓ!TÓUÐÜÔ:¼4ÀÓ;OÓPÓQ€Nà;=€OØ!×-Ñ-Ó/€LØ×$Ñ$×&ˆØ�<‰<œ?Ô*ÙØŸ:™: a�=ˆÜ$ [Ó?ˆßÙØ×#Ñ#Ô$<×=Ò=Ü�MŠMÐ,¨^Ð,<Ð<XÐYdÐXeÐevÐwÔxÙàˆØ—N”NˆDØ�y‰y˜FÖ"Ø—v‘v’ñ #ô %×-Ò-¨mÓ<ˆÜ#×,Ò,¬\¸$¿*¹*ÀQ½-ÈÓ-VÓWˆÜˆt�z‰z‹?˜QÔÜ$×-Ò-¬l¸4¿:¹:Àa½=È,Ó.WÓX‰IäŸš L×$6Ñ$6¼e¿k¹kÔJˆIð ×Ñ 	§¡Ö3°!×3à'×/Ñ/°Ó3ˆLØ!×)Ñ)¨"Ó-ˆIØ×Ñ §¡Ô0ÜØDÀ\×EWÑEWÐDXÐX\Ð]f×]lÑ]lÐ\mÐnóð ô .¨mÈ9ÔhˆØ!Ð"B¤SÔ)AÓ%BÐ$BÐCˆØÒÜ�MŠMÐ,¨^Ð,<¸DÀÀÐMtÐuÔvÚä# K×1MÑ1MÓ1OÓPˆßÜ�MŠMÐ,Ð-=Ð,>Ð>PÐQ\ÐP]Ð]iÐjÔkÚÜ#×,Ò,¨\Ó:ˆØ(/°¸}ÈlÐ'[ˆÔ$ñW 'ðZ Ðr   c                óä   € V ^8„  d   QhR\         \        P                  ,          \        P                  ,          R\         \        P                  ,          \        P                  ,          R\        /# )r   ÚxÚyr   )r   r,   rM   rz   )r   s   "r   r   r   U  sH   € ÷  ñ  Ü”—‘Õ¤§¡Õ.ð Ü3;¼E¿M¹MÕ3JÌUÏ]É]Õ3Zð ä
ñ r   c                 ó¬  € \        V \        P                  4      '       d   V .pMT p\        V\        P                  4      '       d   V.pMTp\        V4      \        V4      8w  d   \	        R 4      h\        P
                  ! V4      P                  4       p\        P
                  ! V4      P                  4       p\        P                  ! R4      P                  p\        \        P                  P                  V4      V4      p\        \        P                  P                  WE,
          4      V4      pWx,          p	^\        P                  ! V	4      ,          # )z%Unequal number of tensors to compare!rz   )Ú
isinstancer,   rM   r|   rZ   r“   ÚflattenÚfinfoÚepsÚmaxÚlinalgÚnormÚmathÚlog10)
r·   r¸   ÚxlistÚylistÚleftÚrightÚepsilonÚtensor_normÚ	diff_normÚress
   &&        r   Ú*compute_signal_to_quantization_noice_ratiorË   U  só   € ô �!”U—]‘]×#Ò#Ø�‰àˆÜ�!”U—]‘]×#Ò#Ø�‰àˆÜ
ˆ5ƒz”S˜“ZÔÜÐBÓCÐCä×Ò˜UÓ#×+Ñ+Ó-€DÜ×Ò˜eÓ$×,Ñ,Ó.€Eä�kŠk˜'Ó"×&Ñ&€GÜ”e—l‘l×'Ñ'¨Ó-¨wÓ7€KÜ”E—L‘L×%Ñ% d¥lÓ3°WÓ=€IØ
Õ
!€CØ”—
’
˜3“ÕÐr   c                ó  € V ^8„  d   QhR\         \        \         \        \        P                  3,          3,          R\        \        P                  \        P                  .\
        3,          R\         \        \
        3,          /# )r   Úweights_matchÚerr_funcr   )rK   r   r,   rM   r   rz   )r   s   "r   r   r   m  s^   € ÷ ñ ÜœœT¤#¤u§}¡}Ð"4Õ5Ð5Õ6ðäœŸ™¤u§}¡}Ð5´uÐ<Õ=ðô 
Œ#Œuˆ*Õñr   c                 ón   € / pV P                  4        F  w  r4V! VR ,          VR,          4      W#&   K   	  V# )rz   r¡   ©r{   )rÍ   rÎ   Úresultr¯   Úweight_matchs   &&   r   Úcompute_weight_errorrÓ   m  s=   € ð  "€FØ%2×%8Ñ%8Ö%:Ñ!ˆÙ& |°GÕ'<¸lÈ=Õ>YÓZˆÓñ &;à€Mr   c          
      óp  € V ^8„  d   QhR\         \        \         \        \        \        P                  ,          3,          3,          R\
        \        \        P                  ,          \        \        P                  ,          .\        3,          R\         \        \         \        \        3,          3,          /# )r   Úactivations_matchrÎ   r   )rK   r   r   r,   rM   r   rz   )r   s   "r   r   r   w  sz   € ÷ ñ ÜœC¤¤c¬8´E·M±MÕ+BÐ&BÕ!CÐCÕDðäÜ	”%—-‘-Õ	 ¤(¬5¯=©=Õ"9Ð:¼EÐAõðô
 
Œ#Œt”Cœ�JÕÐ
Õ ñr   c                 óÂ   € / pV P                  4        FH  w  r4/ pV! VR ,          VR,          4      VR&   VR,          pV'       d   V! WdR,          4      VR&   WRV&   KJ  	  V# )rr   rs   Úqdq_errrz   Ú
xmodel_errrÐ   )rÕ   rÎ   rÑ   r&   ÚmatchÚ
err_resultÚfloat_activations   &&     r   Úcompute_activation_errorrÜ   w  sn   € ð +-€FØ(×.Ñ.Ö0‰ˆØ')ˆ
Ù (¨¨yÕ)9¸5ÀÕ;LÓ Mˆ
�9ÑØ  �>ÐßÙ'/Ð0@È
ÕBSÓ'TˆJ�|Ñ$Ø!ˆt‹ñ 1ð €Mr   )NF)NN)N)'Ú__doc__r¥   rÁ   r*   Úcollections.abcr   r   Úpathlibr   r,   r3   r   r   rS   Ú	calibrater   r   Ú
onnx_modelr	   Úquant_utilsr
   r   r   r   r   r   r2   r|   r^   rF   ri   r~   ru   rƒ   r›   rµ   rË   rÓ   rÜ   rt   r   r   Ú<module>rã      sœ   ðñó< Û Û ß .Ý ã Û ß %ã ç <Ý !÷÷ ð .Ð ÙÐ3Ó4Ð ÷0÷f/ðd +¨TÕ1Ð õ	@÷;õ|õ8DõN ð4 Ak÷ð 	3÷	ñ r   