U
    <c0                     @   s   d dl Z d dlmZ d dlm  m  mZ d dlm  mZ	 d dlm
Z
 d dlmZ d dlmZ G dd dejjjejZdS )    N)init)	Parameter)fuse_linear_bn_weightsc                       sp   e Zd ZdZdddZd	d
 Zdd Z fddZdd Zdd Z	dd Z
dddZedd Zdd Z  ZS )
LinearBn1da  
    A LinearBn1d module is a module fused from Linear and BatchNorm1d, attached
    with FakeQuantize modules for weight, used in quantization aware training.

    We combined the interface of :class:`torch.nn.Linear` and
    :class:torch.nn.BatchNorm1d`.

    Similar to :class:`torch.nn.Linear`, with FakeQuantize modules initialized
    to default.

    Attributes:
        freeze_bn:
        weight_fake_quant: fake quant module for weight

    Th㈵>皙?FNc                 C   s   t jjj| ||| |s"td|| _| jr2|nd| _t 	|||dd| _
| j | _|rntt|| _n| dd  |   | jr|r|   q|   n|   d S )Nz&qconfig must be provded for QAT moduleTbias)nnmoduleslinearLinear__init__AssertionErrorqconfigtraining	freeze_bnZBatchNorm1dbnweightweight_fake_quantr   torchemptyr   Zregister_parameterreset_bn_parametersfreeze_bn_statsupdate_bn_stats)selfin_featuresout_featuresr   epsmomentumr   r    r   O/tmp/pip-unpacked-wheel-gikjz4vx/torch/nn/intrinsic/qat/modules/linear_fused.pyr      s    

zLinearBn1d.__init__c                 C   s   | j   d S N)r   reset_running_statsr   r   r   r    r"   ;   s    zLinearBn1d.reset_running_statsc                 C   s*   | j   t| j j t| j j d S r!   )r   r"   r   Zuniform_r   Zzeros_r   r#   r   r   r    r   >   s    
zLinearBn1d.reset_bn_parametersc                    s   t t|   d S r!   )superr   reset_parametersr#   	__class__r   r    r%   C   s    zLinearBn1d.reset_parametersc                 C   s   d| _ d| j_| S )NFTr   r   r   r#   r   r   r    r   F   s    zLinearBn1d.update_bn_statsc                 C   s   d| _ d| j_| S )NTFr(   r#   r   r   r    r   K   s    zLinearBn1d.freeze_bn_statsc                 C   s   | j jd k	stt| j j| j j }| j j| }dgt| jj }d|d< dgt| jj }d|d< | 	| j|
| }| jd k	rt| j}ntj| j|jd}t|||}||
| }	| jd k	r|	| j
| }	|  |	}
|
S )N   r   )device)r   running_varr   r   sqrtr   r   lenshaper   Zreshaper   Z
zeros_likezerosr   r+   Fr   )r   inputZrunning_stdZscale_factorZweight_shapeZ
bias_shapeZscaled_weightZ	zero_biasZ
linear_outZlinear_out_origZbn_outr   r   r    forwardP   s"    


zLinearBn1d.forwardc                 C   s(   || _ | js$|  D ]}|| q| S )z
        Batchnorm's training behavior is using the self.training flag. Prevent
        changing it if BN is frozen. This makes sure that calling `model.train()`
        on a model with a frozen BN will behave properly.
        )r   r   childrentrain)r   modemoduler   r   r    r5   x   s
    zLinearBn1d.trainc                 C   s   t |tjks(td| j d tjj t|ds:td|jsHtd|j}|d |d  }}| |j|j|j	dk	|j
|jd	|}|j|_|j	|_	|j|j_|j	|j_	|j|j_|j|j_|j|j_|S )
zCreate a qat module from a float module or qparams_dict

            Args: `mod' a float module, either produced by torch.ao.quantization
            utilities or directly from user
        zqat.z.from_float only works for r   z,Input float module must have qconfig definedz+Input float module must have a valid configr   r)   NF)typennir   r   __name__hasattrr   r   r   r   r   r   r   r   running_meanr,   Znum_batches_tracked)clsmodr   r   r   Zqat_linearbnr   r   r    
from_float   s.      




zLinearBn1d.from_floatc                 C   sJ   t j| j| j}t| j| j| jj	| jj
| jj| jj| jj\|_|_|S r!   )r   r	   r   r   r   r   r   r   r   r<   r,   r   )r   r   r   r   r    to_float   s    zLinearBn1d.to_float)Tr   r   FN)T)r:   
__module____qualname____doc__r   r"   r   r%   r   r   r3   r5   classmethodr?   r@   __classcell__r   r   r&   r    r   
   s"         
!(

r   )r   Ztorch.nnr	   Ztorch.ao.nn.intrinsicZaoZ	intrinsicr9   Ztorch.nn.functionalZ
functionalr1   r   Ztorch.nn.parameterr   Ztorch.nn.utils.fusionr   r
   r   r   Z_FusedModuler   r   r   r   r    <module>   s   