o
    #jq                     @   s`   d dl Z ddlmZ ddlmZ ddlmZmZm	Z	 g Z
ddd	ZG d
d dZ	dddZdS )    N   )
functional)Linear)Conv1DTransposeConv2DTransposeConv3DTranspose              ?c                 C   s"   t j||| jd}t ||  | S )N)shape)paddlenormalr
   assign)xmeanZstdZ
temp_value r   c/var/www/html/Deteccion_Ine/venv/lib/python3.10/site-packages/paddle/nn/utils/spectral_norm_hook.pynormal_   s   r   c                   @   s:   e Zd ZdddZdd Zd	d
 Zdd Zedd ZdS )SpectralNormweight   r   -q=c                 C   s2   || _ || _|dkrtd| || _|| _d S )Nr   zGExpected n_power_iterations to be positive, but got n_power_iterations=)namedim
ValueErrorn_power_iterationseps)selfr   r   r   r   r   r   r   __init__   s   
zSpectralNorm.__init__c                    sN   |} j dkr| j g fddt|  D  }|jd }||dgS )Nr   c                    s   g | ]	}| j kr|qS r   )r   ).0dr   r   r   
<listcomp>0   s    z9SpectralNorm.reshape_weight_to_matrix.<locals>.<listcomp>)r   Z	transposeranger
   Zreshape)r   r   
weight_matheightr   r    r   reshape_weight_to_matrix*   s   

z%SpectralNorm.reshape_weight_to_matrixc           	      C   s   t || jd }t || jd }t || jd }| |}|rmt B t| jD ]'}ttj	tj
||dddd| jd| ttj	t
||d| jd| q)| jdkr^| }| }W d    n1 shw   Y  t|t||}|| }|S )	N_orig_u_vTF)Ztranspose_xZtranspose_yr   Zaxisepsilon)getattrr   r&   r   no_gradr#   r   r   F	normalizematmulr   clonedotmv)	r   layerdo_power_iterationr   uvr$   _sigmar   r   r   compute_weight7   sH   




zSpectralNorm.compute_weightc                 C   s   t || j| j||jd d S )N)r5   )setattrr   r:   Ztraining)r   r4   Zinputsr   r   r   __call__^   s
   zSpectralNorm.__call__c                 C   s>  | j  D ]\}}t|tr|j|krtd| qt||||}| j| }t < |	|}	|	j
\}
}| |
g}t|dd}| |g}t|dd}tj|d|jd}tj|d|jd}W d    n1 sjw   Y  | j|j= | |jd | t| |j|d  | |jd | | |jd | | | |S )	Nz>Cannot register two spectral_norm hooks on the same parameter r   r	   r   r*   r'   r(   r)   )Z_forward_pre_hooksitems
isinstancer   r   RuntimeError_parametersr   r-   r&   r
   Zcreate_parameterr   r.   r/   r   Zadd_parameterr;   Zregister_bufferZregister_forward_pre_hook)r4   r   r   r   r   khookfnr   r$   hwr6   r7   r   r   r   applye   s6   





zSpectralNorm.applyN)r   r   r   r   )	__name__
__module____qualname__r   r&   r:   r<   staticmethodrF   r   r   r   r   r      s    
'r   r   r   r   c                 C   s:   |du rt | ttttfrd}nd}t| |||| | S )a
  
    Applies spectral normalization to a parameter according to the
    following Calculation:

    Step 1:
    Generate vector U in shape of [H], and V in shape of [W].
    While H is the :attr:`dim` th dimension of the input weights,
    and W is the product result of remaining dimensions.

    Step 2:
    :attr:`n_power_iterations` should be a positive integer, do following
    calculations with U and V for :attr:`power_iters` rounds.

    .. math::

        \mathbf{v} := \frac{\mathbf{W}^{T} \mathbf{u}}{\|\mathbf{W}^{T} \mathbf{u}\|_2}

        \mathbf{u} := \frac{\mathbf{W} \mathbf{v}}{\|\mathbf{W} \mathbf{v}\|_2}

    Step 3:
    Calculate :math:`\sigma(\mathbf{W})` and normalize weight values.

    .. math::

        \sigma(\mathbf{W}) = \mathbf{u}^{T} \mathbf{W} \mathbf{v}

        \mathbf{W} = \frac{\mathbf{W}}{\sigma(\mathbf{W})}


    Refer to `Spectral Normalization <https://arxiv.org/abs/1802.05957>`_ .

    Parameters:
        layer(Layer): Layer of paddle, which has weight.
        name(str, optional): Name of the weight parameter. Default: 'weight'.
        n_power_iterations(int, optional): The number of power iterations to calculate spectral norm. Default: 1.
        eps(float, optional): The epsilon for numerical stability in calculating norms. Default: 1e-12.
        dim(int, optional): The index of dimension which should be permuted to the first before reshaping Input(Weight) to matrix, it should be set as 0 if Input(Weight) is the weight of fc layer, and should be set as 1 if Input(Weight) is the weight of conv layer. Default: None.

    Returns:
        Layer, the original layer with the spectral norm hook.

    Examples:
        .. code-block:: python

            >>> from paddle.nn import Conv2D
            >>> from paddle.nn.utils import spectral_norm
            >>> paddle.seed(2023)
            >>> conv = Conv2D(3, 1, 3)
            >>> sn_conv = spectral_norm(conv)
            >>> print(sn_conv)
            Conv2D(3, 1, kernel_size=[3, 3], data_format=NCHW)
            >>> # Conv2D(3, 1, kernel_size=[3, 3], data_format=NCHW)
            >>> print(sn_conv.weight)
            Tensor(shape=[1, 3, 3, 3], dtype=float32, place=Place(cpu), stop_gradient=False,
            [[[[ 0.01668976,  0.30305523,  0.11405435],
               [-0.06765547, -0.50396705, -0.40925547],
               [ 0.47344422,  0.03628403,  0.45277366]],
              [[-0.15177251, -0.16305730, -0.15723954],
               [-0.28081197, -0.09183260, -0.08081978],
               [-0.40895155,  0.18298769, -0.29325116]],
              [[ 0.21819633, -0.01822380, -0.50351536],
               [-0.06262003,  0.17713565,  0.20517939],
               [ 0.16659889, -0.14333329,  0.05228264]]]])

    Nr   r   )r>   r   r   r   r   r   rF   )r4   r   r   r   r   r   r   r   spectral_norm   s   ErK   )r   r	   )r   r   r   N)r    r   r.   Zlayer.commonr   Z
layer.convr   r   r   __all__r   r   rK   r   r   r   r   <module>   s   
o