o
    ߥi'>                     @   s|   d dl Z d dl mZ d dlmZ ddlmZmZmZm	Z	m
Z
mZmZmZmZmZ dZG dd dejZG d	d
 d
ejZdS )    N)nn)
functional   )
MemoryEfficientSwishSwishcalculate_output_image_sizedrop_connectefficientnet_paramsget_model_paramsget_same_padding_conv2dload_pretrained_weightsround_filtersround_repeats)
zefficientnet-b0zefficientnet-b1zefficientnet-b2zefficientnet-b3zefficientnet-b4zefficientnet-b5zefficientnet-b6zefficientnet-b7zefficientnet-b8zefficientnet-l2c                       s2   e Zd Zd	 fdd	Zd	ddZd
ddZ  ZS )MBConvBlockNc                    s  t    || _d|j | _|j| _| jjd uo%d| jj  k o#dkn  | _|j	| _	| jj
}| jj
| jj }| jjdkrVt|d}|||ddd| _tj|| j| jd| _| jj}| jj}t|d}||||||dd| _tj|| j| jd| _t||}| jrtdd}tdt| jj
| jj }	|||	dd	| _||	|dd	| _| jj}
t|d}|||
ddd| _tj|
| j| jd| _t | _d S )
Nr   r   
image_sizeF)in_channelsout_channelskernel_sizebiasnum_featuresmomentumeps)r   r   groupsr   strider   )r   r   )r   r   r   )super__init___block_argsbatch_norm_momentum_bn_mombatch_norm_epsilon_bn_epsse_ratiohas_seid_skipinput_filtersexpand_ratior   _expand_convr   BatchNorm2d_bn0r   r   _depthwise_conv_bn1r   maxint
_se_reduce
_se_expandoutput_filters_project_conv_bn2r   _swish)self
block_argsglobal_paramsr   inpoupConv2dksnum_squeezed_channels	final_oup	__class__ e/home/ubuntu/.local/lib/python3.10/site-packages/modelscope/models/cv/face_emotion/efficient/model.pyr      s|   








zMBConvBlock.__init__c                 C   s   |}| j jdkr| |}| |}| |}| |}| |}| |}| jrEt	|d}| 
|}| |}| |}t|| }| |}| |}| j j| j j}}| jrs| j jdkrs||krs|rot||| jd}|| }|S )zMBConvBlock's forward function.
        Args:
            inputs (tensor): Input tensor.
            drop_connect_rate (bool): Drop connect rate (float, between 0 and 1).
        Returns:
            Output of this block after processing.
        r   )ptraining)r   r'   r(   r*   r4   r+   r,   r$   Fadaptive_avg_pool2dr/   r0   torchsigmoidr2   r3   r&   r1   r%   r   r   rD   )r5   inputsdrop_connect_ratex
x_squeezedr&   r1   rA   rA   rB   forwardL   s0   	










zMBConvBlock.forwardTc                 C   s   |rt  | _dS t | _dS zSets swish function as memory efficient (for training) or standard (for export).
        Args:
            memory_efficient (bool): Whether to use memory-efficient version of swish.
        N)r   r   r4   )r5   memory_efficientrA   rA   rB   	set_swishq   s   zMBConvBlock.set_swish)NT)__name__
__module____qualname__r   rM   rP   __classcell__rA   rA   r?   rB   r      s    
7%r   c                       s   e Zd ZdZd fdd	ZdddZdd	 Zd
d Zdd Ze	dddZ
e					dddZe	dd Ze	dd Zdd Z  ZS )EfficientNetaj  EfficientNet model.
       Most easily loaded with the .from_name or .from_pretrained methods.
    Args:
        blocks_args (list[namedtuple]): A list of BlockArgs to construct blocks.
        global_params (namedtuple): A set of GlobalParams shared between blocks.
    References:
        [1] https://arxiv.org/abs/1905.11946 (EfficientNet)
    Example:
        >>> import torch
        >>> from efficientnet.model import EfficientNet
        >>> inputs = torch.rand(1, 3, 224, 224)
        >>> model = EfficientNet.from_pretrained('efficientnet-b0')
        >>> model.eval()
        >>> outputs = model(inputs)
    Nc              	      s  t    t|tsJ dt|dksJ d|| _|| _d| jj }| jj}|j	}t
|d}d}td| j}|||ddd	d
| _tj|||d| _t|d}tg | _| jD ]N}	|	jt|	j| jt|	j| jt|	j| jd}	| jt|	| j|d t||	j}|	jdkr|	j|	jdd}	t|	jd D ]}
| jt|	| j|d qqY|	j}td| j}t
|d}|||dd	d| _tj|||d| _td| _| jj rt!| jj"| _#t$|| jj%| _&t' | _(d S )Nzblocks_args should be a listr   z!block args must be greater than 0r   r             Fr   r   r   r   )r&   r1   
num_repeat)r&   r   i   )r   r   ))r   r   
isinstancelistlen_global_params_blocks_argsr   r!   r   r   r   
_conv_stemr   r)   r*   r   
ModuleList_blocks_replacer&   r1   r   r[   appendr   r   range
_conv_headr,   AdaptiveAvgPool2d_avg_poolinginclude_topDropoutdropout_rate_dropoutLinearnum_classes_fcr   r4   )r5   blocks_argsr7   bn_mombn_epsr   r:   r   r   r6   _r?   rA   rB   r      s   






zEfficientNet.__init__Tc                 C   s,   |rt  nt | _| jD ]}|| qdS rN   )r   r   r4   rc   rP   )r5   rO   blockrA   rA   rB   rP      s   
zEfficientNet.set_swishc                 C   s   t  }| | | |}|}t| jD ]G\}}| jj}|r*|t|t	| j 9 }|||d}|
d|
dkrF||dt	|d < n|t	| jd krZ||dt	|d < |}q| | | |}||dt	|d < |S )a?  Use convolution layer to extract features
        from reduction levels i in [1, 2, 3, 4, 5].
        Args:
            inputs (tensor): Input tensor.
        Returns:
            Dictionary of last intermediate features
            with reduction levels i in [1, 2, 3, 4, 5].
        Example:
            >>> import torch
            >>> from efficientnet.model import EfficientNet
            >>> inputs = torch.rand(1, 3, 224, 224)
            >>> model = EfficientNet.from_pretrained('efficientnet-b0')
            >>> endpoints = model.extract_endpoints(inputs)
            >>> print(endpoints['reduction_1'].shape)  # torch.Size([1, 16, 112, 112])
            >>> print(endpoints['reduction_2'].shape)  # torch.Size([1, 24, 56, 56])
            >>> print(endpoints['reduction_3'].shape)  # torch.Size([1, 40, 28, 28])
            >>> print(endpoints['reduction_4'].shape)  # torch.Size([1, 112, 14, 14])
            >>> print(endpoints['reduction_5'].shape)  # torch.Size([1, 320, 7, 7])
            >>> print(endpoints['reduction_6'].shape)  # torch.Size([1, 1280, 7, 7])
        rJ   rY   zreduction_{}r   )dictr4   r*   ra   	enumeraterc   r_   rJ   floatr^   sizeformatr,   rg   )r5   rI   	endpointsrK   prev_xidxru   rJ   rA   rA   rB   extract_endpoints   s$   
zEfficientNet.extract_endpointsc                 C   sr   |  | | |}t| jD ]\}}| jj}|r%|t|t| j 9 }|||d}q|  | 	| 
|}|S )zuse convolution layer to extract feature .
        Args:
            inputs (tensor): Input tensor.
        Returns:
            Output of the final convolution
            layer in the efficientnet model.
        rv   )r4   r*   ra   rx   rc   r_   rJ   ry   r^   r,   rg   )r5   rI   rK   r~   ru   rJ   rA   rA   rB   extract_features   s   zEfficientNet.extract_featuresc                 C   s@   |  |}| |}| jjr|jdd}| |}| |}|S )a  EfficientNet's forward function.
           Calls extract_features to extract features, applies final linear layer, and returns logits.
        Args:
            inputs (tensor): Input tensor.
        Returns:
            Output of this model after processing.
        r   )	start_dim)r   ri   r_   rj   flattenrm   rp   )r5   rI   rK   rA   rA   rB   rM     s   



zEfficientNet.forwardrW   c                 K   s0   |  | t||\}}| ||}|| |S )a  Create an efficientnet model according to name.
        Args:
            model_name (str): Name for efficientnet.
            in_channels (int): Input data's channel number.
            override_params (other key word params):
                Params to override model's global_params.
                Optional key:
                    'width_coefficient', 'depth_coefficient',
                    'image_size', 'dropout_rate',
                    'num_classes', 'batch_norm_momentum',
                    'batch_norm_epsilon', 'drop_connect_rate',
                    'depth_divisor', 'min_depth'
        Returns:
            An efficientnet model.
        )_check_model_name_is_validr
   _change_in_channels)cls
model_namer   override_paramsrq   r7   modelrA   rA   rB   	from_name  s   


zEfficientNet.from_nameF  c                 K   s$   | j |fd|i|}|| |S )a{  Create an efficientnet model according to name.
        Args:
            model_name (str): Name for efficientnet.
            weights_path (None or str):
                str: path to pretrained weights file on the local disk.
                None: use pretrained weights downloaded from the Internet.
            advprop (bool):
                Whether to load pretrained weights
                trained with advprop (valid when weights_path is None).
            in_channels (int): Input data's channel number.
            num_classes (int):
                Number of categories for classification.
                It controls the output size for final linear layer.
            override_params (other key word params):
                Params to override model's global_params.
                Optional key:
                    'width_coefficient', 'depth_coefficient',
                    'image_size', 'dropout_rate',
                    'batch_norm_momentum',
                    'batch_norm_epsilon', 'drop_connect_rate',
                    'depth_divisor', 'min_depth'
        Returns:
            A pretrained efficientnet model.
        ro   )r   r   )r   r   weights_pathadvpropr   ro   r   r   rA   rA   rB   from_pretrained5  s    
zEfficientNet.from_pretrainedc                 C   s   |  | t|\}}}}|S )zGet the input image size for a given efficientnet model.
        Args:
            model_name (str): Name for efficientnet.
        Returns:
            Input image size (resolution).
        )r   r	   )r   r   rt   resrA   rA   rB   get_image_sizeZ  s   
zEfficientNet.get_image_sizec                 C   s   |t vrtddt  dS )zValidates model name.
        Args:
            model_name (str): Name for efficientnet.
        Returns:
            bool: Is a valid name or not.
        zmodel_name should be one of: z, N)VALID_MODELS
ValueErrorjoin)r   r   rA   rA   rB   r   f  s
   z'EfficientNet._check_model_name_is_validc                 C   s>   |dkrt | jjd}td| j}|||dddd| _dS dS )zAdjust model's first convolution layer to in_channels, if in_channels not equals 3.
        Args:
            in_channels (int): Input data's channel number.
        rW   r   rX   rY   FrZ   N)r   r_   r   r   ra   )r5   r   r:   r   rA   rA   rB   r   r  s   
z EfficientNet._change_in_channels)NNrQ   )rW   )NFrW   r   )rR   rS   rT   __doc__r   rP   r   r   rM   classmethodr   r   r   r   r   rU   rA   rA   r?   rB   rV   y   s(    
<	+$

rV   )rG   r   torch.nnr   rE   utilsr   r   r   r   r	   r
   r   r   r   r   r   Moduler   rV   rA   rA   rA   rB   <module>   s   0f