
    |jJ                    P   U d dl mZ d dlZd dlmZ d dlZd dlmZ ddlmZ erd dl	m
Z
 ddlmZ ej        j        ej        j        j        ej        ej        j        j        ej        ej        j        j        iZd	ed
<   ej        ej        gZ G d d          Z G d d          ZdS )    )annotationsN)TYPE_CHECKING)nn   )ObserveWrapper)Layer)QuanterFactorydict[Layer, Layer]DEFAULT_QAT_LAYER_MAPPINGSc                  P    e Zd ZdZddZedd            Zedd	            Zd
 ZdS )SingleLayerConfiga-  
    Configure how to quantize the activations and weights of a single layer.

    Args:
        activation(QuanterFactory): The factory to create instance of quanter used to quantize activations.
        weight(QuanterFactory): The factory to create instance of quanter used to quantize weights.
    
activationr	   weightreturnNonec                "    || _         || _        d S N_activation_weightselfr   r   s      j/lsinfo/ai/hellotax_ai/data_center/backend/venv/lib/python3.11/site-packages/paddle/quantization/config.py__init__zSingleLayerConfig.__init__1   s     &    c                    | j         S r   )r   r   s    r   r   zSingleLayerConfig.activation7   s    r   c                    | j         S r   )r   r   s    r   r   zSingleLayerConfig.weight;   s
    |r   c                &    d| j          d| j         S )Nzactivation: z	
weight: r   r   s    r   __str__zSingleLayerConfig.__str__?   s    Hd.HH$,HHHr   N)r   r	   r   r	   r   r   )r   r	   )	__name__
__module____qualname____doc__r   propertyr   r   r     r   r   r   r   (   s                   X     XI I I I Ir   r   c                  8   e Zd ZdZd2dZ	 	 d3d4dZ	 	 d3d5dZ	 	 d3d6dZd7dZd8dZ	e
d9d            Zd:dZd:dZd:dZd:dZd:dZd:dZd:d Zd:d!Zd:d"Ze
d;d$            Ze
d;d%            Ze
d<d'            Zd<d(Zd:d)Zd=d+Zd=d,Zd>d.Zd:d/Zd0 Zd1 ZdS )?QuantConfiga  
    Configure how to quantize a model or a part of the model. It will map each layer to
    an instance of SingleLayerConfig by the settings. It provides diverse methods to set
    the strategies of quantization.

    Args:
        activation(QuanterFactory | None): The global quantizer used to quantize the activations.
        weight(QuanterFactory | None): The global quantizer used to quantize the weights.

    Examples:
        .. code-block:: python

            >>> from paddle.quantization import QuantConfig
            >>> from paddle.quantization.quanters import FakeQuanterWithAbsMaxObserver

            >>> quanter = FakeQuanterWithAbsMaxObserver(moving_rate=0.9)
            >>> q_config = QuantConfig(activation=quanter, weight=quanter)
            >>> print(q_config)
            Global config:
            activation: FakeQuanterWithAbsMaxObserver(name=None,moving_rate=0.9,bit_length=8,dtype=float32)
            weight: FakeQuanterWithAbsMaxObserver(name=None,moving_rate=0.9,bit_length=8,dtype=float32)

    r   QuanterFactory | Noner   r   r   c                    |
|d | _         nt          ||          | _         i | _        i | _        i | _        d | _        t          j        t                    | _	        i | _
        g | _        d S r   )_global_configr   _layer2config_prefix2config_type2config_modelcopydeepcopyr   _qat_layer_mapping_customized_qat_layer_mapping_customized_leavesr   s      r   r   zQuantConfig.__init__\   ss     &."&D"3J"G"GD "&-0J"K"K-/*"$r   NlayerLayer | list[Layer]c                    t          |t                    r|D ]}|                     |||           dS |                     |                                ||           dS )a  
        Set the quantization config by layer. It has the highest priority among
        all the setting methods.

        Args:
            layer(Layer|list[Layer]]): One or a list of layers.
            activation(QuanterFactory | None): Quanter used for activations. Default is None.
            weight(QuanterFactory | None): Quanter used for weights. Default is None.

        Examples:
            .. code-block:: python

                >>> import paddle
                >>> from paddle.nn import Linear
                >>> from paddle.quantization import QuantConfig
                >>> from paddle.quantization.quanters import FakeQuanterWithAbsMaxObserver

                >>> class Model(paddle.nn.Layer):
                ...    def __init__(self):
                ...        super().__init__()
                ...        self.fc = Linear(576, 120)
                >>> model = Model()
                >>> quanter = FakeQuanterWithAbsMaxObserver(moving_rate=0.9)
                >>> q_config = QuantConfig(activation=None, weight=None)
                >>> q_config.add_layer_config([model.fc], activation=quanter, weight=quanter)
                >>> # doctest: +SKIP('random memory address')
                >>> print(q_config)
                Global config:
                None
                Layer prefix config:
                {'linear_0': <paddle.quantization.config.SingleLayerConfig object at 0x7fe41a680ee0>}

        r   r   N)
isinstancelistadd_layer_configadd_name_config	full_name)r   r5   r   r   _elements        r   r;   zQuantConfig.add_layer_configl   s    N eT"" 	!  %%F &     
   !!j !     r   
layer_namestr | list[str]c                    t          |t                    rt          ||          }|| j        |<   t          |t                    r|D ]}|                     |||           dS dS )a  
        Set the quantization config by full name of layer. Its priority is
        lower than `add_layer_config`.

        Args:
            layer_name(str|list[str]): One or a list of layers' full name.
            activation(QuanterFactory | None): Quanter used for activations. Default is None.
            weight(QuanterFactory | None): Quanter used for weights. Default is None.

        Examples:
            .. code-block:: python

                >>> import paddle
                >>> from paddle.nn import Linear
                >>> from paddle.quantization import QuantConfig
                >>> from paddle.quantization.quanters import FakeQuanterWithAbsMaxObserver

                >>> class Model(paddle.nn.Layer):
                ...     def __init__(self):
                ...         super().__init__()
                ...         self.fc = Linear(576, 120)
                >>> model = Model()
                >>> quanter = FakeQuanterWithAbsMaxObserver(moving_rate=0.9)
                >>> q_config = QuantConfig(activation=None, weight=None)
                >>> q_config.add_name_config([model.fc.full_name()], activation=quanter, weight=quanter)
                >>> # doctest: +SKIP('random memory address')
                >>> print(q_config)
                Global config:
                None
                Layer prefix config:
                {'linear_0': <paddle.quantization.config.SingleLayerConfig object at 0x7fe41a680fd0>}

        r8   N)r9   strr   r-   r:   r<   )r   r?   r   r   configr>   s         r   r<   zQuantConfig.add_name_config   s    N j#&& 	5&z6::F.4D
+j$'' 	&  $$F %    	 	 r   
layer_typetype[Layer] | list[type[Layer]]c                
   t          |t                    r9t          |t          j        j                  rt          ||          }|| j        |<   t          |t                    r|D ]}| 	                    |||           dS dS )a  
        Set the quantization config by the type of layer. The `layer_type` should be
        subclass of `paddle.nn.Layer`. Its priority is lower than `add_layer_config`
        and `add_name_config`.

        Args:
            layer_type(type[Layer] | list[type[Layer]]): One or a list of layers' type. It should be subclass of
            `paddle.nn.Layer`. Python built-in function `type()` can be used to get the type of a layer.
            activation(QuanterFactory | None): Quanter used for activations. Default is None.
            weight(QuanterFactory | None): Quanter used for weights. Default is None.

        Examples:
            .. code-block:: pycon

                >>> import paddle
                >>> from paddle.nn import Linear
                >>> from paddle.quantization import QuantConfig
                >>> from paddle.quantization.quanters import (
                ...     FakeQuanterWithAbsMaxObserver,
                ... )

                >>> class Model(paddle.nn.Layer):
                ...     def __init__(self):
                ...         super().__init__()
                ...         self.fc = Linear(576, 120)
                >>> model = Model()
                >>> quanter = FakeQuanterWithAbsMaxObserver(moving_rate=0.9)
                >>> q_config = QuantConfig(activation=None, weight=None)
                >>> q_config.add_type_config([Linear], activation=quanter, weight=quanter)
                >>> # doctest: +SKIP('random memory address')
                >>> print(q_config)
                Global config:
                None
                Layer type config:
                {<class 'paddle.nn.layer.common.Linear'>: <paddle.quantization.config.SingleLayerConfig object at 0x7fe41a680a60>}

        r8   N)
r9   type
issubclasspaddler   r   r   r.   r:   add_type_config)r   rD   r   r   rC   r>   s         r   rJ   zQuantConfig.add_type_config   s    V j$'' 	3J	-
 -
 	3 'z6::F,2Dj)j$'' 	&  $$F %    	 	 r   sourcetype[Layer]targetc                &   t          |t                    rt          |t          j        j                  s
J d            t          |t                    rt          |t          j        j                  s
J d            || j        |<   || j        |<   dS )a(  
        Add rules converting layers to simulated quantization layers
        before quantization-aware training. It will convert layers
        with type `source` to layers with type `target`. `source` and
        `target` should be subclass of `paddle.nn.Layer`. And a default
        mapping is provided by property `default_qat_layer_mapping`.

        Args:
            source(type[Layer]): The type of layers that will be converted.
            target(type[Layer]): The type of layers that will be converted to.

        Examples:
            .. code-block:: pycon

                >>> import paddle
                >>> from paddle.nn import Conv2D
                >>> from paddle.quantization import QuantConfig
                >>> from paddle.quantization.quanters import (
                ...     FakeQuanterWithAbsMaxObserver,
                ... )
                >>> quanter = FakeQuanterWithAbsMaxObserver(moving_rate=0.9)
                >>> q_config = QuantConfig(activation=None, weight=None)
                >>> class CustomizedQuantedConv2D(paddle.nn.Layer):
                ...     def forward(self, x):
                ...         pass
                ...         # add some code for quantization simulation
                >>> q_config.add_qat_layer_mapping(Conv2D, CustomizedQuantedConv2D)
        zEThe source layer to be placed should be a subclass of paddle.nn.Layerz<The target layer should be a subclass of paddle.nn.qat.LayerN)r9   rG   rH   rI   r   r   r2   r3   )r   rK   rM   s      r   add_qat_layer_mappingz!QuantConfig.add_qat_layer_mapping  s    > &$'' 	
JFIO-
 -
 	
 	
 T	
 	
 

 &$'' 	JJFIO-
 -
 	J 	JI	J 	J 
 +1'5;*6222r   c                :    | j                             |           dS )a  
        Declare the customized layer as leaf of model for quantization.
        The leaf layer is quantized as one layer. The sublayers of
        leaf layer will not be quantized.

        Args:
            layer_type(type[Layer]): The type of layer to be declared as leaf.

        Examples:
            .. code-block:: python

                >>> from paddle.nn import Sequential
                >>> from paddle.quantization import QuantConfig
                >>> from paddle.quantization.quanters import FakeQuanterWithAbsMaxObserver
                >>> q_config = QuantConfig(activation=None, weight=None)
                >>> q_config.add_customized_leaf(Sequential)

        N)r4   append)r   rD   s     r   add_customized_leafzQuantConfig.add_customized_leaf-  s!    & 	&&z22222r   list[type[Layer]]c                    | j         S )z0
        Get all the customized leaves.
        )r4   r   s    r   customized_leaveszQuantConfig.customized_leavesB  s    
 &&r   r   c                V    |                      |          o|                     |          S )zC
        Whether the layer should be observed by observer.
        )_is_leaf_has_observer_configr   r5   s     r   _need_observezQuantConfig._need_observeI  s)     }}U##H(A(A%(H(HHr   c                    |                      |          }| j                            t          |          | j                            t          |                              } |||          S r   )_get_config_by_layerr3   getrG   qat_layer_mappings)r   r5   q_configtarget_types       r   _get_qat_layerzQuantConfig._get_qat_layerO  sc    ,,U338<<KK044T%[[AA
 
 {5(+++r   c                F    |                      |          }|duo|j        duS )zT
        Whether the layer has been configured for activation quantization.
        N)r\   r   )r   r5   _configs      r   rX   z QuantConfig._has_observer_configW  s/     ++E22d"Ew'9'EEr   c                    |                      |          p)|                     |          p|                     |          S r   )_is_default_leaf_is_real_leaf_is_customized_leafrY   s     r   rW   zQuantConfig._is_leaf^  sD    !!%(( /!!%((/''..	
r   c                .    t          |          t          v S r   )rG   DEFAULT_LEAVESrY   s     r   re   zQuantConfig._is_default_leafe  s    E{{n,,r   c                D    |j         du pt          |j                   dk    S )zA
        The leaf is real leaf when it has no sublayers.
        Nr   )_sub_layerslenrY   s     r   rf   zQuantConfig._is_real_leafh  s'      D(GC0A,B,Ba,GGr   c                .    t          |          | j        v S r   )rG   rU   rY   s     r   rg   zQuantConfig._is_customized_leafn  s    E{{d444r   c                t    |                      |          }|dn|j        }|dn|                    |          S )zw
        Create an instance of observer or quanter according to the
        given layer's quantization config.
        N)r\   r   	_instance)r   r5   rc   	_observers       r   _get_observerzQuantConfig._get_observerq  sD    
 ++E22#ODD1C	 (tti.A.A%.H.HHr   c                L    |                      |          }t          ||          S r   )rq   r   )r   r5   rp   s      r   _get_observe_wrapperz QuantConfig._get_observe_wrapperz  s%    &&u--	i///r   r
   c                    | j         S r   )r2   r   s    r   r^   zQuantConfig.qat_layer_mappings~  s    &&r   c                    t           S r   )r   r   s    r   default_qat_layer_mappingz%QuantConfig.default_qat_layer_mapping  s    ))r   r   c                    | j         S r   )r+   r   s    r   global_configzQuantConfig.global_config  s    ""r   c                8    | j                             |d           S r   )r,   r]   rY   s     r   r\   z QuantConfig._get_config_by_layer  s    !%%eT222r   c                    || j         v S )z
        The layer is quantifiable when it configured by activation quanter/observer
        or weight quanter/observer.
        )r,   rY   s     r   _is_quantifiablezQuantConfig._is_quantifiable  s    
 ***r   modelc                H    || _         |                     | j                    dS )aA  
        Specify the quantization config of each sublayer in model.
        For each layer in sublayers of mode,
        1. Set the config by global config
        2. Overwrite the config with parents' config
        3. Overwrite the config with config set by layer's type
        4. Overwrite the config with config set by layer's full name
        5. Overwrite the config with config set by layer

        Args:
            model(Layer): The model to be specified by the config.

        Examples:
            .. code-block:: python

                >>> import paddle
                >>> from paddle.nn import Linear, Sequential
                >>> from paddle.quantization import QuantConfig
                >>> from paddle.quantization.quanters import FakeQuanterWithAbsMaxObserver

                >>> class Model(paddle.nn.Layer):
                ...     def __init__(self):
                ...         super().__init__()
                ...         self.fc = Sequential(Linear(576, 120),Linear(576, 120))
                >>> model = Model()
                >>> quanter = FakeQuanterWithAbsMaxObserver(moving_rate=0.9)
                >>> q_config = QuantConfig(activation=None, weight=None)
                >>> q_config.add_layer_config([model.fc], activation=quanter, weight=quanter)
                >>> q_config._specify(model)
        N)r/   _specify_helper)r   r|   s     r   _specifyzQuantConfig._specify  s'    > T[)))))r   c                d   |                                 D ]}|                                }| j                            || j                  }| j                            t          |          |          }| j                            ||          }|
|| j        |<   |                     |           | S r   )	childrenr=   r,   r]   rx   r.   rG   r-   r~   )r   r|   childlayer_prefixrC   s        r   r~   zQuantConfig._specify_helper  s    ^^%% 	( 	(E ??,,L'++E43EFFF&**4;;??F(,,\6BBF!,2"5)  ''''r   rB   c                l    | j         |                                 S |                     | j                   S )z>
        Get the formatted details of current config.
        )r/   r    _details_helperr   s    r   detailszQuantConfig.details  s0     ;<<>>!##DK000r   c                   g }|                                 D ]u\  }}|                     |          }|                     |d          }|| j        v r<|                    d|z   dz   |z   dz   t          | j        |                   z              v|j        j        dz   }|r|dd                    |          z   dz   z  }|dz  }|S )N   (z): z, z
  
))	named_childrenr   
_addindentr,   rQ   rB   	__class__r!   join)r   r5   sublayer_linesnamesublayersublayer_str	final_strs          r   r   zQuantConfig._details_helper  s    #2244 	 	ND(//99L??<;;L4---%% ## 	
 $,X6778   O,s2	 	E&++n"="==DDIS	r   c                "   |                     d          }t          |          dk    r|S g }t          |          D ]3\  }}|dk    r(|                    t	          |dz  |z                        4|d         dz   d                    |          z   S )Nr   r   r    )splitrl   	enumeraterQ   rB   r   )r   stringindents1s2idxlines          r   r   zQuantConfig._addindent  s    \\$r77a<<M"2 	6 	6ICQww		#v|t344555!ut|diimm++r   c                    d}|d| j          dz  }t          | j                  dk    r|d| j         dz  }t          | j                  dk    r|d| j         dz  }|S )N zGlobal config:
r   r   zLayer type config:
zLayer prefix config: 
)r+   rl   r.   r-   )r   results     r   r    zQuantConfig.__str__  s    <T%8<<<<t !!A%%BT->BBBBFt"##a''G0CGGGGFr   )r   r)   r   r)   r   r   )NN)r5   r6   r   r)   r   r)   r   r   )r?   r@   r   r)   r   r)   r   r   )rD   rE   r   r)   r   r)   r   r   )rK   rL   rM   rL   r   r   )rD   rL   r   r   )r   rS   )r5   r   )r   r
   )r   r   )r|   r   )r   rB   ) r!   r"   r#   r$   r   r;   r<   rJ   rO   rR   r%   rU   rZ   ra   rX   rW   re   rf   rg   rq   rs   r^   rv   rx   r\   r{   r   r~   r   r   r   r    r&   r   r   r(   r(   C   s        0% % % %& -1(,	/ / / / /h -1(,	. . . . .f -1(,	4 4 4 4 4l(< (< (< (<T3 3 3 3* ' ' ' X'I I I I, , , ,F F F F
 
 
 
- - - -H H H H5 5 5 5I I I I0 0 0 0 ' ' ' X' * * * X* # # # X#3 3 3 3+ + + + *  *  *  *D
 
 
 
1 1 1 1   ,, , ,    r   r(   )
__future__r   r0   typingr   rI   r   wrapperr   	paddle.nnr   factoryr	   quantStubstubQuanterStubLinearqatQuantedLinearConv2DQuantedConv2Dr   __annotations__ReLU	AvgPool2Dri   r   r(   r&   r   r   <module>r      sV   # " " " " " "                     # # # # # # (''''''
 HM28=,Irx|)Irx|)2      '2<(I I I I I I I I6n n n n n n n n n nr   