
    2Vh_:                     |    d dl Z d dl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)
    N)backend)ops)keras_export)TFDataLayer)
tensorflowzkeras.layers.Normalizationc                   d     e Zd ZdZ	 d fd	Zd Zd Zd Zd Zd Z	 fdZ
 fd	Zd
 Zd Z xZS )Normalizationa  A preprocessing layer that normalizes continuous features.

    This layer will shift and scale inputs into a distribution centered around
    0 with standard deviation 1. It accomplishes this by precomputing the mean
    and variance of the data, and calling `(input - mean) / sqrt(var)` at
    runtime.

    The mean and variance values for the layer must be either supplied on
    construction or learned via `adapt()`. `adapt()` will compute the mean and
    variance of the data and store them as the layer's weights. `adapt()` should
    be called before `fit()`, `evaluate()`, or `predict()`.

    Args:
        axis: Integer, tuple of integers, or None. The axis or axes that should
            have a separate mean and variance for each index in the shape.
            For example, if shape is `(None, 5)` and `axis=1`, the layer will
            track 5 separate mean and variance values for the last axis.
            If `axis` is set to `None`, the layer will normalize
            all elements in the input by a scalar mean and variance.
            When `-1`, the last axis of the input is assumed to be a
            feature dimension and is normalized per index.
            Note that in the specific case of batched scalar inputs where
            the only axis is the batch axis, the default will normalize
            each index in the batch separately.
            In this case, consider passing `axis=None`. Defaults to `-1`.
        mean: The mean value(s) to use during normalization. The passed value(s)
            will be broadcast to the shape of the kept axes above;
            if the value(s) cannot be broadcast, an error will be raised when
            this layer's `build()` method is called.
        variance: The variance value(s) to use during normalization. The passed
            value(s) will be broadcast to the shape of the kept axes above;
            if the value(s) cannot be broadcast, an error will be raised when
            this layer's `build()` method is called.
        invert: If `True`, this layer will apply the inverse transformation
            to its inputs: it would turn a normalized input back into its
            original form.

    Examples:

    Calculate a global mean and variance by analyzing the dataset in `adapt()`.

    >>> adapt_data = np.array([1., 2., 3., 4., 5.], dtype='float32')
    >>> input_data = np.array([1., 2., 3.], dtype='float32')
    >>> layer = keras.layers.Normalization(axis=None)
    >>> layer.adapt(adapt_data)
    >>> layer(input_data)
    array([-1.4142135, -0.70710677, 0.], dtype=float32)

    Calculate a mean and variance for each index on the last axis.

    >>> adapt_data = np.array([[0., 7., 4.],
    ...                        [2., 9., 6.],
    ...                        [0., 7., 4.],
    ...                        [2., 9., 6.]], dtype='float32')
    >>> input_data = np.array([[0., 7., 4.]], dtype='float32')
    >>> layer = keras.layers.Normalization(axis=-1)
    >>> layer.adapt(adapt_data)
    >>> layer(input_data)
    array([-1., -1., -1.], dtype=float32)

    Pass the mean and variance directly.

    >>> input_data = np.array([[1.], [2.], [3.]], dtype='float32')
    >>> layer = keras.layers.Normalization(mean=3., variance=2.)
    >>> layer(input_data)
    array([[-1.4142135 ],
           [-0.70710677],
           [ 0.        ]], dtype=float32)

    Use the layer to de-normalize inputs (after adapting the layer).

    >>> adapt_data = np.array([[0., 7., 4.],
    ...                        [2., 9., 6.],
    ...                        [0., 7., 4.],
    ...                        [2., 9., 6.]], dtype='float32')
    >>> input_data = np.array([[1., 2., 3.]], dtype='float32')
    >>> layer = keras.layers.Normalization(axis=-1, invert=True)
    >>> layer.adapt(adapt_data)
    >>> layer(input_data)
    array([2., 10., 8.], dtype=float32)
    c                    t        |   di | |d}nt        |t              r|f}nt	        |      }|| _        || _        || _        || _        d| _	        d | _
        d | _        |d u|d uk7  rt        d| d|       y )N TzUWhen setting values directly, both `mean` and `variance` must be set. Received: mean=z and variance=)super__init__
isinstanceinttupleaxis
input_meaninput_varianceinvertsupports_masking_build_input_shapemean
ValueError)selfr   r   variancer   kwargs	__class__s         \/home/dcms/DCMS/lib/python3.12/site-packages/keras/src/layers/preprocessing/normalization.pyr   zNormalization.__init__`   s     	"6"<Dc"7D;D	& $"&	 ($"67//3fN8*N  8    c           	      h    y t               _        t        fd j                  D              rt	        d d j                         t        t         j                  D cg c]  }|dk\  r|n|z    c}             _         j                  D ]%  }|   	t	        d j                   d d|        t         fdt              D               _	        t              D cg c]  }| j                  v rdnd	 c} _
        t              D cg c]  }| j                  v r|   nd	 c} _        t        fd
 j                  D              }| _         j                  g j                  d|dd       _         j                  d|dd       _         j                  ddddd       _        d _         j'                          y t)        j*                   j                        }t)        j*                   j,                        }t)        j.                  | j                        }t)        j.                  | j                        }t)        j0                  | j2                         _        t)        j0                  | j2                         _        y c c}w c c}w c c}w )Nc              3   8   K   | ]  }| k  xs |k\    y wNr   ).0andims     r   	<genexpr>z&Normalization.build.<locals>.<genexpr>   s#     9!qD5y%AI%9s   zPAll `axis` values must be in the range [-ndim, ndim). Received inputs with ndim=z, while axis=r   zDAll `axis` values to be kept must have a known shape. Received axis=z, inputs.shape=z, with unknown axis at index c              3   @   K   | ]  }|j                   vs|  y wr!   )
_keep_axis)r"   dr   s     r   r%   z&Normalization.build.<locals>.<genexpr>   s!      "
at&>A"
s      c              3   (   K   | ]	  }|     y wr!   r   )r"   r(   input_shapes     r   r%   z&Normalization.build.<locals>.<genexpr>   s     "Ka;q>"Ks   r   zerosF)nameshapeinitializer	trainabler   onescountr   r   )r-   r.   dtyper/   r0   Tr3   )lenr   anyr   r   r   sortedr'   range_reduce_axis_reduce_axis_mask_broadcast_shape_mean_and_var_shaper   
add_weight
adapt_meanadapt_variancer2   builtfinalize_stater   convert_to_tensorr   broadcast_tocastcompute_dtyper   r   )r   r+   r(   mean_and_var_shaper   r   r$   s   ``    @r   buildzNormalization.build{   s   ;"-9tyy99--1F-		{L   tyyA!aAQX-AB
  	A1~% %%)YYK 0$$/= 12236 	 " "
T{"
 

 7<Dk"
12doo%A1,"

 DI;!
>?a4??2KN9!
 #"K4??"KK#5 ??""oo(#	 . DO #'//("	 #2 #D # ) DJ DJ! ((9D,,T-@-@AH##D$*?*?@D''$2G2GHHT-?-?@DIHHXT5G5GHDMs B "
!
s   *J%0J*J/c                    t        |t        j                        st        j                  |      r|j
                  }nt        |t        j                  j                        r]t        |j                  j
                        }t        |      dk(  r|j                  d      }t        |j                  j
                        }| j                  s| j                         nA| j                  D ]2  }|   | j                   |   k7  st#        d| j                    d|        t        |t        j                        rDt        j$                  || j&                        }t        j(                  || j&                        }nt        j                  |      rDt+        j$                  || j&                        }t+        j(                  || j&                        }nbt        |t        j                  j                        r&t+        j,                  | j.                        }t+        j,                  | j.                        }d}|D ]  t        j0                  | j2                        t+        j$                  | j&                        }t+        j(                  | j&                        }| j&                  r+fd| j&                  D        }	t5        j6                  |	      }
nd}
||
z  }t9        |
      |z  }d	|z
  }||z  ||z  z   }|||z
  d
z  z   |z  |||z
  d
z  z   |z  z   }|} nt;        dt=        |             | j>                  jA                  |       | jB                  jA                  |       | jE                          y)a  Computes the mean and variance of values in a dataset.

        Calling `adapt()` on a `Normalization` layer is an alternative to
        passing in `mean` and `variance` arguments during layer construction. A
        `Normalization` layer should always either be adapted over a dataset or
        passed `mean` and `variance`.

        During `adapt()`, the layer will compute a `mean` and `variance`
        separately for each position in each axis specified by the `axis`
        argument. To calculate a single `mean` and `variance` over the input
        data, simply pass `axis=None` to the layer.

        Arg:
            data: The data to train on. It can be passed either as a
                `tf.data.Dataset`, as a NumPy array, or as a backend-native
                eager tensor.
                If a dataset, *it must be batched*. Keras will assume that the
                data is batched, and if that assumption doesn't hold, the mean
                and variance may be incorrectly computed.
        r)      z%The layer was built with input_shape=zO, but adapt() is being called with data with an incompatible shape, data.shape=)r   r   r4   c              3   <   K   | ]  }j                   |     y wr!   )r.   )r"   r(   batchs     r   r%   z&Normalization.adapt.<locals>.<genexpr>  s      *+,A*s   g      ?   zUnsupported data type: N)#r   npndarrayr   	is_tensorr.   tfdataDatasetr   element_specr5   rK   r@   rG   r'   r   r   r   r9   varr   r,   r<   rB   rE   mathprodfloatNotImplementedErrortyper>   assignr?   rA   )r   rQ   r+   r(   
total_mean	total_vartotal_count
batch_mean	batch_varbatch_reduce_shapebatch_countbatch_weightexisting_weightnew_total_meanrK   s                 @r   adaptzNormalization.adapt   s   * dBJJ'7+<+<T+B**Kbggoo. 1 1 7 78K;1$zz# 1 1 7 78KzzJJ{#__ q>T%<%<Q%??$''+'>'>&? @==HMK  dBJJ'D,=,=>Jt$*;*;<It$$T->->?J4+<+<=Ibggoo.4#;#;<J		$":":;IK ,11!3!3 !XXe$2C2CD
GGE0A0AB	$$*040A0A*& #')),>"?K"#K{*$[1K?"%"40:3LL  n!< BB#$ n!< BB '!!	
 ,
9,< &(?T
|&LMMz*""9-r   c                    | j                   | j                  sy t        j                  | j                  | j
                        | _        t        j                  | j                  | j                        | _        t        j                  | j                  | j
                        | _
        t        j                  | j                  | j                        | _
        y r!   )r   r@   r   reshaper>   r;   r   rD   rE   r?   r   r   s    r   rA   zNormalization.finalize_state  s    ??&djj KK1F1FG	HHTYY(:(:;	D$7$79N9NO0B0BCr   c                    | j                   t        d      | j                  j                  j	                  || j
                        }| j                  | j                         }| j                  | j                        }| j                  r| j                  j                  j                  || j                  j                  j                  || j                  j                  j                  | j                  j                  j                  |      t        j                                           S | j                  j                  j                  | j                  j                  j!                  ||      | j                  j                  j                  | j                  j                  j                  |      t        j                                     S )NzAYou must call `.build(input_shape)` on the layer before using it.r4   )r   r   r   corerB   rE   convert_weightr   r   numpyaddmultiplymaximumsqrtepsilondividesubtract)r   inputsr   r   s       r   callzNormalization.call)  sc    990  ""44$,, 5 

 ""499-&&t}}5;;<<%%))""++LL&&..**//97??;L  <<%%,,""++FD9""**LL&&++H5w7H r   c                     |S r!   r   )r   r+   s     r   compute_output_shapez"Normalization.compute_output_shapeL  s    r   c                 $   t         |          }|j                  | j                  | j                  t        j                  | j                        j                         t        j                  | j                        j                         d       |S )N)r   r   r   r   )
r   
get_configupdater   r   rM   arrayr   tolistr   )r   configr   s     r   ry   zNormalization.get_configO  sj    #%		++188:HHT%8%89@@B		
 r   c                 D    t         |   |       | j                          y r!   )r   load_own_variablesrA   )r   storer   s     r   r   z Normalization.load_own_variables[  s    "5)r   c                 8    | j                   rd| j                   iS y Nr+   )r   rh   s    r   get_build_configzNormalization.get_build_config`  s!    ""!4#:#:;; #r   c                 2    |r| j                  |d          y y r   )rG   )r   r}   s     r   build_from_configzNormalization.build_from_configd  s    JJvm,- r   )NNF)__name__
__module____qualname____doc__r   rG   re   rA   ru   rw   ry   r   r   r   __classcell__)r   s   @r   r	   r	      sH    Pf 9>6IIVVp	D!F

<.r   r	   )rU   rl   rM   	keras.srcr   r   keras.src.api_exportr   ,keras.src.layers.preprocessing.tf_data_layerr   keras.src.utils.module_utilsr   rP   r	   r   r   r   <module>r      s>        - D 9 *+Y.K Y. ,Y.r   