
    2Vh                     x    d dl mZ d dl mZ d dlmZ d dlmZ d dlmZ d dl	m
Z
  ed       G d d	e             Zy
)    )initializers)ops)keras_export)Wrapper)	InputSpec)	normalizez"keras.layers.SpectralNormalizationc                   L     e Zd ZdZd fd	Z fdZd	dZd Zd Z fdZ	 xZ
S )
SpectralNormalizationa  Performs spectral normalization on the weights of a target layer.

    This wrapper controls the Lipschitz constant of the weights of a layer by
    constraining their spectral norm, which can stabilize the training of GANs.

    Args:
        layer: A `keras.layers.Layer` instance that
            has either a `kernel` (e.g. `Conv2D`, `Dense`...)
            or an `embeddings` attribute (`Embedding` layer).
        power_iterations: int, the number of iterations during normalization.
        **kwargs: Base wrapper keyword arguments.

    Examples:

    Wrap `keras.layers.Conv2D`:
    >>> x = np.random.rand(1, 10, 10, 1)
    >>> conv2d = SpectralNormalization(keras.layers.Conv2D(2, 2))
    >>> y = conv2d(x)
    >>> y.shape
    (1, 9, 9, 2)

    Wrap `keras.layers.Dense`:
    >>> x = np.random.rand(1, 10, 10, 1)
    >>> dense = SpectralNormalization(keras.layers.Dense(10))
    >>> y = dense(x)
    >>> y.shape
    (1, 10, 10, 10)

    Reference:

    - [Spectral Normalization for GAN](https://arxiv.org/abs/1802.05957).
    c                 \    t        |   |fi | |dk  rt        d| d      || _        y )Nr   zL`power_iterations` should be greater than zero. Received: `power_iterations=`)super__init__
ValueErrorpower_iterations)selflayerr   kwargs	__class__s       e/home/dcms/DCMS/lib/python3.12/site-packages/keras/src/layers/normalization/spectral_normalization.pyr   zSpectralNormalization.__init__,   sF    )&)q %%5$6a9  !1    c                 ^   t         |   |       t        d gt        |dd        z         | _        t        | j                  d      r| j                  j                  | _        n]t        | j                  d      r| j                  j                  | _        n+t        t        | j                        j                   d      | j                  j                  | _        | j                  d| j                  d   ft        j                   d      d	d
| j                  j"                        | _        y )N   )shapekernel
embeddingsz2 object has no attribute 'kernel' nor 'embeddings'g{Gz?)stddevFvector_u)r   initializer	trainablenamedtype)r   buildr   list
input_spechasattrr   r   r   r   type__name__r   kernel_shape
add_weightr   TruncatedNormalr"   r   )r   input_shaper   s     r   r#   zSpectralNormalization.build5   s    k"#4&4AB3H*HI4::x(**++DKTZZ.**//DK

#,,- .# # 
 !KK--d''+,$44DA++## ( 
r   c                     |rt        j                  t        j                  t        j                   j                  j
                  d             fd j                        \  }} j                  j                  |        j                  j                  |        j                  |      }t        j                  ||j                        S )Nr   c                  \     j                   j                   j                  j                  fS N)r   valuer   )r   s   r   <lambda>z,SpectralNormalization.call.<locals>.<lambda>Q   s     ,,dkk.?.?@ r   )r   condallequalr   r0   normalized_weightsr   assignr   castr"   )r   inputstrainingnew_vector_u
new_kerneloutputs   `     r   callzSpectralNormalization.callM   s    '*xx		$++"3"3Q78@''($L*
 MM  .KKz*F#xx--r   c                 8    | j                   j                  |      S r/   )r   compute_output_shape)r   r,   s     r   r?   z*SpectralNormalization.compute_output_shapeZ   s    zz..{;;r   c           	      \   t        j                  | j                  d| j                  d   g      }| j                  j
                  }t        | j                        D ]W  }t        t        j                  |t        j                  |            d      }t        t        j                  ||      d      }Y t        j                  |      }t        j                        }t        j                  t        j                  ||      t        j                  |            }t        j                  t        j                  | j                  |      | j                        }t        j                  || j                  j                        t        j                  || j                  j                        fS )zGenerate spectral normalized weights.

        This method returns the updated value for `self.kernel` with the
        spectral normalized value, so that the layer is ready for `call()`.
        r   N)axis)r   reshaper   r)   r   r0   ranger   r   matmul	transposestop_gradientdivider7   r"   )r   weightsr   _vector_vsigmar   s          r   r5   z(SpectralNormalization.normalized_weights]   s;    ++dkkB0A0A"0E+FG==&&t,,- 	KA 

8S]]7%;<4H !Hg!>TJH		K
 $$X.$$X.

JJx)3==+B
 SZZU;T=N=NOxx$--"5"56DKK%%9
 
 	
r   c                 H    d| j                   i}t        | 	         }i ||S )Nr   )r   r   
get_config)r   configbase_configr   s      r   rM   z SpectralNormalization.get_configv   s0    $d&;&;<g(*(+(((r   )r   )F)r(   
__module____qualname____doc__r   r#   r=   r?   r5   rM   __classcell__)r   s   @r   r
   r
   	   s,    B1
0.<
2) )r   r
   N)	keras.srcr   r   keras.src.api_exportr   keras.src.layersr   keras.src.layers.input_specr   keras.src.utils.numerical_utilsr   r
    r   r   <module>rZ      s;    "  - $ 1 5 23o)G o) 4o)r   