a
    dF                     @   s  d dl Z d dlZd dlZd dlZd dlmZ d dlmZmZm	Z	m
Z
mZmZmZ d dlZd dl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 d dlmZmZ d d	lmZ d d
l m!Z!m"Z"m#Z# e j$%ddurd dl&m'Z' nd dl'm'Z' edZ(ere(rd dl)m*Z+ d dl,m-Z- e.e/Z0dde1dddZ2G dd dZ3d0dde4e4e5e1ee4 e6ee3 d	ddZ7de	e1ef dd d!Z8de5ee4 dd"d#d$Z9de	e1ef dd%d&d'Z:G d(d) d)eZ;G d*d+ d+eZ<G d,d- d-eZ=de	e1ef dd%d.d/Z>dS )1    N)deepcopy)AnycastDictListOptionalTYPE_CHECKINGUnion)RequirementCache)_TORCH_LRSCHEDULER)Callback)MisconfigurationException)lightning_hasattrlightning_setattr)rank_zero_warn)LRSchedulerLRSchedulerConfigSTEP_OUTPUTZ
ipywidgets)tqdmZ
matplotlib)Axes
pl.Trainerpl.LightningModule)trainermodelreturnc                 C   sd   t | jtr0t|| js*td| j d| jS d}|D ]}t||r8|  S q8td| dd S )Nz`auto_lr_find` was set to zG, however could not find this as a field in `model` or `model.hparams`.)lrZlearning_ratez]When `auto_lr_find=True`, either `model` or `model.hparams` should have one of these fields: z overridden.)
isinstanceauto_lr_findstrr   r   )r   r   Zattr_optionsattr r    j/var/www/html/stable-diffusion-webui/venv/lib/python3.9/site-packages/pytorch_lightning/tuner/lr_finder.py_determine_lr_attr_name/   s    

r"   c                   @   sl   e Zd ZdZeeeeddddZddddd	Zde	e	e
d e
d dddZdeee
e dddZdS )	_LRFindera,  LR finder object. This object stores the results of lr_find().

    Args:
        mode: either `linear` or `exponential`, how to increase lr after each step

        lr_min: lr to start search from

        lr_max: lr to stop search

        num_training: number of steps to take between lr_min and lr_max

    Example::
        # Run lr finder
        lr_finder = trainer.lr_find(model)

        # Results stored in
        lr_finder.results

        # Plot using
        lr_finder.plot()

        # Get suggestion
        lr = lr_finder.suggestion()
    N)modelr_minlr_maxnum_trainingr   c                 C   s8   |dv sJ d|| _ || _|| _|| _i | _d| _d S )N)linearexponentialz/mode should be either `linear` or `exponential`r   )r$   r%   r&   r'   results_total_batch_idx)selfr$   r%   r&   r'   r    r    r!   __init__]   s    z_LRFinder.__init__r   r   r   c           
      C   s   ddl m} |jj}t|dkr4tdt| d|d }| jgt|j }t|j|D ]\}}||d< ||d< qZ|| j	| j
f}| jdkrt| nt| }	tt|	}	|g|j_t|	d	dd
g|j_||j|j dS )zDecorate `trainer.strategy.setup_optimizers` method such that it sets the user's originally specified
        optimizer together with a new scheduler that takes care of the learning rate search.r   )_set_scheduler_opt_idx   z(`model.configure_optimizers()` returned z;, but learning rate finder only works with single optimizerr   Z
initial_lrr(   step)intervalZopt_idxN)Z pytorch_lightning.core.optimizerr/   strategy
optimizerslenr   r%   Zparam_groupszipr&   r'   r$   	_LinearLR_ExponentialLRr   r   r   lr_scheduler_configs)
r,   r   r/   r4   	optimizerZnew_lrsZparam_groupZnew_lrargs	schedulerr    r    r!   _exchange_schedulerh   s"    


z_LRFinder._exchange_schedulerFr   z
plt.Figure)suggestshowaxr   c           	      C   s   t stdddlm} | jd }| jd }|du rB| \}}n|j}||| | jdkrh|	d |
d |d	 |r|  }| jr|j|| j || j d
ddd |r|  |S )a  Plot results from lr_find run
        Args:
            suggest: if True, will mark suggested lr to use with a red point

            show: if True, will show figure

            ax: Axes object to which the plot is to be drawn. If not provided, a new figure is created.
        zpTo use the `plot` method, you must have Matplotlib installed. Install it by running `pip install -U matplotlib`.r   Nr   lossr)   logzLearning rateZLoss
   oZred)Z
markersizemarkercolor)_MATPLOTLIB_AVAILABLEr   matplotlib.pyplotpyplotr*   Zsubplotsfigureplotr$   Z
set_xscaleZ
set_xlabelZ
set_ylabel
suggestion_optimal_idxr?   )	r,   r>   r?   r@   pltlrslossesZfig_r    r    r!   rK      s,    	





 z_LRFinder.plotrC   r0   )
skip_beginskip_endr   c                 C   sp   t | jd ||  }|t | }t|dk rHtd d| _dS t |	 }|| | _| jd | j S )a  This will propose a suggestion for an initial learning rate based on the point with the steepest
        negative gradient.

        Args:
            skip_begin: how many samples to skip in the beginning; helps to avoid too naive estimates
            skip_end: how many samples to skip in the end; helps to avoid too optimistic estimates

        Returns:
            The suggested initial learning rate to use, or `None` if a suggestion is not possible due to too few
            loss samples.
        rA      zFailed to compute suggestion for learning rate because there are not enough points. Increase the loop iteration limits or the size of your dataset/dataloader.Nr   )
nparrayr*   isfiniter5   rB   errorrM   ZgradientZargmin)r,   rR   rS   rP   Zmin_gradr    r    r!   rL      s    
z_LRFinder.suggestion)FFN)rC   r0   )__name__
__module____qualname____doc__r   floatintr-   r=   boolr   rK   rL   r    r    r    r!   r#   C   s
   )r#   :0yE>r0   d   r)         @F)	r   r   min_lrmax_lrr'   r$   early_stop_thresholdupdate_attrr   c                 C   sp  | j rtd dS |r t| |}tj| jdt  d}	| j	
|	}	| |	 | j}
t| }t| || | jr|| j  t||||}||  t| | | j||
 krtd| j d |j| jd j| jd jd | jj|_t| | | jr| j  | j	
|j|_|rL|  }|durLt!||| td	|  | j"#|	 | j	$|	 d
| j_%|S )z9See :meth:`~pytorch_lightning.tuner.tuning.Tuner.lr_find`z>Skipping learning rate finder since `fast_dev_run` is enabled.Nz	.lr_find_z.ckptzLR finder stopped early after z steps due to diverging loss.r   )r   rA   zLearning rate set to F)&Zfast_dev_runr   r"   ospathjoinZdefault_root_diruuiduuid4r3   	broadcastZsave_checkpointglobal_step__lr_finder_dump_params__lr_finder_reset_paramsZprogress_bar_callbackdisabler#   r=   _try_loop_runrB   infor*   update	callbacksrO   rP   fit_loopZtotal_batch_idxr+   __lr_finder_restore_paramsenablerL   r   Z_checkpoint_connectorrestoreZremove_checkpoint
restarting)r   r   rc   rd   r'   r$   re   rf   Zlr_attr_nameZ	ckpt_pathZstart_stepsparamsZ	lr_finderr   r    r    r!   lr_find   sB    




"



r{   r.   c                 C   s:   | j j| j j| j j| j| j| j| jj| j	t
| j d	S )N)	r4   r9   optimizer_frequenciesrt   loggersr   	max_stepslimit_val_batchesloop_state_dict)r3   r4   r9   r|   rt   r}   r   ru   r~   r   r   Z
state_dict)r   r    r    r!   rn     s    rn   )r   r'   re   r   c                 C   sb   ddl m} g | j_g | j_d| _t||ddg| _| jd urD| nd | _|| j	 | j
_|| _d S )Nr   )DummyLoggerFr0   )progress_bar_refresh_rate)Z pytorch_lightning.loggers.loggerr   r3   r9   r|   r   _LRCallbackrt   loggerrm   ru   r~   r   )r   r'   re   r   r    r    r!   ro   '  s    ro   )r   rz   r   c                 C   s   |d | j _|d | j _|d | j _|d | _|d | _|d | _|d | j_|d | _	| j}|
t|d	  d
|_d
| _d S )Nr4   r9   r|   r   rt   r}   r~   r   r   F)r3   r4   r9   r|   r   rt   r}   ru   r~   r   load_state_dictr   ry   should_stopr   rz   Zloopr    r    r!   rv   7  s    



rv   c                   @   sX   e Zd ZdZdeee eedddZdd	eed
dddZ	dd	e
eed
dddZd
S )r   a  Special callback used by the learning rate finder. This callback logs the learning rate before each batch
    and logs the corresponding loss after each batch.

    Args:
        num_training: number of iterations done by the learning rate finder
        early_stop_threshold: threshold for stopping the search. If the
            loss at any point is larger than ``early_stop_threshold*best_loss``
            then the search is stopped. To disable, set to ``None``.
        progress_bar_refresh_rate: rate to refresh the progress bar for
            the learning rate finder
        beta: smoothing value, the loss being logged is a running average of
            loss values logged until now. ``beta`` controls the forget rate i.e.
            if ``beta=0`` all past information is ignored.
    rb   r   \(\?)r'   re   r   betac                 C   s:   || _ || _|| _g | _g | _d| _d| _|| _d | _d S )Ng        )	r'   re   r   rP   rO   avg_loss	best_lossr   progress_bar)r,   r'   re   r   r   r    r    r!   r-   W  s    z_LRCallback.__init__r   r   N)r   	pl_modulebatch	batch_idxr   c                 C   sX   |j jd |j dkrdS | jr:| jdu r:td| jd| _| j|j	d j
jd  dS )zACalled before each training batch, logs the lr that will be used.r0   r   NzFinding best initial lr)desctotal)ru   r   accumulate_grad_batchesr   r   r   r'   rO   appendr9   r<   r   )r,   r   r   r   r   r    r    r!   on_train_batch_starth  s
    z _LRCallback.on_train_batch_start)r   r   outputsr   r   r   c           
      C   s   |j jd |j dkrdS | jr*| j  |j j }|dusBJ | }|j}| j	| j
 d| j	 |  | _
| j
d| j	|d    }	| jdur|dkr|	| j| j krd|_| jr| j  |j|j|_|	| jk s|dkr|	| _| j|	 dS )z>Called when the training batch ends, logs the calculated loss.r0   r   NT)ru   r   r   r   rs   Zrunning_losslastitemrm   r   r   re   r   r   closer3   rl   rP   r   )
r,   r   r   r   r   r   Zloss_tensorZcurrent_lossZcurrent_stepZsmoothed_lossr    r    r!   on_train_batch_endt  s&    


z_LRCallback.on_train_batch_end)rb   r   r   )rY   rZ   r[   r\   r^   r   r]   r-   r   r   r   r   r    r    r    r!   r   G  s       
r   c                       sb   e Zd ZdZdejjeeed fddZ	e
e dddZeeee
e f dd	d
Z  ZS )r7   a<  Linearly increases the learning rate between two boundaries over a number of iterations.

    Args:

        optimizer: wrapped optimizer.

        end_lr: the final learning rate.

        num_iter: the number of iterations over which the test occurs.

        last_epoch: the index of last epoch. Default: -1.
    r:   end_lrnum_iter
last_epochc                    s   || _ || _t || d S Nr   r   superr-   r,   r:   r   r   r   	__class__r    r!   r-     s    z_LinearLR.__init__r   c                    sP   j d }|j  j dkr6 fddjD }ndd jD }|_|S )Nr0   r   c                    s   g | ]}| j |   qS r    r   .0Zbase_lrrr,   r    r!   
<listcomp>      z$_LinearLR.get_lr.<locals>.<listcomp>c                 S   s   g | ]}|qS r    r    r   r    r    r!   r     r   r   r   Zbase_lrs_lrr,   Z	curr_itervalr    r   r!   get_lr  s    


z_LinearLR.get_lrc                 C   s   | j S r   r   r,   r    r    r!   r     s    z_LinearLR.lr)r   rY   rZ   r[   r\   torchZoptimZ	Optimizerr]   r^   r-   r   r   propertyr	   r   __classcell__r    r    r   r!   r7     s
   r7   c                       sb   e Zd ZdZdejjeeed fddZ	e
e dddZeeee
e f dd	d
Z  ZS )r8   aF  Exponentially increases the learning rate between two boundaries over a number of iterations.

    Arguments:

        optimizer: wrapped optimizer.

        end_lr: the final learning rate.

        num_iter: the number of iterations over which the test occurs.

        last_epoch: the index of last epoch. Default: -1.
    r   r   c                    s   || _ || _t || d S r   r   r   r   r    r!   r-     s    z_ExponentialLR.__init__r   c                    sP   j d }|j  j dkr6 fddjD }ndd jD }|_|S )Nr0   r   c                    s   g | ]}|j |    qS r    r   r   r   r    r!   r     r   z)_ExponentialLR.get_lr.<locals>.<listcomp>c                 S   s   g | ]}|qS r    r    r   r    r    r!   r     r   r   r   r    r   r!   r     s    


z_ExponentialLR.get_lrc                 C   s   | j S r   r   r   r    r    r!   r     s    z_ExponentialLR.lr)r   r   r    r    r   r!   r8     s
   r8   c                 C   s*   | j }|t|d  d|_|  d S )Nr   F)ru   r   r   ry   runr   r    r    r!   rq     s    rq   )r`   r0   ra   r)   rb   F)?	importlibloggingrg   rj   copyr   typingr   r   r   r   r   r   r	   numpyrU   r   Z lightning_utilities.core.importsr
   Zpytorch_lightningplZ lightning_fabric.utilities.typesr   Zpytorch_lightning.callbacksr   Z&pytorch_lightning.utilities.exceptionsr   Z#pytorch_lightning.utilities.parsingr   r   Z%pytorch_lightning.utilities.rank_zeror   Z!pytorch_lightning.utilities.typesr   r   r   util	find_specZ	tqdm.autor   rG   rH   rI   rN   Zmatplotlib.axesr   	getLoggerrY   rB   r   r"   r#   r]   r^   r_   r{   rn   ro   rv   r   r7   r8   rq   r    r    r    r!   <module>   sd   $
       LP##