
    6bij1                         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KJr  SSKJr  \" S	5       " S
 S\	\R$                  S95       rS rg)zEContains the base ProcessingLayer and a subclass that uses Combiners.    N)data_adapter)Layer)version_utils)context)keras_export)doc_controlsz:keras.layers.experimental.preprocessing.PreprocessingLayerc                   <  ^  \ rS rSrSrSrU 4S jr\S 5       r\	R                  S 5       r\	R                  S 5       r\	R                  S 5       r\	R                  S	 5       rSS
 jrSS jrS r\R&                  R(                  R*                  S 5       rS rSrU =r$ )PreprocessingLayer   a'  Base class for Preprocessing Layers.

**Don't use this class directly: it's an abstract base class!** You may
be looking for one of the many built-in
[preprocessing layers](https://keras.io/guides/preprocessing_layers/)
instead.

Preprocessing layers are layers whose state gets computed before model
training starts. They do not get updated during training. Most
preprocessing layers implement an `adapt()` method for state computation.

The `PreprocessingLayer` class is the base class you would subclass to
implement your own preprocessing layers.
Tc                    > [         TU ]  " S0 UD6  SU l        SU l        U R                  U l        U R                  U l        S U l        g )NF )super__init___is_compiled_is_adaptedreset_state_reset_state_impl_reset_state_wrapper_adapt_function)selfkwargs	__class__s     f/home/james-whalen/.local/lib/python3.13/site-packages/tf_keras/src/engine/base_preprocessing_layer.pyr   PreprocessingLayer.__init__2   sI    "6"!  "&!1!144#    c                     U R                   $ )z/Whether the layer has been fit to data already.)r   r   s    r   
is_adaptedPreprocessingLayer.is_adapted=   s     r   c                     [         e)zmAccumulates statistics for the preprocessing layer.

Arguments:
  data: A mini-batch of inputs to the layer.
NotImplementedError)r   datas     r   update_statePreprocessingLayer.update_stateB   s
     "!r   c                     [         e)z1Resets the statistics of the preprocessing layer.r!   r   s    r   r   PreprocessingLayer.reset_stateK   s
     "!r   c                     g)a  Finalize the statistics for the preprocessing layer.

This method is called at the end of `adapt` or after restoring a
serialized preprocessing layer's state. This method handles any one-time
operations that should occur on the layer's state before
`Layer.__call__`.
Nr   r   s    r   finalize_state!PreprocessingLayer.finalize_stateP   s     	r   c                 $  ^ ^ T R                   b  T R                   $ U 4S jmT R                  R                  5       R                  5       S:X  a  TnOUU 4S jnT R                  (       d  [
        R                  " U5      nUT l         T R                   $ )ae  Creates a function to execute one step of `adapt`.

This method can be overridden to support custom adapt logic.
This method is called by `PreprocessingLayer.adapt`.

Typically, this method directly controls `tf.function` settings,
and delegates the actual state update logic to
`PreprocessingLayer.update_state`.

This function is cached the first time `PreprocessingLayer.adapt`
is called. The cache is cleared whenever `PreprocessingLayer.compile`
is called.

Returns:
  Function. The function created by this method should accept a
  `tf.data.Iterator`, retrieve a batch, and update the state of the
  layer.
c                 `   > [        U 5      nTR                  U5        TR                  U5        g N)next_adapt_maybe_buildr$   )iteratorr#   r   s     r   
adapt_step:PreprocessingLayer.make_adapt_function.<locals>.adapt_stepr   s(    >D##D)d#r      c                 d   > [         R                  " TR                  5       H  nT" U 5        M     g r-   )tfrange_steps_per_execution)r0   _r1   r   s     r   adapt_fn8PreprocessingLayer.make_adapt_function.<locals>.adapt_fn{   s$    $";";<Ax( =r   )r   r7   numpyitem_run_eagerlyr5   function)r   r9   r1   s   ` @r   make_adapt_function&PreprocessingLayer.make_adapt_function[   s{    ( +'''	$
 $$**,113q8!H)   {{8,H'###r   c                 h    Uc  SnU R                  U5        Uc  U R                  nXl        SU l        g)a  Configures the layer for `adapt`.

Arguments:
  run_eagerly: Bool. If `True`, this `Model`'s
    logic will not be wrapped in a `tf.function`. Recommended to leave
    this as `None` unless your `Model` cannot be run inside a
    `tf.function`. Defaults to `False`.
  steps_per_execution: Int. The number of batches to run
    during each `tf.function` call. Running multiple batches inside a
    single `tf.function` call can greatly improve performance on TPUs or
    small models with a large Python overhead. Defaults to `1`.
Nr3   T)_configure_steps_per_executiondynamicr=   r   )r   run_eagerlysteps_per_executions      r   compilePreprocessingLayer.compile   s<     &"#++,?@,,K' r   c           	         [        S5        [        R                  " 5       (       d  [        S5      eU R                  (       d  U R                  5         U R                  (       a  U R                  5         [        R                  " UUUSU R                  SS9nU R                  5       U l        UR                  5        Hn  u  pVUR                  5          UR                  5        H<  nU R                  U5        UR                   (       d  M'  ["        R$                  " 5         M>     SSS5        Mp     U R'                  5         SU l        g! , (       d  f       M  = f)a  Fits the state of the preprocessing layer to the data being passed.

After calling `adapt` on a layer, a preprocessing layer's state will not
update during training. In order to make preprocessing layers efficient
in any distribution context, they are kept constant with respect to any
compiled `tf.Graph`s that call the layer. This does not affect the layer
use when adapting each layer only once, but if you adapt a layer
multiple times you will need to take care to re-compile any compiled
functions as follows:

 * If you are adding a preprocessing layer to a `keras.Model`, you need
   to call `model.compile` after each subsequent call to `adapt`.
 * If you are calling a preprocessing layer inside
  `tf.data.Dataset.map`, you should call `map` again on the input
  `tf.data.Dataset` after each `adapt`.
 * If you are using a `tf.function` directly which calls a preprocessing
   layer, you need to call `tf.function` again on your callable after
   each subsequent call to `adapt`.

`tf.keras.Model` example with multiple adapts:

>>> layer = tf.keras.layers.Normalization(
...     axis=None)
>>> layer.adapt([0, 2])
>>> model = tf.keras.Sequential(layer)
>>> model.predict([0, 1, 2])
array([-1.,  0.,  1.], dtype=float32)
>>> layer.adapt([-1, 1])
>>> model.compile() # This is needed to re-compile model.predict!
>>> model.predict([0, 1, 2])
array([0., 1., 2.], dtype=float32)

`tf.data.Dataset` example with multiple adapts:

>>> layer = tf.keras.layers.Normalization(
...     axis=None)
>>> layer.adapt([0, 2])
>>> input_ds = tf.data.Dataset.range(3)
>>> normalized_ds = input_ds.map(layer)
>>> list(normalized_ds.as_numpy_iterator())
[array([-1.], dtype=float32),
 array([0.], dtype=float32),
 array([1.], dtype=float32)]
>>> layer.adapt([-1, 1])
>>> normalized_ds = input_ds.map(layer) # Re-map over the input dataset.
>>> list(normalized_ds.as_numpy_iterator())
[array([0.], dtype=float32),
 array([1.], dtype=float32),
 array([2.], dtype=float32)]

`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.
adaptz+`adapt` is only supported in tensorflow v2.r3   F)
batch_sizesteps_per_epochepochsrE   
distributeNT)_disallow_inside_tf_functionr   should_use_v2RuntimeErrorr   rF   builtr   r   DataHandlerr7   r?   r   enumerate_epochscatch_stop_iterationstepsshould_syncr   
async_waitr)   r   )r   r#   rJ   rU   data_handlerr8   r0   s          r   rI   PreprocessingLayer.adapt   s	   Z 	%W-**,,LMM  LLN::#//!! $ 9 9
  $779'88:KA224%++-A((2#///**, . 54 ; 	 54s   4EE
E	c                 2    U R                  5         SU l        g)z2Calls `reset_state` and sets `adapted` to `False`.FN)r   r   r   s    r   r   'PreprocessingLayer._reset_state_wrapper  s      r   c                 j    [         R                  " US[         R                  R                  S9U l        g )Nint64)dtypeaggregation)r5   VariableVariableAggregationONLY_FIRST_REPLICAr7   )r   rE   s     r   rB   1PreprocessingLayer._configure_steps_per_execution  s(    $&KK..AA%
!r   c                 
   U R                   (       d^   UR                  n[        S /[        UR                  5      -  5      n[        U SS 5      nUc  X0l        U R                  U5        SU l         g g ! [         a    S nS n N@f = f)N_batch_input_shapeT)rQ   shapetuplelenAttributeErrorgetattrre   build)r   r#   
data_shapedata_shape_nonesbatch_input_shapes        r   r/   %PreprocessingLayer._adapt_maybe_build  s    zz( "ZZ
#($#djj/)A#B  !(.BD I (*:'JJz"DJ#  " (!
#' (s   .A1 1BB)	r   re   r   r   r   r=   r7   rQ   r   )NN)__name__
__module____qualname____firstlineno____doc___must_restore_from_configr   propertyr   r   do_not_generate_docsr$   r   r)   r?   rF   rI   r   r5   __internal__tracking no_automatic_dependency_trackingrB   r/   __static_attributes____classcell__)r   s   @r   r
   r
      s     !%	$     &&" '" &&" '" && ' &&'$ ''$R!.d L!
 __>>
 ?
 r   r
   )	metaclassc                 l    [         R                  " 5       (       a  SR                  U S9n[        U5      eg)z1Disallow calling a method inside a `tf.function`.a  Detected a call to `PreprocessingLayer.{method_name}` inside a `tf.function`. `PreprocessingLayer.{method_name} is a high-level endpoint that manages its own `tf.function`. Please move the call to `PreprocessingLayer.{method_name}` outside of all enclosing `tf.function`s. Note that you can call a `PreprocessingLayer` directly on `Tensor`s inside a `tf.function` like: `layer(x)`, or update its state like: `layer.update_state(x)`.)method_nameN)r5   inside_functionformatrP   )r   	error_msgs     r   rN   rN   %  s<    	A &[&
) 	 9%% r   )rt   abctensorflow.compat.v2compatv2r5   tf_keras.src.enginer   tf_keras.src.engine.base_layerr   tf_keras.src.utilsr   tensorflow.python.eagerr    tensorflow.python.util.tf_exportr   tensorflow.tools.docsr   ABCMetar
   rN   r   r   r   <module>r      sY    L 
 ! ! , 0 , , 9 . JKB#++ B LBJ&r   