U
    Kcm                     @   s   d dl Z d dlmZ d dlm  m  mZ d dlZ d dlm  m	  m
Z	 ejejhZejejhZdd Zdd Zdd ZG dd	 d	e	jZedfd
dZdS )    Nc                 C   s   t |  | S )zQ Given name of submodule, this function grabs the submodule from given model
    )dictnamed_modules)modelname r   G/tmp/pip-unpacked-wheel-gikjz4vx/torch/ao/quantization/_correct_bias.py
get_module   s    r   c                 C   s8   |  dd}t|dkr$d|d fS |d |d fS dS )zYSplits full name of submodule into parent submodule's full name and submodule's name
    .    r   N)rsplitlen)r   Z
split_namer   r   r   parent_child_names   s    r   c                 C   s"   t | |d}t|r| S |S dS )z Sometimes the weights/bias attribute gives you the raw tensor, but sometimes
    gives a function that will give you the raw tensor, this function takes care of that logic
    N)getattrcallable)moduleattrparamr   r   r   	get_param   s    r   c                       s0   e Zd ZdZ fddZdd Zdd Z  ZS )MeanShadowLoggerzA logger for a Shadow module whose purpose is to record the rolling mean
    of the data passed to the floating point and quantized models
    c                    s8   t t|   d | jd< d | jd< d| _d | _d | _d S Nfloat	quantizedr   )superr   __init__statscount	float_sum	quant_sumself	__class__r   r   r   '   s    

zMeanShadowLogger.__init__c                 C   s   |j r| }|  jd7  _| jd dkr<|| jd< || _n |  j|7  _| j| j | jd< | jd dkr||| jd< || _n |  j|7  _| j| j | jd< dS )z The inputs x,y are output data from the quantized and floating-point modules.
        x is for the quantized module, y is for the floating point module
        r
   r   Nr   )Zis_quantizedZ
dequantizer   r   r   r   )r    xyr   r   r   forward/   s    

zMeanShadowLogger.forwardc                 C   s*   d | j d< d | j d< d| _d | _d | _d S r   )r   r   r   r   r   r   r   r   clearE   s
    

zMeanShadowLogger.clear)__name__
__module____qualname____doc__r   r%   r&   __classcell__r   r   r!   r   r   #   s   r   c                 C   s.  t | |tt i }| D ]\}}t||kr|||< q|D ]}t||}	t|	d}
|
dk	r>d}|D ]$}||d  |d7 }||krf qqft |}t	|\}}||d  d }||d  d }|| }t
t| }|d t||}|
j| }||
_| D ]\}}t|tr|  qq>dS )ah   Using numeric suite shadow module, the expected output of the floating point and quantized modules
    is recorded. Using that data the bias of supported modules is shifted to compensate for the drift caused
    by quantization
    Paper reference: https://arxiv.org/pdf/1906.04721.pdf (Section 4.2)

    Args:
        float_model: a trained model that serves as a reference to what bias correction should aim for
        quantized_model: quantized form of float_model that bias correction is to applied to
        img_data: calibration data to estimate the expected output (used to find quantization error)
        target_modules: specifies what submodules in quantized_model need bias correction (can be extended to
                unquantized submodules)
        neval_batches: a cap to the number of batches you want to be used for estimating the expected output
    biasNr   r
   z.statsr   r   )nsZprepare_model_with_stubs_supported_modulesr   r   typer   r   Zget_logger_dictr   listrangeZdimremovetorchZmeandata
isinstancer&   )Zfloat_modelZquantized_modelZimg_dataZtarget_modulesZneval_batchesZuncorrected_modulesr   	submoduleZuncorrected_moduleZquantized_submoduler,   r   r4   Zob_dictparent_name_Z
float_dataZ
quant_dataZquantization_errorZdimsZexpected_errorZupdated_biasr   r   r   bias_correctionL   s8    





r9   )r3   Ztorch.nnnnZtorch.ao.nn.quantizedZaor   ZnnqZtorch.ao.quantizationZtorch.ao.ns._numeric_suiter-   Z_numeric_suiteZLinearZConv2dr.   Z_supported_modules_quantizedr   r   r   Loggerr   r9   r   r   r   r   <module>   s   	
)