o
    پiQ)                     @   s   d Z ddlZddlmZ ddlZddlmZ ddlmZm	Z	m
Z
mZmZ ddlmZ dd	 Zefd
dZdd Zdd Zdd ZG dd dZg dfddZg ddfddZg dfddZg dfddZd#dejjd ejjfd!d"ZdS )$zM Model / state_dict utils

Hacked together by / Copyright 2020 Ross Wightman
    Ndeepcopy)FrozenBatchNorm2d)BatchNormAct2dSyncBatchNormActFrozenBatchNormAct2dfreeze_batch_norm_2dunfreeze_batch_norm_2d   )ModelEmac                 C   s@   t | tr
t| jS t| drt| jS t| drt| jS | S )Nmodule	_orig_mod)
isinstancer   unwrap_modelemahasattrr   r   )model r   D/home/ubuntu/.local/lib/python3.10/site-packages/timm/utils/model.pyr      s   





r   c                 C   s   ||   S N)
state_dict)r   	unwrap_fnr   r   r   get_state_dict   s   r   c                 C   s   t |jg ddd  S )zA calculate average channel square mean of output activations
    r         axisr   )torchmeanitemr   inputoutputr   r   r   avg_sq_ch_mean    s   r$   c                 C      t |jg dd S z> calculate average channel variance of output activations
    r   r   r   r   varr    r!   r   r   r   
avg_ch_var&      r)   c                 C   r%   r&   r'   r!   r   r   r   avg_ch_var_residual,   r*   r+   c                   @   s(   e Zd ZdZdd Zdd Zdd ZdS )	ActivationStatsHooka  Iterates through each of `model`'s modules and matches modules using unix pattern 
    matching based on `hook_fn_locs` and registers `hook_fn` to the module if there is 
    a match. 

    Arguments:
        model (nn.Module): model from which we will extract the activation stats
        hook_fn_locs (List[str]): List of `hook_fn` locations based on Unix type string 
            matching with the name of model's modules. 
        hook_fns (List[Callable]): List of hook functions to be registered at every
            module in `layer_names`.
    
    Inspiration from https://docs.fast.ai/callback.hook.html.

    Refer to https://gist.github.com/amaarora/6e56942fcb46e67ba203f3009b30d950 for an example 
    on how to plot Signal Propagation Plots using `ActivationStatsHook`.
    c                 C   sb   || _ || _|| _t|t|krtdtdd |D | _t||D ]
\}}| || q$d S )Nz_Please provide `hook_fns` for each `hook_fn_locs`,                 their lengths are different.c                 s   s    | ]}|j g fV  qd S r   )__name__).0hook_fnr   r   r   	<genexpr>K   s    z/ActivationStatsHook.__init__.<locals>.<genexpr>)	r   hook_fn_locshook_fnslen
ValueErrordictstatszipregister_hook)selfr   r1   r2   hook_fn_locr/   r   r   r   __init__D   s   zActivationStatsHook.__init__c                    s    fdd}|S )Nc                    s"    | ||}j  j | d S r   )r6   r-   append)r   r"   r#   outr/   r9   r   r   append_activation_statsP   s   zAActivationStatsHook._create_hook.<locals>.append_activation_statsr   )r9   r/   r?   r   r>   r   _create_hookO   s   z ActivationStatsHook._create_hookc                 C   s6   | j  D ]\}}t||sq|| | qd S r   )r   named_modulesfnmatchregister_forward_hookr@   )r9   r:   r/   namer   r   r   r   r8   V   s
   z!ActivationStatsHook.register_hookN)r-   
__module____qualname____doc__r;   r@   r8   r   r   r   r   r,   2   s
    r,   )   r      rI   c                 C   s*   t dd|}t| ||d}| |}|jS )a  Extract average square channel mean and variance of activations during 
        forward pass to plot Signal Propagation Plots (SPP).
    
    Paper: https://arxiv.org/abs/2101.08692

    Example Usage: https://gist.github.com/amaarora/6e56942fcb46e67ba203f3009b30d950
    g        g      ?)r1   r2   )r   normalr,   r6   )r   r1   r2   input_shapexhook_r   r   r   extract_spp_stats]   s   rO   Tfreezec           
         s"  |dv sJ dt  tjjjjtjjjjttfrt	dt |t
r%|g}|} fdd|D }t|s>tt   \}}t||D ]K\}}| D ]}|dkrSdnd|_qK|rd	d
 }|dkr}t|}	t |tjjjjtjjjjttfr|| ||	 qCt|}	t |ttfr| ||	 qCdS )a9  
    Freeze or unfreeze parameters of the specified modules and those of all their hierarchical descendants. This is
        done in place.

    Args:
        root_module (nn.Module, optional): Root module relative to which the `submodules` are referenced.
        submodules (list[str]): List of modules for which the parameters will be (un)frozen. They are to be provided as
            named modules relative to the root module (accessible via `root_module.named_modules()`). An empty list
            means that the whole root module will be (un)frozen. Defaults to []
        include_bn_running_stats (bool): Whether to also (un)freeze the running statistics of batch norm 2d layers.
            Defaults to `True`.
        mode (bool): Whether to freeze ("freeze") or unfreeze ("unfreeze"). Defaults to `"freeze"`.
    )rP   unfreezez,`mode` must be one of "freeze" or "unfreeze"zYou have provided a batch norm layer as the `root module`. Please use `timm.utils.model.freeze_batch_norm_2d` or `timm.utils.model.unfreeze_batch_norm_2d` instead.c                    s   g | ]}  |qS r   )get_submodule)r.   mroot_moduler   r   
<listcomp>   s    z$_freeze_unfreeze.<locals>.<listcomp>rP   FTc                 S   sF   | dd}t|dkr| |d |d | d S | || d S )N.r
   r   )rsplitr3   rR   
add_module)r   rD   	submodulesplitr   r   r   _add_submodule   s   z(_freeze_unfreeze.<locals>._add_submoduleN)r   r   nnmodules	batchnormBatchNorm2dSyncBatchNormr   r   AssertionErrorstrr3   listr7   named_children
parametersrequires_gradr   r	   r   r   )
rU   
submodulesinclude_bn_running_statsmoderA   nrS   pr\   resr   rT   r   _freeze_unfreezeo   sH   




rn   c                 C      t | ||dd dS )a  
    Freeze parameters of the specified modules and those of all their hierarchical descendants. This is done in place.

    Args:
        root_module (nn.Module): Root module relative to which `submodules` are referenced.
        submodules (list[str]): List of modules for which the parameters will be frozen. They are to be provided as
            named modules relative to the root module (accessible via `root_module.named_modules()`). An empty list
            means that the whole root module will be frozen. Defaults to `[]`.
        include_bn_running_stats (bool): Whether to also freeze the running statistics of `BatchNorm2d` and
            `SyncBatchNorm` layers. These will be converted to `FrozenBatchNorm2d` in place. Hint: During fine tuning,
            it's good practice to freeze batch norm stats. And note that these are different to the affine parameters
            which are just normal PyTorch parameters. Defaults to `True`.

    Hint: If you want to freeze batch norm ONLY, use `timm.utils.model.freeze_batch_norm_2d`.

    Examples::

        >>> model = timm.create_model('resnet18')
        >>> # Freeze up to and including layer2
        >>> submodules = [n for n, _ in model.named_children()]
        >>> print(submodules)
        ['conv1', 'bn1', 'act1', 'maxpool', 'layer1', 'layer2', 'layer3', 'layer4', 'global_pool', 'fc']
        >>> freeze(model, submodules[:submodules.index('layer2') + 1])
        >>> # Check for yourself that it works as expected
        >>> print(model.layer2[0].conv1.weight.requires_grad)
        False
        >>> print(model.layer3[0].conv1.weight.requires_grad)
        True
        >>> # Unfreeze
        >>> unfreeze(model)
    rP   ri   rj   Nrn   rU   rh   ri   r   r   r   rP      s    c                 C   ro   )a  
    Unfreeze parameters of the specified modules and those of all their hierarchical descendants. This is done in place.

    Args:
        root_module (nn.Module): Root module relative to which `submodules` are referenced.
        submodules (list[str]): List of submodules for which the parameters will be (un)frozen. They are to be provided
            as named modules relative to the root module (accessible via `root_module.named_modules()`). An empty
            list means that the whole root module will be unfrozen. Defaults to `[]`.
        include_bn_running_stats (bool): Whether to also unfreeze the running statistics of `FrozenBatchNorm2d` layers.
            These will be converted to `BatchNorm2d` in place. Defaults to `True`.

    See example in docstring for `freeze`.
    rQ   rp   Nrq   rr   r   r   r   rQ      s   rQ   Fr   returnc                    s$   |st | }  fdd  |  | S )Nc                    s`   |   D ])\}}t|drt| ||  nt|dr |  n	t|dr)|   | qd S )Nfusereparameterizeswitch_to_deploy)re   r   setattrrt   ru   rv   )rS   
child_namechild_fuser   r   r{      s   




z#reparameterize_model.<locals>._fuser   )r   inplacer   rz   r   reparameterize_model   s
   
r}   )F)rG   rB   copyr   r   torchvision.ops.miscr   timm.layersr   r   r   r   r	   	model_emar   r   r   r$   r)   r+   r,   rO   rn   rP   rQ   r]   Moduler}   r   r   r   r   <module>   s&    /
F# 