o
    ߥimN                     @   s  d dl Z d dlZd dlZd dlmZ d dlZd dlmZ d dlmZ	 d dl
mZ e dg dZe dg d	Zd
eej ej_d
eej ej_eedrSejZn	G dd dejZG dd dejjZG dd dejZdd Zdd Zdd Zdd Zdd Zd
ddZ G dd dej!Z"G d d! d!ej!Z#d
d"d#Z$G d$d% d%ej%Z&G d&d' d'ej%Z'G d(d) d)e(Z)d*d+ Z*				,	,	-	.d6d/d0Z+d1d2 Z,		.	3	.d7d4d5Z-dS )8    N)partial)nn)
functional)	model_zooGlobalParamswidth_coefficientdepth_coefficient
image_sizedropout_ratenum_classesbatch_norm_momentumbatch_norm_epsilondrop_connect_ratedepth_divisor	min_depthinclude_top	BlockArgs
num_repeatkernel_sizestrideexpand_ratioinput_filtersoutput_filtersse_ratioid_skipNSiLUc                   @      e Zd Zdd ZdS )Swishc                 C   s   |t | S r   )torchsigmoidselfx r&   e/home/ubuntu/.local/lib/python3.10/site-packages/modelscope/models/cv/face_emotion/efficient/utils.pyforward"   s   zSwish.forwardN__name__
__module____qualname__r(   r&   r&   r&   r'   r            r    c                   @   s$   e Zd Zedd Zedd ZdS )SwishImplementationc                 C   s   |t | }| | |S r   )r!   r"   save_for_backward)ctxiresultr&   r&   r'   r(   (   s   
zSwishImplementation.forwardc                 C   s,   | j d }t|}||d|d|     S )Nr      )saved_tensorsr!   r"   )r0   grad_outputr1   	sigmoid_ir&   r&   r'   backward.   s   

zSwishImplementation.backwardN)r*   r+   r,   staticmethodr(   r7   r&   r&   r&   r'   r.   &   s
    
r.   c                   @   r   )MemoryEfficientSwishc                 C   s
   t |S r   )r.   applyr#   r&   r&   r'   r(   7   s   
zMemoryEfficientSwish.forwardNr)   r&   r&   r&   r'   r9   5   r-   r9   c                 C   sd   |j }|s| S |j}|j}| |9 } |p|}t|t| |d  | | }|d|  k r.||7 }t|S )a[  Calculate and round number of filters based on width multiplier.
       Use width_coefficient, depth_divisor and min_depth of global_params.
    Args:
        filters (int): Filters number to be calculated.
        global_params (namedtuple): Global params of the model.
    Returns:
        new_filters: New filters number after calculating.
       g?)r   r   r   maxint)filtersglobal_params
multiplierdivisorr   new_filtersr&   r&   r'   round_filters;   s   	rC   c                 C   s    |j }|s| S tt||  S )a>  Calculate module's repeat number of a block based on depth multiplier.
       Use depth_coefficient of global_params.
    Args:
        repeats (int): num_repeat to be calculated.
        global_params (namedtuple): Global params of the model.
    Returns:
        new repeat: New repeat number after calculating.
    )r	   r=   mathceil)repeatsr?   r@   r&   r&   r'   round_repeatsS   s   	rG   c                 C   s|   d|  krdksJ d J d|s| S | j d }d| }|}|tj|dddg| j| jd7 }t|}| | | }|S )zDrop connect.
    Args:
        input (tensor: BCWH): Input of this structure.
        p (float: 0.0~1.0): Probability of drop connection.
        training (bool): The running mode.
    Returns:
        output: Output after drop connection.
    r   r3   zp must be in range of [0,1])dtypedevice)shaper!   randrH   rI   floor)inputsptraining
batch_size	keep_probrandom_tensorbinary_tensoroutputr&   r&   r'   drop_connectb   s   $	

rU   c                 C   s0   t | tr	| | fS t | tst | tr| S t )zObtain height and width from x.
    Args:
        x (int, tuple or list): Data size.
    Returns:
        size: A tuple or list (H,W).
    )
isinstancer=   listtuple	TypeError)r%   r&   r&   r'   get_width_and_height_from_size}   s
   
rZ   c                 C   sZ   | du rdS t | \}}t|tr|n|d }tt|| }tt|| }||gS )ag  Calculates the output image size when using Conv2dSamePadding with a stride.
       Necessary for static padding. Thanks to mannatsingh for pointing this out.
    Args:
        input_image_size (int, tuple or list): Size of input image.
        stride (int, tuple or list): Conv2d operation's stride.
    Returns:
        output_image_size: A list [H,W].
    Nr   )rZ   rV   r=   rD   rE   )input_image_sizer   image_heightimage_widthr&   r&   r'   calculate_output_image_size   s   	r^   c                 C      | du rt S tt| dS )a*  Chooses static padding if you have specified an image size, and dynamic padding otherwise.
       Static padding is necessary for ONNX exporting of models.
    Args:
        image_size (int or tuple): Size of the image.
    Returns:
        Conv2dDynamicSamePadding or Conv2dStaticSamePadding.
    Nr
   )Conv2dDynamicSamePaddingr   Conv2dStaticSamePaddingr`   r&   r&   r'   get_same_padding_conv2d      rc   c                       s2   e Zd ZdZ				d fdd	Zdd Z  ZS )	ra   z2D Convolutions like TensorFlow, for a dynamic image size.
       The padding is operated in forward function by calculating dynamically.
    r3   Tc              
      sJ   t  ||||d||| t| jdkr| j| _d S | jd gd | _d S )Nr   r;   )super__init__lenr   )r$   in_channelsout_channelsr   r   dilationgroupsbias	__class__r&   r'   rf      s   z!Conv2dDynamicSamePadding.__init__c              	   C   s  |  dd  \}}| j  dd  \}}| j\}}t|| t|| }}	|d | jd  }
t|
|d | jd   d | d}|	d | jd  }t||d | jd   d | d}|dksg|dkr}t||d ||d  |d ||d  g}t	|| j| j
| j| j| j| jS Nr3   r   r;   )sizeweightr   rD   rE   r<   rj   Fpadconv2drl   paddingrk   )r$   r%   ihiwkhkwshswohowa1pad_ha2pad_wr&   r&   r'   r(      s   
$$ z Conv2dDynamicSamePadding.forward)r3   r3   r3   Tr*   r+   r,   __doc__rf   r(   __classcell__r&   r&   rm   r'   ra      s    ra   c                       s.   e Zd ZdZ		d fdd	Zdd Z  ZS )	rb   z2D Convolutions like TensorFlow's 'SAME' mode, with the given input image size.
       The padding module is calculated in construction function, then used in forward.
    r3   Nc                    s^  t  j||||fi | t| jdkr| jn| jd gd | _|d us&J t|tr/||fn|\}}| j dd  \}	}
| j\}}t	|| t	|| }}|d | jd  }t
||	d | jd   d | d}|d | jd  }t
||
d | jd   d | d}|dks|dkrt|d ||d  |d ||d  f| _d S t | _d S )Nr;   r   rp   r3   )re   rf   rg   r   rV   r=   rr   rq   rD   rE   r<   rj   r   	ZeroPad2dstatic_paddingIdentity)r$   rh   ri   r   r   r
   kwargsrw   rx   ry   rz   r{   r|   r}   r~   b1r   b2r   rm   r&   r'   rf      s>   

$$

z Conv2dStaticSamePadding.__init__c              	   C   0   |  |}t|| j| j| j| j| j| j}|S r   )	r   rs   ru   rr   rl   r   rv   rj   rk   r#   r&   r&   r'   r(      s
   
zConv2dStaticSamePadding.forward)r3   Nr   r&   r&   rm   r'   rb      s    rb   c                 C   r_   )a0  Chooses static padding if you have specified an image size, and dynamic padding otherwise.
       Static padding is necessary for ONNX exporting of models.
    Args:
        image_size (int or tuple): Size of the image.
    Returns:
        MaxPool2dDynamicSamePadding or MaxPool2dStaticSamePadding.
    Nr`   )MaxPool2dDynamicSamePaddingr   MaxPool2dStaticSamePaddingr`   r&   r&   r'   get_same_padding_maxPool2d   rd   r   c                       s2   e Zd ZdZ				d	 fdd	Zdd Z  ZS )
r   z2D MaxPooling like TensorFlow's 'SAME' mode, with a dynamic image size.
       The padding is operated in forward function by calculating dynamically.
    r   r3   Fc                    s   t  |||||| t| jtr| jgd n| j| _t| jtr'| jgd n| j| _t| jtr:| jgd | _d S | j| _d S )Nr;   )re   rf   rV   r   r=   r   rj   )r$   r   r   rv   rj   return_indices	ceil_moderm   r&   r'   rf     s$   z$MaxPool2dDynamicSamePadding.__init__c              	   C   s  |  dd  \}}| j\}}| j\}}t|| t|| }}	|d | jd  }
t|
|d | jd   d | d}|	d | jd  }t||d | jd   d | d}|dksa|dkrwt||d ||d  |d ||d  g}t	|| j| j| j
| j| j| jS ro   )rq   r   r   rD   rE   r<   rj   rs   rt   
max_pool2drv   r   r   )r$   r%   rw   rx   ry   rz   r{   r|   r}   r~   c1r   c2r   r&   r&   r'   r(     s   

$$ z#MaxPool2dDynamicSamePadding.forward)r   r3   FFr   r&   r&   rm   r'   r     s    r   c                       s*   e Zd ZdZd fdd	Zdd Z  ZS )r   z2D MaxPooling like TensorFlow's 'SAME' mode, with the given input image size.
       The padding mudule is calculated in construction function, then used in forward.
    Nc                    s  t  j||fi | t| jtr| jgd n| j| _t| jtr'| jgd n| j| _t| jtr7| jgd n| j| _|d usAJ t|trJ||fn|\}}| j\}}| j\}	}
t||	 t||
 }}|d | jd  }t	||d | jd   d | d}|d | jd  }t	||d | jd   d | d}|dks|dkrt
|d ||d  |d ||d  f| _d S t
 | _d S )Nr;   r3   r   )re   rf   rV   r   r=   r   rj   rD   rE   r<   r   r   r   r   )r$   r   r   r
   r   rw   rx   ry   rz   r{   r|   r}   r~   d1r   d2r   rm   r&   r'   rf   2  sJ   

$$

z#MaxPool2dStaticSamePadding.__init__c              	   C   r   r   )	r   rs   r   r   r   rv   rj   r   r   r#   r&   r&   r'   r(   L  s
   
z"MaxPool2dStaticSamePadding.forwardr   r   r&   r&   rm   r'   r   -  s    r   c                   @   s@   e Zd ZdZedd Zedd Zedd Zedd	 Zd
S )BlockDecoderz\Block Decoder for readability,
       straight from the official TensorFlow repository.
    c              
   C   s   t | tsJ | d}i }|D ]}td|}t|dkr*|dd \}}|||< qd|v r7t|d dksMt|d dkrK|d d |d d ksMJ tt|d t|d	 t|d d gt|d
 t|d t|d d|v ryt|d ndd| vdS )a2  Get a block through a string notation of arguments.
        Args:
            block_string (str): A string notation of arguments.
                                Examples: 'r1_k3_s11_e1_i32_o16_se0.25_noskip'.
        Returns:
            BlockArgs: The namedtuple defined at the top of this file.
        _z(\d.*)r;   Nsr3   r   rker1   osenoskipr   )rV   strsplitrerg   r   r=   float)block_stringopsoptionsopsplitskeyvaluer&   r&   r'   _decode_block_stringX  s,   	





z!BlockDecoder._decode_block_stringc                 C   s   d| j  d| j d| jd | jd f d| j d| j d| j g}d| j  k r,dkr6n n|d	| j  | jd
u r@|d d	|S )zEncode a block to a string.
        Args:
            block (namedtuple): A BlockArgs type argument.
        Returns:
            block_string: A String form of BlockArgs.
        zr%dzk%dzs%d%dr   r3   ze%szi%dzo%dzse%sFr   r   )
r   r   stridesr   r   r   r   appendr   join)blockargsr&   r&   r'   _encode_block_stringz  s   	


z!BlockDecoder._encode_block_stringc                 C   s0   t | tsJ g }| D ]
}|t| q|S )a  Decode a list of string notations to specify blocks inside the network.
        Args:
            string_list (list[str]): A list of strings, each string is a notation of block.
        Returns:
            blocks_args: A list of BlockArgs namedtuples of block args.
        )rV   rW   r   r   r   )string_listblocks_argsr   r&   r&   r'   decode  s
   zBlockDecoder.decodec                 C   s"   g }| D ]
}| t| q|S )a  Encode a list of BlockArgs to a list of strings.
        Args:
            blocks_args (list[namedtuples]): A list of BlockArgs namedtuples of block args.
        Returns:
            block_strings: A list of strings, each string is a notation of block.
        )r   r   r   )r   block_stringsr   r&   r&   r'   encode  s   zBlockDecoder.encodeN)	r*   r+   r,   r   r8   r   r   r   r   r&   r&   r&   r'   r   S  s    
!

r   c                 C   s"   ddddddddd	d
d
}||  S )zMap EfficientNet model name to parameter coefficients.
    Args:
        model_name (str): Model name to be queried.
    Returns:
        params_dict[model_name]: A (width,depth,res,dropout) tuple.
    )      ?r   p   皙?)r   皙?   r   )r   333333?i  333333?)r   ffffff?i,  r   )r   ?i|  皙?)g?皙@i  r   )r   g@i        ?)g       @g@iX  r   )r   g@i  r   )g333333@g333333@i   r   )
zefficientnet-b0zefficientnet-b1zefficientnet-b2zefficientnet-b3zefficientnet-b4zefficientnet-b5zefficientnet-b6zefficientnet-b7zefficientnet-b8zefficientnet-l2r&   )
model_nameparams_dictr&   r&   r'   efficientnet_params  s   r   r     Tc           	      C   s8   g d}t |}t| ||||dd|dd|d}||fS )aU  Create BlockArgs and GlobalParams for efficientnet model.
    Args:
        width_coefficient (float)
        depth_coefficient (float)
        image_size (int)
        dropout_rate (float)
        drop_connect_rate (float)
        num_classes (int)
        Meaning as the name suggests.
    Returns:
        blocks_args, global_params.
    )zr1_k3_s11_e1_i32_o16_se0.25zr2_k3_s22_e6_i16_o24_se0.25zr2_k5_s22_e6_i24_o40_se0.25zr3_k3_s22_e6_i40_o80_se0.25zr3_k5_s11_e6_i80_o112_se0.25zr4_k5_s22_e6_i112_o192_se0.25zr1_k3_s11_e6_i192_o320_se0.25gGz?gMbP?   Nr   )r   r   r   )	r   r	   r
   r   r   r   r   r   r?   r&   r&   r'   efficientnet  s    
	r   c                 C   sZ   |  drt| \}}}}t||||d\}}ntd| |r)|jdi |}||fS )zGet the block args and global params for a given model name.
    Args:
        model_name (str): Model's name.
        override_params (dict): A dict to modify global_params.
    Returns:
        blocks_args, global_params
    r   )r   r	   r   r
   z!model name is not pre-defined: {}Nr&   )
startswithr   r   NotImplementedErrorformat_replace)r   override_paramswdr   rN   r   r?   r&   r&   r'   get_model_params  s   
r   Fc           	      C   s   t |trt|}n|rtnt}t|| }|r-| j|dd}|j	r,J d
|j	n$|d |d | j|dd}t|j	tddgksQJ d
|j	|jr\J d
|j|rgtd
| dS dS )aZ  Loads pretrained weights from weights path or download using url.
    Args:
        model (Module): The whole model of efficientnet.
        model_name (str): Model name of efficientnet.
        weights_path (None or str):
            str: path to pretrained weights file on the local disk.
            None: use pretrained weights downloaded from the Internet.
        load_fc (bool): Whether to load pretrained weights for fc layer at the end of the model.
        advprop (bool): Whether to load pretrained weights
                        trained with advprop (valid when weights_path is None).
    F)strictz0Missing keys when loading pretrained weights: {}z
_fc.weightz_fc.biasz Loaded pretrained weights for {}N)rV   r   r!   loadurl_map_advpropurl_mapr   load_urlload_state_dictmissing_keysr   popsetunexpected_keysprint)	modelr   weights_pathload_fcadvpropverbose
state_dicturl_map_retr&   r&   r'   load_pretrained_weights  s2   




r   )NNNr   r   r   T)NTFT).collectionsrD   r   	functoolsr   r!   r   torch.nnr   rs   torch.utilsr   
namedtupler   r   rg   _fields__new____defaults__hasattrr   r    ModuleautogradFunctionr.   r9   rC   rG   rU   rZ   r^   rc   Conv2dra   rb   r   	MaxPool2dr   r   objectr   r   r   r   r   r&   r&   r&   r'   <module>   sX   

#
)&&Y
/