
    khQ)                     $   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 Zefd	Zd
 Zd Zd Z G d d      Zg dfdZg ddfdZg dfdZg dfdZddej2                  j4                  dej2                  j4                  fdZy)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                     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   )models    L/var/www/teggl/fontify/venv/lib/python3.12/site-packages/timm/utils/model.pyr   r      sR    %"EII&&5(#--UK(00L    c                 .     ||       j                         S N)
state_dict)r   	unwrap_fns     r   get_state_dictr      s    U&&((r   c                 r    t        j                  |j                  g d      dz        j                         S )zA calculate average channel square mean of output activations
    r         axisr   )torchmeanitemr   inputoutputs      r   avg_sq_ch_meanr(       s,     ::fkkyk1Q67<<>>r   c                 l    t        j                  |j                  g d            j                         S z> calculate average channel variance of output activations
    r   r    r"   r#   varr$   r%   s      r   
avg_ch_varr-   &   '     ::fjjij016688r   c                 l    t        j                  |j                  g d            j                         S r*   r+   r%   s      r   avg_ch_var_residualr0   ,   r.   r   c                   "    e Zd ZdZd Zd Zd Zy)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                     || _         || _        || _        t        |      t        |      k7  rt	        d      t        d |D              | _        t        ||      D ]  \  }}| j                  ||        y )Nz_Please provide `hook_fns` for each `hook_fn_locs`,                 their lengths are different.c              3   8   K   | ]  }|j                   g f  y wr   )__name__).0hook_fns     r   	<genexpr>z/ActivationStatsHook.__init__.<locals>.<genexpr>K   s     IW7++R0Is   )	r   hook_fn_locshook_fnslen
ValueErrordictstatszipregister_hook)selfr   r9   r:   hook_fn_locr7   s         r   __init__zActivationStatsHook.__init__D   sx    
( |H- . / /III
$'h$? 	5 K{G4	5r   c                       fd}|S )Nc                 j     | ||      }j                   j                     j                  |       y r   )r>   r5   append)r   r&   r'   outr7   rA   s       r   append_activation_statszAActivationStatsHook._create_hook.<locals>.append_activation_statsP   s.    &%0CJJw''(//4r    )rA   r7   rH   s   `` r   _create_hookz ActivationStatsHook._create_hookO   s    	5 '&r   c                     | j                   j                         D ]<  \  }}t        j                  ||      s|j                  | j	                  |             > y r   )r   named_modulesfnmatchregister_forward_hookrJ   )rA   rB   r7   namer   s        r   r@   z!ActivationStatsHook.register_hookV   sN     JJ446 	ELD&??45(():):7)CD	Er   N)r5   
__module____qualname____doc__rC   rJ   r@   rI   r   r   r2   r2   2   s    "	5'Er   r2   )   r      rT   c                 t    t        j                  dd|      }t        | ||      } | |      }|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      ?)r9   r:   )r"   normalr2   r>   )r   r9   r:   input_shapexhook_s          r   extract_spp_statsr[   ]   s7     	R[)Au<(SDaA::r   Tfreezec                    |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}|}|D cg c]  }| j                  |       }}t        |      s"t        t        | j                                \  }}t        ||      D ]  \  }}|j!                         D ]  }|dk(  rdnd|_         |s,d }|dk(  rt%        |      }	t        |t        j                  j                  j                  j
                  t        j                  j                  j                  j                  t        t        f      s || ||	       t'        |      }	t        |t(        t*        f      s || ||	        yc c}w )	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"`.
    )r\   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.r\   FTc                     |j                  dd      }t        |      dkD  r(| j                  |d         j                  |d   |       y | j                  ||       y )N.r   r   )rsplitr;   get_submodule
add_module)r   rO   	submodulesplits       r   _add_submodulez(_freeze_unfreeze.<locals>._add_submodule   sP    C+u:>((q2==eAh	R%%dI6r   N)r   r"   nnmodules	batchnormBatchNorm2dSyncBatchNormr   r   AssertionErrorstrrb   r;   listr?   named_children
parametersrequires_gradr	   r
   r   r   )
root_module
submodulesinclude_bn_running_statsmoderL   mnprf   ress
             r   _freeze_unfreezerz   o   s    ))Y+YY)+HH&&22HH&&44	   lm 	m *c" \
M8BC1+++A.CJCz?$(k.H.H.J)K$L!zM:. 81 	BA'+x'7eTAO	B#7 x*1- a((22>>((22@@&(	"  #;37 -Q/a"35I!JK";37?8 Ds    Gc                 "    t        | ||d       y)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)
    r\   rt   ru   Nrz   rr   rs   rt   s      r   r\   r\      s    @ [*G_fnor   c                 "    t        | ||d       y)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`.
    r^   r|   Nr}   r~   s      r   r^   r^      s     [*G_fpqr   r   returnc                 <    |st        |       } fd |        | S )Nc                    | j                         D ]n  \  }}t        |d      rt        | ||j                                n9t        |d      r|j	                          nt        |d      r|j                           |       p y )Nfusereparameterizeswitch_to_deploy)ro   r   setattrr   r   r   )rv   
child_namechild_fuses      r   r   z#reparameterize_model.<locals>._fuse   sq    !"!1!1!3 	Juf%:uzz|4 01$$& 23&&(%L	r   r   )r   inplacer   s     @r   reparameterize_modelr      s"     
%LLr   )F)rR   rM   copyr   r"   torchvision.ops.miscr   timm.layersr   r   r   r	   r
   	model_emar   r   r   r(   r-   r0   r2   r[   rz   r\   r^   rg   Moduler   rI   r   r   <module>r      s       21 1 	 %1 )?99(E (E^ %	$ .0$U] C8L $&  pF &($ r" 588?? r   