
    6bi/A                         S r SSKrSSKJs  Jr  SSKJr  SSK	J
r
  SSKJr  SSKJr  \" SS5       " S	 S
\
R                   5      5       rg)z"Normalization preprocessing layer.    N)backend)base_preprocessing_layer)preprocessing_utils)keras_exportzkeras.layers.Normalizationz5keras.layers.experimental.preprocessing.Normalizationc                      ^  \ rS rSrSr SU 4S jjrU 4S jrSU 4S jjrS rS r	S r
S	 rS
 rS rU 4S jrS rU 4S jrSrU =r$ )Normalization   a<  A preprocessing layer which 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()`.

For an overview and full list of preprocessing layers, see the preprocessing
[guide](https://www.tensorflow.org/guide/tf_keras/preprocessing_layers).

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 = tf.keras.layers.Normalization(axis=None)
>>> layer.adapt(adapt_data)
>>> layer(input_data)
<tf.Tensor: shape=(3,), dtype=float32, numpy=
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 = tf.keras.layers.Normalization(axis=-1)
>>> layer.adapt(adapt_data)
>>> layer(input_data)
<tf.Tensor: shape=(1, 3), dtype=float32, numpy=
array([-1., -1., -1.], dtype=float32)>

Pass the mean and variance directly.

>>> input_data = np.array([[1.], [2.], [3.]], dtype='float32')
>>> layer = tf.keras.layers.Normalization(mean=3., variance=2.)
>>> layer(input_data)
<tf.Tensor: shape=(3, 1), dtype=float32, numpy=
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 = tf.keras.layers.Normalization(axis=-1, invert=True)
>>> layer.adapt(adapt_data)
>>> layer(input_data)
<tf.Tensor: shape=(1, 3), dtype=float32, numpy=
array([2., 10., 8.], dtype=float32)>
c                   > [         TU ]  " S0 UD6  Uc  SnO$[        U[        5      (       a  U4nO[	        U5      nXl        [        U[        R                  5      (       a  [        S5      e[        U[        R                  5      (       a  [        S5      eUS LUS L:w  a  [        SR                  X#5      5      eX l
        X0l        X@l        g )N zJNormalization does not support passing a Variable for the `mean` init arg.zNNormalization does not support passing a Variable for the `variance` init arg.zcWhen setting values directly, both `mean` and `variance` must be set. Got mean: {} and variance: {})super__init__
isinstanceinttupleaxistfVariable
ValueErrorformat
input_meaninput_varianceinvert)selfr   meanvariancer   kwargs	__class__s         i/home/james-whalen/.local/lib/python3.13/site-packages/tf_keras/src/layers/preprocessing/normalization.pyr   Normalization.__init__z   s     	"6" <Dc""7D;D	 dBKK((+  h,,/  ($"67==CV>  &    c                   >^^ [         TU ]  T5        [        T[        [        45      (       a"  [        S T 5       5      (       a  [        S5      e[        R                  " T5      R                  5       m[        T5      m[        U4S jU R                   5       5      (       a%  [        SR                  TU R                  5      5      e[        U R                   Vs/ s H  o"S:  a  UOUT-   PM     sn5      U l        U R                   H/  nTU   b  M  [        SR                  U R                  TU5      5      e   [!        T5       Vs/ s H  o"U R                  ;  d  M  UPM     snU l        [!        T5       Vs/ s H  o"U R                  ;   a  SOSPM     snU l        [!        T5       Vs/ s H  o"U R                  ;   a  TU   OSPM     snU l        [	        U4S jU R                   5       5      nU R(                  c{  U R+                  S	UU R,                  S
SS9U l        U R+                  SUU R,                  SSS9U l        U R+                  SS[        R2                  S
SS9U l        U R7                  5         g U R(                  [8        R:                  " U5      -  nU R<                  [8        R:                  " U5      -  n[        R>                  " X@R&                  5      n[        R>                  " XPR&                  5      n[        R@                  " X@R,                  5      U l!        [        R@                  " XPR,                  5      U l"        g s  snf s  snf s  snf s  snf )Nc              3   V   #    U  H  n[        U[        R                  5      v   M!     g 7fN)r   r   TensorShape).0shapes     r   	<genexpr>&Normalization.build.<locals>.<genexpr>   s!      :
;F%Jubnn--;s   ')zNormalization only accepts a single input. If you are passing a python list or tuple as a single input, please convert to a numpy array or `tf.Tensor`.c              3   F   >#    U  H  oT* :  =(       d    UT:  v   M     g 7fr#   r   )r%   andims     r   r'   r(      s!     9y!D5y%AI%ys   !zPAll `axis` values must be in the range [-ndim, ndim). Found ndim: `{}`, axis: {}r   zqAll `axis` values to be kept must have known shape. Got axis: {}, input shape: {}, with unknown axis at index: {}   c              3   .   >#    U  H
  nTU   v   M     g 7fr#   r   )r%   dinput_shapes     r   r'   r(      s     "K?a;q>?s   r   zerosF)namer&   dtypeinitializer	trainabler   onescountr   )#r   buildr   listr   allr   r   r$   as_listlenanyr   r   sorted
_keep_axisrange_reduce_axis_reduce_axis_mask_broadcast_shaper   
add_weightcompute_dtype
adapt_meanadapt_varianceint64r6   finalize_statenpr5   r   reshapecastr   r   )r   r/   r.   mean_and_var_shaper   r   r+   r   s    `    @r   r7   Normalization.build   s   k"kD%=11c :
;F:
 7
 7
 B  nn[199;;9tyy999--3VD$))-D  !TYY!OYAv!1t8";Y!OPA1~% FFLf		;G  ! ).dP17OQP 7<Dk"
6Adoo%A1,k"

 DI;!
CNa4??2KN9;!
 #"K4??"KK??""oo(((# . DO #'//(((" #2 #D hh# ) DJ ! ??RWW-?%@@D**RWW5G-HHH::d$9$9:Dzz(,A,ABH&8&89DIGGH.@.@ADMm "P Q"
!
s   M	M M;M- Mc                 "   > [         TU ]  XUS9  g)aj  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`.

In order to make `Normalization` efficient in any distribution context,
the computed mean and variance are kept static with respect to any
compiled `tf.Graph`s that call the layer. As a consequence, if the layer
is adapted a second time, any models using the layer should be
re-compiled. For more information see
`tf.keras.layers.experimental.preprocessing.PreprocessingLayer.adapt`.

`adapt()` is meant only as a single machine utility to compute layer
state.  To analyze a dataset that cannot fit on a single machine, see
[Tensorflow Transform](
https://www.tensorflow.org/tfx/transform/get_started)
for a multi-machine, map-reduce solution.

Arguments:
  data: The data to train on. It can be passed either as a
      `tf.data.Dataset`, or as a numpy array.
  batch_size: Integer or `None`.
      Number of samples per state update.
      If unspecified, `batch_size` will default to 32.
      Do not specify the `batch_size` if your data is in the
      form of datasets, generators, or `keras.utils.Sequence` instances
      (since they generate batches).
  steps: Integer or `None`.
      Total number of steps (batches of samples)
      When training with input tensors such as
      TensorFlow data tensors, the default `None` is equal to
      the number of samples in your dataset divided by
      the batch size, or 1 if that cannot be determined. If x is a
      `tf.data` dataset, and 'steps' is None, the epoch will run until
      the input dataset is exhausted. When passing an infinitely
      repeating dataset, you must specify the `steps` argument. This
      argument is not supported with array inputs.
)
batch_sizestepsN)r   adapt)r   datarO   rP   r   s       r   rQ   Normalization.adapt   s    \ 	d?r    c                 *   U R                   b/  [        SR                  U R                   U R                  5      5      eU R                  (       d  [        S5      eU R                  U5      n[        R                  " XR                  R                  5      n[        R                  R                  XR                  S9u  p#[        R                  " XR                  R                  S9nU R                  (       a7  [        R                   " X@R                  5      n[        R"                  " U5      nOSnX`R                  -   n[        R                  " X`R$                  S9[        R                  " XpR$                  S9-  nSU-
  n	U R                  U	-  X(-  -   n
U R&                  U R                  U
-
  S-  -   U	-  X2U
-
  S-  -   U-  -   nU R                  R)                  U
5        U R&                  R)                  U5        U R                  R)                  U5        g )	NzCannot `adapt` a Normalization layer that is initialized with static `mean` and `variance`, you passed mean {} and variance {}.z-`build` must be called before `update_state`.)axes)out_typer,   )r2   g      ?   )r   r   r   r   builtRuntimeError_standardize_inputsr   rK   rE   r2   nnmomentsr@   r&   r6   gatherreduce_prodrD   rF   assign)r   rR   
batch_meanbatch_variancebatch_shapebatch_reduce_shapebatch_counttotal_countbatch_weightexisting_weight
total_meantotal_variances               r   update_stateNormalization.update_state  s   ??&66<fOOT%8%87  zzNOO''-wwt__223%'UU]]4>O>O]%P"
hhtjj.>.>?!#;8I8I!J..);<KK!JJ.ww{2D2DE11I
 
 , OOo-
0II 	 4??Z#?A"EE :5!;;
 	z*"">2

+&r    c                    U R                   c  U R                  (       d  g U R                  R                  [        R
                  " U R                  5      5        U R                  R                  [        R                  " U R                  5      5        U R                  R                  [        R
                  " U R                  5      5        g r#   )	r   rX   rE   r_   r   
zeros_likerF   	ones_liker6   r   s    r   reset_stateNormalization.reset_stateJ  sv    ??&djjr}}T__=>""2<<0C0C#DE

"--

34r    c                    U R                   c  U R                  (       d  g [        R                  " U R                  U R
                  5      U l        [        R                  " U R                  U R                  5      U l        [        R                  " U R                  U R
                  5      U l
        [        R                  " U R                  U R                  5      U l
        g r#   )r   rX   r   rJ   rE   rB   r   rK   rD   rF   r   ro   s    r   rH   Normalization.finalize_stateR  s    ??&djj JJt0E0EF	GGDIIt'9'9:	

4#6#68M8MNt/A/ABr    c                    U R                  U5      n[        R                  " XR                  5      nU R                  (       aX  U R
                  U[        R                  " [        R                  " U R                  5      [        R                  " 5       5      -  -   $ XR
                  -
  [        R                  " [        R                  " U R                  5      [        R                  " 5       5      -  $ r#   )rZ   r   rK   rD   r   r   maximumsqrtr   r   epsilonr   inputss     r   callNormalization.call]  s    ))&1 !3!34;;99BGGDMM$:GOO<MNN  YY&"**&(9+  r    c                     U$ r#   r   )r   r/   s     r   compute_output_shape"Normalization.compute_output_shapek  s    r    c                     U$ r#   r   )r   
input_specs     r   compute_output_signature&Normalization.compute_output_signaturen  s    r    c                    > [         TU ]  5       nUR                  U R                  U R                  [
        R                  " U R                  5      [
        R                  " U R                  5      S.5        U$ )N)r   r   r   r   )	r   
get_configupdater   r   utilslistify_tensorsr   r   )r   configr   s     r   r   Normalization.get_configq  s\    #%		++--doo>!11$2E2EF		
 r    c                     [         R                  " U5      nUR                  U R                  :w  a   [         R                  " XR                  5      nU$ r#   )r   convert_to_tensorr2   rD   rK   rx   s     r   rZ   !Normalization._standardize_inputs}  s=    %%f-<<4---WWV%7%78Fr    c                 D   > [         TU ]  U5        U R                  5         g r#   )r   load_own_variablesrH   )r   storer   s     r   r    Normalization.load_own_variables  s    "5)r    )rB   r>   r@   rA   rE   rF   r   r6   r   r   r   r   r   )NNF)NN)__name__
__module____qualname____firstlineno____doc__r   r7   rQ   rj   rp   rH   rz   r}   r   r   rZ   r   __static_attributes____classcell__)r   s   @r   r   r      sX    
Vr 9>"HMB`.@`*'X5	C
 r    r   )r   numpyrI   tensorflow.compat.v2compatv2r   tf_keras.srcr   tf_keras.src.enginer   !tf_keras.src.layers.preprocessingr   r    tensorflow.python.util.tf_exportr   PreprocessingLayerr   r   r    r   <module>r      sS    )  ! !   8 J :  ;e,?? e	er    