
    2Vh"                     t    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)ops)keras_export)Callback)compile_utils)io_utilszkeras.callbacks.EarlyStoppingc                   ^     e Zd ZdZ	 	 	 	 	 	 	 	 d	 fd	Zd Zd
dZd
dZd
dZd Z	d Z
 xZS )EarlyStoppingax  Stop training when a monitored metric has stopped improving.

    Assuming the goal of a training is to minimize the loss. With this, the
    metric to be monitored would be `'loss'`, and mode would be `'min'`. A
    `model.fit()` training loop will check at end of every epoch whether
    the loss is no longer decreasing, considering the `min_delta` and
    `patience` if applicable. Once it's found no longer decreasing,
    `model.stop_training` is marked True and the training terminates.

    The quantity to be monitored needs to be available in `logs` dict.
    To make it so, pass the loss or metrics at `model.compile()`.

    Args:
        monitor: Quantity to be monitored. Defaults to `"val_loss"`.
        min_delta: Minimum change in the monitored quantity to qualify as an
            improvement, i.e. an absolute change of less than min_delta, will
            count as no improvement. Defaults to `0`.
        patience: Number of epochs with no improvement after which training will
            be stopped. Defaults to `0`.
        verbose: Verbosity mode, 0 or 1. Mode 0 is silent, and mode 1 displays
            messages when the callback takes an action. Defaults to `0`.
        mode: One of `{"auto", "min", "max"}`. In `min` mode, training will stop
            when the quantity monitored has stopped decreasing; in `"max"` mode
            it will stop when the quantity monitored has stopped increasing; in
            `"auto"` mode, the direction is automatically inferred from the name
            of the monitored quantity. Defaults to `"auto"`.
        baseline: Baseline value for the monitored quantity. If not `None`,
            training will stop if the model doesn't show improvement over the
            baseline. Defaults to `None`.
        restore_best_weights: Whether to restore model weights from the epoch
            with the best value of the monitored quantity. If `False`, the model
            weights obtained at the last step of training are used. An epoch
            will be restored regardless of the performance relative to the
            `baseline`. If no epoch improves on `baseline`, training will run
            for `patience` epochs and restore weights from the best epoch in
            that set. Defaults to `False`.
        start_from_epoch: Number of epochs to wait before starting to monitor
            improvement. This allows for a warm-up period in which no
            improvement is expected and thus training will not be stopped.
            Defaults to `0`.

    Example:

    >>> callback = keras.callbacks.EarlyStopping(monitor='loss',
    ...                                               patience=3)
    >>> # This callback will stop the training when there is no improvement in
    >>> # the loss for three consecutive epochs.
    >>> model = keras.models.Sequential([keras.layers.Dense(10)])
    >>> model.compile(keras.optimizers.SGD(), loss='mse')
    >>> history = model.fit(np.arange(100).reshape(5, 20), np.zeros(5),
    ...                     epochs=10, batch_size=1, callbacks=[callback],
    ...                     verbose=0)
    >>> len(history.history['loss'])  # Only 4 epochs are run.
    4
    c	                    t         	|           || _        || _        || _        || _        t        |      | _        d| _        d| _	        || _
        d | _        || _        |dvrt        j                  d| dd       d}|| _        d | _        y )Nr   )autominmaxzEarlyStopping mode z# is unknown, fallback to auto mode.   
stacklevelr   )super__init__monitorpatienceverbosebaselineabs	min_deltawaitstopped_epochrestore_best_weightsbest_weightsstart_from_epochwarningswarnmode
monitor_op)
selfr   r   r   r   r    r   r   r   	__class__s
            R/home/dcms/DCMS/lib/python3.12/site-packages/keras/src/callbacks/early_stopping.pyr   zEarlyStopping.__init__D   s     	  Y	$8!  0--MM%dV+NO D	    c                 d   | j                   dk(  rt        j                  | _        n2| j                   dk(  rt        j                  | _        n| j
                  j                  d      }|dk(  rt        j                  | _        t        | j                  d      rg }| j                  j                  D ]H  }t        |t        j                  t        j                  f      s.|j                  |j                         J |D ]Y  }|j                  |k(  st        |d      s |j                   dk(  rt        j                  | _        Et        j                  | _        [ | j                  t#        d| j
                   d	      | j                  t        j                  k(  r| xj$                  d
z  c_        y y )Nr   r   val_lossmetrics
_directionupz(EarlyStopping callback received monitor=z but Keras isn't able to automatically determine whether that metric should be maximized or minimized. Pass `mode='max'` in order to do early stopping based on the highest metric value, or pass `mode='min'` in order to use the lowest value.)r    r   lessr!   greaterr   removeprefixhasattrmodelr)   
isinstancer   CompileMetricsMetricsListextendnamer*   
ValueErrorr   )r"   metric_nameall_metricsms       r$   _set_monitor_opzEarlyStopping._set_monitor_ope   sV   99!hhDOYY%!kkDO,,33F;Kf$"%((tzz9- ++ 6A!)88)55 $**19956 % ;Avv,"1l3 ||t325++25((; ??":4<<. I4 4  ??chh&NNb N 'r%   c                 J    d| _         d| _        d | _        d | _        d| _        y )Nr   )r   r   bestr   
best_epochr"   logss     r$   on_train_beginzEarlyStopping.on_train_begin   s'    		 r%   c                    | j                   | j                          | j                  |      }||| j                  k  ry | j                  r2| j
                  &| j                  j                         | _        || _        | xj                  dz  c_	        | j                  || j                        ri|| _        || _        | j                  r| j                  j                         | _        | j                  | j                  || j                        rd| _	        y | j                  | j                  k\  r|dkD  r|| _        d| j                  _        y y y )N   r   T)r!   r;   get_monitor_valuer   r   r   r1   get_weightsr>   r   _is_improvementr=   r   r   r   stop_training)r"   epochr@   currents       r$   on_epoch_endzEarlyStopping.on_epoch_end   s   ??"  "((.?ed&;&;;$$):):)B !%

 6 6 8D#DO		Q	3DI#DO(($(JJ$:$:$<! }}$(<(<) 	99%%!)!&D'+DJJ$ +4%r%   c                 t   | j                   dkD  r5| j                  dkD  r&t        j                  d| j                   dz    d       | j                  rh| j
                  [| j                  dkD  r&t        j                  d| j                  dz    d       | j                  j                  | j
                         y y y )Nr   zEpoch rC   z: early stoppingz8Restoring model weights from the end of the best epoch: .)	r   r   r   	print_msgr   r   r>   r1   set_weightsr?   s     r$   on_train_endzEarlyStopping.on_train_end   s    !dllQ&6++a/00@A $$):):)F||a""2*+1.
 JJ""4#4#45 *G$r%   c                     |xs i }|j                  | j                        }|Mt        j                  d| j                   ddj	                  t        |j                                      d       |S )Nz&Early stopping conditioned on metric `z1` which is not available. Available metrics are: ,r   r   )getr   r   r   joinlistkeys)r"   r@   monitor_values      r$   rD   zEarlyStopping.get_monitor_value   sm    zr. MM<T\\N K..1hhtDIIK7H.I-JL  r%   c                 F    |y| j                  || j                  z
  |      S )NT)r!   r   )r"   rV   reference_values      r$   rF   zEarlyStopping._is_improvement   s%    "}t~~=OOr%   )val_lossr   r   r   r   NFr   )N)__name__
__module____qualname____doc__r   r;   rA   rJ   rO   rD   rF   __classcell__)r#   s   @r$   r	   r	   
   sJ    6t "B%!N ,D6Pr%   r	   )r   	keras.srcr   keras.src.api_exportr   keras.src.callbacks.callbackr   keras.src.trainersr   keras.src.utilsr   r	    r%   r$   <module>re      s>      - 1 , $ -.JPH JP /JPr%   