o
    zi-                     @   s   d Z ddlZddlmZmZmZmZmZ ddlZddlm	Z	 ddl
mZ ddlZddlmZ ddlmZ ddlmZmZ eeZG d	d
 d
eZdS )z]
Early Stopping
^^^^^^^^^^^^^^

Monitor a metric and stop training when it stops improving.

    N)AnyCallableDictOptionalTuple)Tensor)override)Callback)MisconfigurationException)rank_prefixed_messagerank_zero_warnc                       s  e Zd ZdZejejdZdddZ									
	
	
	d<de	de
dedede	dededee
 dee
 dee def fddZeede	fddZeddddde	dd
fd d!Zd"ee	ef defd#d$Zedefd%d&Zedee	ef fd'd(Zed)ee	ef dd
fd*d+Zdddefd,d-Zed=d.d/Zed=d0d1Zd>d2d3Zd4edeeee	 f fd5d6Z d4ede	fd7d8Z!e"ddd9e	dedd
fd:d;Z#  Z$S )?EarlyStoppinga
  Monitor a metric and stop training when it stops improving.

    Args:
        monitor: quantity to be monitored.
        min_delta: minimum change in the monitored quantity to qualify as an improvement, i.e. an absolute
            change of less than or equal to `min_delta`, will count as no improvement.
        patience: number of checks with no improvement
            after which training will be stopped. Under the default configuration, one check happens after
            every training epoch. However, the frequency of validation can be modified by setting various parameters on
            the ``Trainer``, for example ``check_val_every_n_epoch`` and ``val_check_interval``.

            .. note::

                It must be noted that the patience parameter counts the number of validation checks with
                no improvement, and not the number of training epochs. Therefore, with parameters
                ``check_val_every_n_epoch=10`` and ``patience=3``, the trainer will perform at least 40 training
                epochs before being stopped.

        verbose: verbosity mode.
        mode: one of ``'min'``, ``'max'``. In ``'min'`` mode, training will stop when the quantity
            monitored has stopped decreasing and in ``'max'`` mode it will stop when the quantity
            monitored has stopped increasing.
        strict: whether to crash the training if `monitor` is not found in the validation metrics.
        check_finite: When set ``True``, stops training when the monitor becomes NaN or infinite.
        stopping_threshold: Stop training immediately once the monitored quantity reaches this threshold.
        divergence_threshold: Stop training as soon as the monitored quantity becomes worse than this threshold.
        check_on_train_epoch_end: whether to run early stopping at the end of the training epoch.
            If this is ``False``, then the check runs at the end of the validation.
        log_rank_zero_only: When set ``True``, logs the status of the early stopping callback only for rank 0 process.

    Raises:
        MisconfigurationException:
            If ``mode`` is none of ``"min"`` or ``"max"``.
        RuntimeError:
            If the metric ``monitor`` is not available.

    Example::

        >>> from pytorch_lightning import Trainer
        >>> from pytorch_lightning.callbacks import EarlyStopping
        >>> early_stopping = EarlyStopping('val_loss')
        >>> trainer = Trainer(callbacks=[early_stopping])

    .. tip:: Saving and restoring multiple early stopping callbacks at the same time is supported under variation in the
        following arguments:

        *monitor, mode*

        Read more: :ref:`Persisting Callback State <extensions/callbacks_state:save callback state>`

    )minmax<>           Fr   TNmonitor	min_deltapatienceverbosemodestrictcheck_finitestopping_thresholddivergence_thresholdcheck_on_train_epoch_endlog_rank_zero_onlyc                    s   t    || _|| _|| _|| _|| _|| _|| _|| _	|	| _
d| _d| _|
| _|| _| j| jvrCtdd| j  d| j |  j| jtjkrNdnd9  _ttj}| jtjkrc|| _d S | | _d S )Nr   z`mode` can be z, z, got    )super__init__r   r   r   r   r   r   r   r   r   
wait_countstopped_epoch_check_on_train_epoch_endr   	mode_dictr
   joinkeys
monitor_optorchgttensorinflt
best_score)selfr   r   r   r   r   r   r   r   r   r   r   	torch_inf	__class__ ^/home/ubuntu/.local/lib/python3.10/site-packages/pytorch_lightning/callbacks/early_stopping.pyr"   ^   s&   
""zEarlyStopping.__init__returnc                 C   s   | j | j| jdS )N)r   r   )_generate_state_keyr   r   r0   r4   r4   r5   	state_key   s   zEarlyStopping.state_keytrainer
pl.Trainer	pl_modulepl.LightningModulestagec                 C   s(   | j d u r|jdko|jdk| _ d S d S )Ng      ?r   )r%   val_check_intervalcheck_val_every_n_epoch)r0   r:   r<   r>   r4   r4   r5   setup   s   
zEarlyStopping.setuplogsc                 C   sb   | | j}d| j ddt|  d}|d u r/| jr"t|| jdkr-t|t	d dS dS )	Nz&Early stopping conditioned on metric `zh` which is not available. Pass in or modify your `EarlyStopping` callback to use any of the following: `z`, ``r   )categoryFT)
getr   r'   listr(   r   RuntimeErrorr   r   RuntimeWarning)r0   rB   monitor_val	error_msgr4   r4   r5   _validate_condition_metric   s   

z(EarlyStopping._validate_condition_metricc                 C   s   | j | j S N)r&   r   r8   r4   r4   r5   r)      s   zEarlyStopping.monitor_opc                 C   s   | j | j| j| jdS )Nr#   r$   r/   r   rM   r8   r4   r4   r5   
state_dict   s
   zEarlyStopping.state_dictrN   c                 C   s,   |d | _ |d | _|d | _|d | _d S )Nr#   r$   r/   r   rM   )r0   rN   r4   r4   r5   load_state_dict   s   


zEarlyStopping.load_state_dictc                 C   s    ddl m} |jj|jkp|jS )Nr   )	TrainerFn) pytorch_lightning.trainer.statesrP   statefnFITTINGsanity_checking)r0   r:   rP   r4   r4   r5   _should_skip_check   s   z EarlyStopping._should_skip_checkc                 C   s"   | j r| |r
d S | | d S rL   r%   rV   _run_early_stopping_checkr0   r:   r<   r4   r4   r5   on_train_epoch_end      z EarlyStopping.on_train_epoch_endc                 C   s"   | j s| |r
d S | | d S rL   rW   rY   r4   r4   r5   on_validation_end   r[   zEarlyStopping.on_validation_endc                 C   s   |j }|js| |sdS || j  }| |\}}|jj|dd}|jp'||_|r/|j	| _
|r>| jr@| ||| j dS dS dS )zdChecks whether the early stopping condition is met and if so tells the trainer to stop the training.NF)all)callback_metricsfast_dev_runrK   r   squeeze_evaluate_stopping_criteriastrategyreduce_boolean_decisionshould_stopcurrent_epochr$   r   	_log_infor   )r0   r:   rB   currentrd   reasonr4   r4   r5   rX      s   

z'EarlyStopping._run_early_stopping_checkrg   c              	   C   sf  d}d }| j r!t|s!d}d| j d| d| jdd}||fS | jd urH| || jrHd}d| j d| d	| j| j  d	| j d	}||fS | j	d urq| | | j	 rqd}d
| j d| d	| j| j  d	| j	 d	}||fS | || j
 | j|jrd}| |}|| _d| _||fS |  jd7  _| j| jkrd}d| j d| j d| jdd}||fS )NFTzMonitored metric z = z( is not finite. Previous best value was .3fz. Signaling Trainer to stop.zStopping threshold reached:  zDivergence threshold reached: r   r   z did not improve in the last z records. Best score: )r   r*   isfiniter   r/   r   r)   
order_dictr   r   r   todevice_improvement_messager#   r   )r0   rg   rd   rh   r4   r4   r5   ra      sb    



z)EarlyStopping._evaluate_stopping_criteriac              	   C   sZ   t | jr!d| j dt| j| ddt| j d|d}|S d| j d|d}|S )zXFormats a log message that informs the user about an improvement in the monitored score.zMetric z improved by ri   z >= min_delta = z. New best score: z improved. New best score: )r*   rk   r/   r   absr   )r0   rg   msgr4   r4   r5   ro     s   z"EarlyStopping._improvement_messagemessagec                 C   sD   | j dkr| jnd }t||}|d u s|r|dkr t| d S d S )Nr   r   )
world_sizeglobal_rankr   loginfo)r:   rr   r   rankr4   r4   r5   rf     s
   
zEarlyStopping._log_info)
r   r   Fr   TTNNNF)r:   r;   r<   r=   r6   N)r:   r;   r6   N)%__name__
__module____qualname____doc__r*   r.   r+   r&   rl   strfloatintboolr   r"   propertyr   r9   rA   r   r   rK   r   r)   r   rN   rO   rV   rZ   r\   rX   r   ra   ro   staticmethodrf   __classcell__r4   r4   r2   r5   r   %   sv    4
	
$
'$r   )r{   loggingtypingr   r   r   r   r   r*   r   typing_extensionsr   pytorch_lightningpl$pytorch_lightning.callbacks.callbackr	   &pytorch_lightning.utilities.exceptionsr
   %pytorch_lightning.utilities.rank_zeror   r   	getLoggerrx   ru   r   r4   r4   r4   r5   <module>   s   
