
    `iVW                     d   S SK r S SKrS SKrS SKrS SKJrJrJr  S SKJr	  S SK
Jr  S SKJr  SSKJrJr  SSKJr  S SKrS SKr " S	 S
\5      r " S S\R,                  S9r " S S5      r " S S\5      r " S S\5      r " S S\R,                  S9r " S S\5      r/ S\R:                  4S jrg)    N)helperTensorProto
ModelProto)onnx_pb)string_types)Enum   )	QuantTypesmooth_distribution)QLinearOpsRegistryc                       \ rS rSrSrSrSrg)CalibrationMethod   r   r	    N)__name__
__module____qualname____firstlineno__MinMaxEntropy__static_attributes__r       g/var/www/html/ai-image-ml/venv/lib/python3.13/site-packages/onnxruntime_tools/quantization/calibrate.pyr   r      s    FGr   r   c                   P    \ rS rSr\S 5       r\R                  S\4S j5       r	Sr
g)CalibrationDataReader   c                 l    [        US5      =(       a    [        UR                  5      =(       d    [        $ )Nget_next)hasattrcallabler   NotImplemented)clssubclasss     r   __subclasshook__&CalibrationDataReader.__subclasshook__   s%    *-M(8;L;L2M_Q_`r   returnc                     [         e)z9generate the input data dict for ONNXinferenceSession runNotImplementedErrorselfs    r   r   CalibrationDataReader.get_next#   s
     "!r   r   N)r   r   r   r   classmethodr$   abcabstractmethoddictr   r   r   r   r   r   r      s7    a a 	"$ " "r   r   )	metaclassc                   d    \ rS rSr/ S4S jrS/4S jrS rS rS rS	 r	S
\
4S jrS
\
4S jrSrg)CalibraterBase)   augmented_model.onnxc                 8   [        U[        5      (       a  [        R                  " U5      U l        O'[        U[
        5      (       a  Xl        O[        S5      eX l        X0l        SU l	        U R                  5         SU l        S/U l        U R                  5         g)  
:param model: ONNX model to calibrate. It can be a ModelProto or a model path
:param op_types_to_calibrate: operator types to calibrate. By default, calibrate all the float32/float16 tensors.
:param augmented_model_path: save augmented model to this path.
z5model should be either model path or onnx.ModelProto.NCPUExecutionProvider)
isinstancer   onnxloadmodelr   
ValueErrorop_types_to_calibrateaugmented_model_pathaugment_modelaugment_graphinfer_sessionexecution_providers_create_inference_session)r+   r<   r>   r?   s       r   __init__CalibraterBase.__init__*   s     e\**5)DJz**JTUU%:"$8! " "$:#; &&(r   r8   c                 0    Xl         U R                  5         g)zj
reset the execution providers to execute the collect_data. It triggers to re-creating inference session.
N)rC   rD   )r+   rC   s     r   set_execution_providers&CalibraterBase.set_execution_providersC   s     $7 &&(r   c                     [         R                  " 5       n[         R                  R                  Ul        [         R
                  " U R                  UU R                  S9U l        g)z)
create an OnnxRuntime InferenceSession.
)sess_options	providersN)	onnxruntimeSessionOptionsGraphOptimizationLevelORT_DISABLE_ALLgraph_optimization_levelInferenceSessionr?   rC   rB   )r+   rK   s     r   rD   (CalibraterBase._create_inference_sessionJ   sN     #1130;0R0R0b0b-(99$:S:SGSDHD\D\^r   c                 2   UR                   R                   Vs0 s H  o"R                  U_M     nnUR                  UR                   R                   Vs0 s H  oDR                  U_M     sn5        UR                  UR                   R
                   Vs0 s H  oUR                  U_M     sn5        [        S UR                   R                   5       5      n[        5       n[        [        R                  [        R                  /5      nUR                   R                   H  n	[        U R                  5      S:X  d  U	R                  U R                  ;   d  M8  [        R                   " U	R
                  U	R                  5       H|  n
XR#                  5       ;   d  M  X:   nUR$                  R'                  S5      (       d  M>  UR$                  R(                  R*                  U;   d  Md  X;  d  Mk  UR-                  U
5        M~     M     Xs4$ s  snf s  snf s  snf )z
select all quantization_candidates op type nodes' input/output tensors. 
returns:
    tensors (set): set of tensor name.
    value_infos (dict): tensor name to value info.
c              3   8   #    U  H  oR                   v   M     g 7fNname).0inits     r   	<genexpr>=CalibraterBase.select_tensors_to_calibrate.<locals>.<genexpr>^   s     H0G))0G   r   tensor_type)graph
value_inforX   updateoutputinputsetinitializerr   FLOATFLOAT16nodelenr>   op_type	itertoolschainkeystypeHasFieldr^   	elem_typeadd)r+   r<   vivalue_infosotitre   tensors_to_calibratetensor_type_to_calibraterh   tensor_names              r   select_tensors_to_calibrate*CalibraterBase.select_tensors_to_calibrateT   s    .3[[-C-CD-Crww{-CD%++2D2DE2DBGGRK2DEF%++2C2CD2CBGGRK2CDEH0G0GHH"u#&(9(9;;N;N'O#P KK$$D4--.!3t||tGaGa7a#,??4::t{{#KK"&6&6&88(577++M:: " 3 3 = =AY Y$/$B044[A $L % $00% EEDs   H
HHc                     U R                   $ )z
return: augmented onnx model
)r@   r*   s    r   get_augment_model CalibraterBase.get_augment_modelo   s     !!!r   c                     [         e)z
abstract method: augment the input model to prepare for collecting data. It will:
    1. save augmented model to augmented_model_path.
    2. set the self.augment_model
r(   r*   s    r   rA   CalibraterBase.augment_graphu   s
     "!r   data_readerc                     [         e)zp
abstract method: collect the tensors that will be used for range computation. It can be called multiple times.
r(   r+   r   s     r   collect_dataCalibraterBase.collect_data}   
     "!r   c                     [         e)zi
abstract method: compute the [min, max] range for the tensors to calibrate based on the collected data.
r(   r   s     r   compute_rangeCalibraterBase.compute_range   r   r   )r@   r?   rC   rB   r<   r>   N)r   r   r   r   rE   rH   rD   ry   r|   rA   r   r   r   r   r   r   r   r3   r3   )   sJ    46Mc )2 <R:R )^16"""(= "")> "r   r3   c                   V   ^  \ rS rSr/ S4U 4S jjrS rS rS\4S jrS r	S	 r
S
rU =r$ )MinMaxCalibrater   r5   c                   > [         [        U ]  XU5        / U l        SU l        [        U R                  R                  R                  5      U l	        [        S U R                  R                  R                   5       5      U l        g)r7   Nc              3   8   #    U  H  oR                   v   M     g 7frV   rW   rY   rb   s     r   r[   ,MinMaxCalibrater.__init__.<locals>.<genexpr>        )\D[&++D[r]   )superr   rE   intermediate_outputscalibrate_tensors_rangeri   r<   r_   rb   num_model_outputsrd   model_original_outputsr+   r<   r>   r?   	__class__s       r   rE   MinMaxCalibrater.__init__   sh     	.uMab$&!'+$!$TZZ%5%5%<%<!=&))\DJJDTDTD[D[)\&\#r   c           
         [         R                  " 5       nUR                  U R                  5        [        R
                  R                  U5      n/ n/ nU R                  U5      u  pEU GH  nXV   R                  R                  R                  R                  nSnSn	U Hc  n
U
R                  S5      S:X  d  M  U
R                  S:X  d  M,  Sn[        U5      S:X  a  SO#[        S [!        [        U5      5       5       5      n	  O   US-   n[        R"                  R%                  S	U/US-   /XS
9nUR'                  U5        UR'                  ["        R(                  " UR*                  S   [,        R.                  U	5      5        US-   n[        R"                  R%                  SU/US-   /XS
9nUR'                  U5        UR'                  ["        R(                  " UR*                  S   [,        R.                  U	5      5        GM     UR0                  R2                  R5                  U5        UR0                  R*                  R5                  U5        [        R6                  " XR8                  5        Xl        g)z
Adds ReduceMin and ReduceMax nodes to all quantization_candidates op type nodes in
model and ensures their outputs are stored as part of the graph output
:return: augmented ONNX model
r   r   value	dim_valuer	   )r	   c              3   &   #    U  H  nS v   M	     g7f)r	   Nr   )rY   is     r   r[   1MinMaxCalibrater.augment_graph.<locals>.<genexpr>   s     ;W!As   
_ReduceMin	ReduceMin)keepdims
_ReduceMax	ReduceMaxN)
onnx_protor   CopyFromr<   r:   shape_inferenceinfer_shapesry   rn   r^   shapedim
WhichOneofr   ri   listranger   	make_nodeappendmake_tensor_value_inforb   r   rf   r_   rh   extendsaver?   r@   )r+   r<   added_nodesadded_outputstensorsrs   tensorr   r   r   dreduce_min_namereduce_min_nodereduce_max_namereduce_max_nodes                  r   rA   MinMaxCalibrater.augment_graph   s    %%'tzz"$$11%8#??FF %**66<<@@CHE <<(K7AKK1<L H$'HMDt;WuSQTX;W7WE  %|3O"kk33K&FUaLaKbds3  HO/  !>!>?U?UVW?XZeZkZkmr!st %|3O"kk33K&FUaLaKbds3  HO/  !>!>?U?UVW?XZeZkZkmr!stA D 	,!!-0		%223"r   c                     / U l         g rV   r   r*   s    r   clear_collected_data%MinMaxCalibrater.clear_collected_data   
    $&!r   r   c                 ,    UR                  5       nU(       d  O7U R                  R                  U R                  R	                  S U5      5        MO  [        U R                  5      S:X  a  [        S5      eU R                  5         U R                  5         g )Nr   No data is collected.)	r   r   r   rB   runri   r=   r   r   )r+   r   inputss      r   r   MinMaxCalibrater.collect_data   s~     ))+F%%,,T-?-?-C-CD&-QR	  t(()Q.455!!#r   c                     U(       d  U$ UR                  5        H2  u  p4[        US   X#   S   5      n[        US   X#   S   5      nXV4X#'   M4     U$ )Nr   r	   )itemsminmax)r+   	old_range	new_rangekeyr   	min_value	max_values          r   merge_rangeMinMaxCalibrater.merge_range   s^    #//+JCE!HinQ&78IE!HinQ&78I'3IN ,
 r   c           	        ^ ^ [        T R                  5      S:X  a  T R                  $ [        [        T R                  S   5      5       Vs/ s H*  nT R                  R                  5       U   R                  PM,     nnT R                   Vs/ s H  n[        [        X#5      5      PM     nn0 mU H=  nUR                  5        H&  u  pgTR                  U/ 5      R                  U5        M(     M?     UT R                  S n[        S[        U5      S5       Vs/ s H  oU   R                  S5      S   PM     n	n[        UU 4S jT 5       5      n
/ n[        S[        U5      S5       H  nSnSn[        XU      5      n[        XUS-         5      n[!        U5      ["        :X  d  UR$                  S:  a  ['        U5      n[!        U5      ["        :X  d  UR$                  S:  a  ['        U5      nUR                  [)        X/5      5        M     [        [        X5      5      nT R                  (       a-  T R+                  T R                  U5      T l        T R                  $ UT l        T R                  $ s  snf s  snf s  snf )t
Compute the min-max range of tensor
:return: dictionary mapping: {added node names: (ReduceMin, ReduceMax) pairs }
r   N   _c              3   T   >#    U  H  oTR                   ;  d  M  UTU   4v   M     g 7frV   r   )rY   r   merged_output_dictr+   s     r   r[   1MinMaxCalibrater.compute_range.<locals>.<genexpr>   s/      (l0B1tOjOjFj&Q"1%&0B   ((r	   )ri   r   r   r   rB   get_outputsrX   r0   zipr   
setdefaultr   r   
rpartitionr   r   rn   intsizefloattupler   )r+   r   output_namesintermediate_outputoutput_dicts_listr   kvadded_output_namescalibrate_tensor_namesmerged_added_output_dictpairsr   r   min_value_arraymax_value_arraynew_calibrate_tensors_ranger   s   `                @r   r   MinMaxCalibrater.compute_range   sk    t(()Q.///JOPSTXTmTmnoTpPqJrsJrQ**668;@@JrsTXTmTm
Tm=PD\78Tm 	 
  "A	"--a4;;A> " # *$*@*@*AB>CAsK]G^`a>b"
>bq!,,S1!4>b 	 "
 $( (l0B(l $l  q#0115AII!":a;P"QRO!":aRSe;T"UVOO$+/C/Ca/G!/2	O$+/C/Ca/G!/2	LL	567 6 '+3/E+M&N#''+/+;+;D<X<XZu+vD( +++ ,GD(+++I t
"
s   1I2I7 I<)r@   r   r   r   r   )r   r   r   r   rE   rA   r   r   r   r   r   r   __classcell__r   s   @r   r   r      s6    46Mc 
]3#j'$(= $	-, -,r   r   c                   P   ^  \ rS rSr/ S4U 4S jjrS rS rS\4S jrS r	S	r
U =r$ )
EntropyCalibrateri  r5   c                   > [         [        U ]  XU5        / U l        SU l        [        U R                  R                  R                  5      U l	        [        S U R                  R                  R                   5       5      U l        SU l        g)r7   Nc              3   8   #    U  H  oR                   v   M     g 7frV   rW   r   s     r   r[   -EntropyCalibrater.__init__.<locals>.<genexpr>!  r   r]   )r   r   rE   r   r   ri   r<   r_   rb   r   rd   r   	collectorr   s       r   rE   EntropyCalibrater.__init__  so     	/Nbc$&!'+$!$TZZ%5%5%<%<!=&))\DJJDTDTD[D[)\&\#r   c                    [         R                  " 5       nUR                  U R                  5        [        R
                  R                  U5      n/ n/ nU R                  U5      u  pEU H  nUR                  XV   5        M     UR                  R                  R                  U5        UR                  R                  R                  U5        [        R                  " XR                  5        Xl        g)zk
make all quantization_candidates op type nodes as part of the graph output.
:return: augmented ONNX model
N)r   r   r   r<   r:   r   r   ry   r   r_   rh   r   rb   r   r?   r@   )r+   r<   r   r   r   rs   r   s          r   rA   EntropyCalibrater.augment_graph$  s    
 %%'tzz"$$11%8#??FF  !45  	,!!-0		%223"r   c                     / U l         g rV   r   r*   s    r   r   &EntropyCalibrater.clear_collected_data9  r   r   r   c           	      X  ^ ^  UR                  5       nU(       d  O7T R                  R                  T R                  R	                  SU5      5        MO  [        T R                  5      S:X  a  [        S5      e[        [        T R                  S   5      5       Vs/ s H*  nT R                  R                  5       U   R                  PM,     nnT R                   Vs/ s H  n[        [        XE5      5      PM     nn0 mU H=  nUR                  5        H&  u  pTR                  U/ 5      R                  U	5        M(     M?     [        UU 4S jT 5       5      n
T R                  (       d  [        5       T l        T R                  R!                  U
5        T R#                  5         gs  snf s  snf )zj
Entropy Calibrator collects operators' tensors as well as generates tensor histogram for each operator. 
Nr   r   c              3   T   >#    U  H  oTR                   ;  d  M  UTU   4v   M     g 7frV   r   )rY   r   merged_dictr+   s     r   r[   1EntropyCalibrater.collect_data.<locals>.<genexpr>T  s)      rkVZVqVqMq!4![^!4kr   )r   r   r   rB   r   ri   r=   r   r   rX   r0   r   r   r   r   HistogramCollectorcollectr   )r+   r   r   r   r   r   r   r   r   r   clean_merged_dictr   s   `          @r   r   EntropyCalibrater.collect_data<  sk     ))+F%%,,T-?-?-C-CD&-QR	  t(()Q.455JOPSTXTmTmnoTpPqJrsJrQ**668;@@JrsTXTmTm
Tm=PD\78Tm 	 
 "A	&&q"-44Q7 " # ! rk rr~~/1DN01!!#! t
s   1F"F'c                 n    U R                   (       d  [        S5      eU R                   R                  5       $ )r   z9No collector created and can't generate calibration data.)r   r=   get_optimal_collection_resultr*   s    r   r   EntropyCalibrater.compute_range\  s*    
 ~~XYY~~;;==r   )r@   r   r   r   r   r   )r   r   r   r   rE   rA   r   r   r   r   r   r   r   s   @r   r   r     s0    46Mc #*'$(= $@> >r   r   c                   `    \ rS rSrSr\R                  S 5       r\R                  S 5       rSr	g)CalibrationDataCollectorig  zD
Base class for collecting data for calibration-based quantization.
c                     [         e)zm
Generate informative data based on given data.
    name_to_arr : dict 
        tensor name to NDArray data 
r(   )r+   name_to_arrs     r   r   CalibrationDataCollector.collectl  s
     "!r   c                     [         e)z1
Get the optimal result among collection data.  
r(   r*   s    r   r  6CalibrationDataCollector.get_optimal_collection_resultu  s
    
 "!r   r   N)
r   r   r   r   __doc__r.   r/   r  r  r   r   r   r   r  r  g  s;     	" " 	" "r   r  c                   @    \ rS rSrSrSS jrS rS rS rS r	S r
S	rg
)r   i|  z
Implementation of collecting histogram data as dict for each tensor targeting on entropy calibration.

ref: https://github.com//apache/incubator-mxnet/blob/master/python/mxnet/contrib/quantization.py
c                     0 U l         Xl        g rV   histogram_dictnum_quantized_bins)r+   r  s     r   rE   HistogramCollector.__init__  s     !3r   c                     U R                   $ rV   )r  r*   s    r   get_histogram_dict%HistogramCollector.get_histogram_dict  s    """r   c                 0   UR                  5        GH  u  p#[        R                  " U5      nUR                  5       nUR                  S:  a-  [        R
                  " U5      n[        R                  " U5      nOSnSn[        [        U5      [        U5      5      nX R                  ;   a1  U R                  U   nU R                  XsXEU5      U R                  U'   M  [        R                  " X0R                  U* U4S9u  pXXEU4U R                  U'   GM     g )Nr   r   )r   npasarrayflattenr   r   r   absr  merge_histogram	histogramr  )
r+   r
  r   data_arrr   r   	thresholdold_histogramhist
hist_edgess
             r   r  HistogramCollector.collect  s     + 1 1 3Fzz(+H'')H}}q FF8,	FF8,			C	NC	N;I,,, $ 3 3F ;.2.B.B=\er{.|##F+ $&<<:Q:Q[dZdfoYp#q /3W`.a##F+' !4r   c                    Uu  pgpn
XZ::  a?  [         R                  " U[        U5      U
* U
4S9u  pX-   U[        X5      [	        X5      U
4$ U
S:X  a>  [         R                  " UWU* U4S9u  pU[        U5      S-  ==   [        U5      -  ss'   Oa[        U5      nSU
-  U-  n[        XZ-
  U-  S-   5      nUSU-  -   nUU-  U
-   n[         R                  " X-U* U4S9u  pUUUU-
  === U-  sss& X[        X5      [	        X5      U4$ )Nr  r   r   r	   )r  r  ri   r   r   r   )r+   r"  r   new_minnew_maxnew_thresholdold_histold_hist_edgesold_minold_maxold_thresholdnew_histr   new_num_binsr#  r$  old_num_bins
old_stridehalf_increased_binss                      r   r  "HistogramCollector.merge_histogram  s6   FSC7]),,xX~WdFefKH'W9NPST[Pegtuu!#%<<,P]~_lNm#n SY!^$H5$"8}.=
&)=+HZ*WZ[*[&\#+a2E.EE 3j @= P#%<<P]~_lNm#n (6I)IJhVJc'&;S=RTabbr   c                     U R                   nU R                  n0 nUR                  5        H  u  pEU R                  XR5      nXcU'   M     U$ rV   )r  r  r   get_optimal_threshold)r+   r  r  thresholds_dictr   r  optimal_thresholds          r   r  0HistogramCollector.get_optimal_collection_result  sU    ,,!44!/!5!5!7F $ : :9 Y&7F# "8 r   c           	      @   SSK Jn  SS KnUu  pV    nUR                  nUS-  n	US-  n
[        R
                  " X-
  S-   5      n[        UR                  5       Vs/ s H  nSPM     nn[        XS-   S5       GH  nX-
  nX-   S-   U::  a  X-   S-   OUn[        Xn   5      [        Xo   5      4XU
-
  '   UR                  X^U 5      nUR                  5       n[        US U 5      n[        X_S  5      nUS==   U-  ss'   US==   U-  ss'   US:g  R                  [        R                  5      n[        R
                  " U[        R                  S9nUR                  U-  n[        U5       H  nUU-  nUU-   n[        UUU 5      UU'   M      US==   [        UUU-  S  5      -  ss'   [        R
                  " UR                  [        R                  S9n[        U5       H@  nUU-  nUU-   n[        UUU 5      nUS:w  d  M#  [        UU   5      [        U5      -  UUU& MB     [        U5      n[        U5      n[        U[        R                  5      (       a  U" UU5      XU
-
  '   GM  [        S5      XU
-
  '   GM     [        R                  " U5      nUU   nU$ s  snf )	Nr   )entropyr   r	   )r   r   )dtypeinf)scipy.statsr;  copyr   r  zerosr   r   deepcopysumastypeint64r   r9   ndarrayargmin)r+   r  r  r;  r@  r#  r$  r   num_binszero_bin_indexnum_half_quantized_binkl_divergencer   
thresholdsstart_index	end_indexsliced_distributionpleft_outliers_countright_outliers_countnonzerosquantized_binsnum_merged_binsindexstartendqnormmin_kl_divergence_idxr8  s                                 r   r6  (HistogramCollector.get_optimal_threshold  s   '$-!!Q99!Q!3q!8!H1!LM&+M,>,>&?@&?f&?
@-/A1EA(,K3A3E3Ih2V*Q.\dI6;J<S6TV[\f\qVr5sJ112"&--0K"L $((*A"%d<K&8"9#&tJ'7#8 aD''DbE))E Qrxx0H  XX&8IN166:LLO 12/o-(+,?c,J(Ku% 3 2#&9:L:^:_&`"aa rxx0A12/o-8E#./19#()>#?%+#MAeCL 3 $A&A#A&A!RZZ((<CAqM"889<A%L"889] F` !#		- 8&'<=  k As   Jr  N)   )r   r   r   r   r  rE   r  r  r  r  r6  r   r   r   r   r   r   |  s'    
4#b,c*
?!r   r   r5   c                     U[         R                  :X  a  [        XU5      $ U[         R                  :X  a  [	        XU5      $ [        SR                  U5      5      e)Nz!Unsupported calibration method {})r   r   r   r   r   r=   format)r<   r>   r?   calibrate_methods       r   create_calibratorra    sV     ,333>RSS	.66	6 ?STT
8??@PQ
RRr   )osnumpyr  r:   rM   r   r   r   r   r   sixr   enumr   quant_utilsr
   r   registryr   r.   rk   r   ABCMetar   r3   r   r   r  r   r   ra  r   r   r   <module>ri     s    
    0 0 &   7 ( 
  
"ckk "^" ^"BJ,~ J,XN> N>b" "*C!1 C!N -/+A'8'?'?	Sr   