o
    oiNL                     @   s8  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 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 d dlmZ d d	lmZmZ d d
lmZ d dl m!Z!m"Z" e j#$ddursd dl%m&Z& nd dl&m&Z& erd dl'm(Z) d dl*m+Z+ edZ,e-e.Z/d8ddde0de0fddZ1G dd dZ2							d9dd ddd!e3d"e3d#e4d$e0d%ee3 d&e5de0dee2 fd'd(Z6dd de	e0ef fd)d*Z7dd d#e4d%ee3 ddfd+d,Z8dd d-e	e0ef ddfd.d/Z9G d0d1 d1eZ:G d2d3 d3eZ;G d4d5 d5eZ<dd d-e	e0ef ddfd6d7Z=dS ):    N)deepcopy)TYPE_CHECKINGAnyDictListOptionalUnion)RequirementCache)LRScheduler)override)Callback)MisconfigurationException)lightning_hasattrlightning_setattr)rank_zero_warn)STEP_OUTPUTLRSchedulerConfig
ipywidgets)tqdm)Axes
matplotlib modelpl.LightningModule	attr_namereturnc                 C   sR   |rt | |std| d|S d}|D ]}t | |r |  S qtd| d)Nz4The attribute name for the learning rate was set to zC, but could not find this as a field in `model` or `model.hparams`.)lrlearning_ratezhWhen using the learning rate finder, either `model` or `model.hparams` should have one of these fields: zb. If your model has a different name for the learning rate, set it with `.lr_find(attr_name=...)`.)r   AttributeError)r   r   attr_optionsattr r!   U/home/ubuntu/.local/lib/python3.10/site-packages/lightning/pytorch/tuner/lr_finder.py_determine_lr_attr_name0   s    


r#   c                   @   s~   e Zd ZdZdededededdf
dd	ZdddZ	dde	de	de
d de
ed  fddZddedede
e f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()

    modelr_minlr_maxnum_trainingr   Nc                 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__trainer
pl.Trainerc           
      C   s   ddl m} |jj}t|dkrtdt| d|d }| jgt|j }t|j|D ]\}}||d< ||d< q-|| j	| j
f}| jdkrJt| nt| }	|g|j_t|	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   )_validate_optimizers_attached   z(`model.configure_optimizers()` returned z;, but learning rate finder only works with single optimizerr   
initial_lrr)   step)intervalN) lightning.pytorch.core.optimizerr1   strategy
optimizerslenr   r&   param_groupszipr'   r(   r%   	_LinearLR_ExponentialLRr   lr_scheduler_configs)
r-   r/   r1   r8   	optimizernew_lrsparam_groupnew_lrargs	schedulerr!   r!   r"   _exchange_schedulerk   s    

z_LRFinder._exchange_schedulerFsuggestshowaxr   )z
plt.Figurezplt.SubFigurec           	      C   s   t stdddlm} | jd }| jd }|du r!| \}}n|j}||| | jdkr4|	d |
d |d	 |rW|  }| jrW|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 rateLoss
   ored)
markersizemarkercolor)_MATPLOTLIB_AVAILABLEr   matplotlib.pyplotpyplotr+   subplotsfigureplotr%   
set_xscale
set_xlabel
set_ylabel
suggestion_optimal_idxrG   )	r-   rF   rG   rH   pltlrslossesfig_r!   r!   r"   rW      s,   





 z_LRFinder.plotrL   r2   
skip_beginskip_endc                 C   s~   t | jd ||  }|t | }t|dk r$td d| _dS t |d }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.

        rI      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   r   )torchtensorr+   isfiniter9   rJ   errorr\   gradientargminitem)r-   rb   rc   r_   	gradientsmin_gradr!   r!   r"   r[      s   
z_LRFinder.suggestion)r/   r0   r   N)FFN)rL   r2   )__name__
__module____qualname____doc__strfloatintr.   rE   boolr   r   rW   r[   r!   r!   r!   r"   r$   E   s    


 ,r$   :0yE>r2   d   r*         @Fr/   r0   min_lrmax_lrr(   r%   early_stop_thresholdupdate_attrc	                 C   s  | 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r`td| j d |j| jd j| jd jd | jj|_t| | | jr| j  | j	
|j|_|r|  }|durt!||| td	|  | j"#|	 | j	$|	 d
| j_%d
| jj&_%d| jj&j'_(|S )a1  Enables the user to do a range test of good initial learning rates, to reduce the amount of guesswork in picking
    a good starting learning rate.

    Args:
        trainer: A Trainer instance.
        model: Model to tune.
        min_lr: minimum learning rate to investigate
        max_lr: maximum learning rate to investigate
        num_training: number of learning rates to test
        mode: Search strategy to update learning rate after each batch:

            - ``'exponential'``: Increases the learning rate exponentially.
            - ``'linear'``: Increases the learning rate linearly.

        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.
        update_attr: Whether to update the learning rate attribute or not.
        attr_name: Name of the attribute which stores the learning rate. The names 'learning_rate' or 'lr' get
            automatically detected. Otherwise, set the name here.

    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   rI   zLearning rate set to F))fast_dev_runr   r#   ospathjoindefault_root_diruuiduuid4r7   	broadcastsave_checkpointglobal_step__lr_finder_dump_params__lr_finder_reset_paramsprogress_bar_callbackdisabler$   rE   _try_loop_runrJ   infor+   update	callbacksr^   r_   fit_looptotal_batch_idxr,   __lr_finder_restore_paramsenabler[   r   _checkpoint_connectorrestoreremove_checkpoint
restarting
epoch_loopval_loop_combined_loader)r/   r   ry   rz   r(   r%   r{   r|   r   	ckpt_pathstart_stepsparams	lr_finderr   r!   r!   r"   _lr_find   sF   !




"



r   c              	   C   s0   | j j| j j| j| j| jj| jt| j	 dS )N)r8   r>   r   loggers	max_stepslimit_val_batchesloop_state_dict)
r7   r8   r>   r   r   r   r   r   r   
state_dict)r/   r!   r!   r"   r   9  s   r   c                 C   sV   ddl m} g | j_t||ddg| _| jd ur| nd | _|| j | jj	_
|| _d S )Nr   )DummyLoggerr2   )progress_bar_refresh_rate) lightning.pytorch.loggers.loggerr   r7   r>   _LRCallbackr   loggerr   r   r   r   r   )r/   r(   r{   r   r!   r!   r"   r   E  s   
r   r   c                 C   sj   |d | j _|d | j _|d | _|d | _| j}|d |j_|d | _|	t
|d  d|_d| _d S )	Nr8   r>   r   r   r   r   r   F)r7   r8   r>   r   r   r   r   r   r   load_state_dictr   r   should_stopr/   r   loopr!   r!   r"   r   R  s   



r   c                   @   s~   e Zd ZdZ			ddedee dedefd	d
Zeddddde	deddf
ddZ
edddddede	deddf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.

    rx   r   \(\?r(   r{   r   betac                 C   s:   || _ || _|| _g | _g | _d| _d| _|| _d | _d S )Ng        )	r(   r{   r   r_   r^   avg_loss	best_lossr   progress_bar)r-   r(   r{   r   r   r!   r!   r"   r.   q  s   
z_LRCallback.__init__r/   r0   	pl_moduler   batch	batch_idxr   Nc                 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.r2   r   NzFinding best initial lr)desctotal)r   r   accumulate_grad_batchesr   r   r   r(   r^   appendr>   rD   r   )r-   r/   r   r   r   r!   r!   r"   on_train_batch_start  s
   z _LRCallback.on_train_batch_startoutputsc           
      C   s  |j jd |j dkrdS |s| jtd dS | jr!| j  t|t	j
r)|n|d }|dus3J | }|j}| j| j d| j |  | _| jd| j|d    }	| jdurp|dkrp|	| j| j krpd|_| jrp| j  |j|j|_|	| jk s|dkr|	| _| j|	 dS )z>Called when the training batch ends, logs the calculated loss.r2   r   NnanrI   T)r   r   r   r_   r   rs   r   r   
isinstancere   Tensorrk   r   r   r   r{   r   r   closer7   r   )
r-   r/   r   r   r   r   loss_tensorcurrent_losscurrent_stepsmoothed_lossr!   r!   r"   on_train_batch_end  s.   


z_LRCallback.on_train_batch_end)rx   r   r   )rn   ro   rp   rq   rt   r   rs   r.   r   r   r   r   r   r!   r!   r!   r"   r   `  sP    
r   c                	       l   e Zd ZdZddejjdededef fddZ	e
d	ee fd
dZed	eeee f fddZ  ZS )r<   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                       || _ || _t || d S Nr   r   superr.   r-   r?   r   r   r   	__class__r!   r"   r.        z_LinearLR.__init__r   c                    J   j d }|j  j dkr fddjD }ntj}|_|S )Nr2   r   c                    s   g | ]}| j |   qS r!   r   .0base_lrrr-   r!   r"   
<listcomp>      z$_LinearLR.get_lr.<locals>.<listcomp>r   r   base_lrslist_lrr-   	curr_itervalr!   r   r"   get_lr     



z_LinearLR.get_lrc                 C      | j S r   r   r-   r!   r!   r"   r        z_LinearLR.lrr   rn   ro   rp   rq   re   optim	Optimizerrs   rt   r.   r   r   r   propertyr   r   __classcell__r!   r!   r   r"   r<         $$r<   c                	       r   )r=   aG  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?   r   r   r   c                    r   r   r   r   r   r!   r"   r.     r   z_ExponentialLR.__init__r   c                    r   )Nr2   r   c                    s   g | ]}|j |    qS r!   r   r   r   r!   r"   r     r   z)_ExponentialLR.get_lr.<locals>.<listcomp>r   r   r!   r   r"   r     r   z_ExponentialLR.get_lrc                 C   r   r   r   r   r!   r!   r"   r     r   z_ExponentialLR.lrr   r   r!   r!   r   r"   r=     r   r=   c                 C   s*   | j }|t|d  d|_|  d S )Nr   F)r   r   r   r   runr   r!   r!   r"   r     s   r   )r   )rv   r2   rw   r*   rx   Fr   )>	importlibloggingr~   r   copyr   typingr   r   r   r   r   r   re    lightning_utilities.core.importsr	   torch.optim.lr_schedulerr
   typing_extensionsr   lightning.pytorchpytorchpllightning.pytorch.callbacksr   &lightning.pytorch.utilities.exceptionsr   #lightning.pytorch.utilities.parsingr   r   %lightning.pytorch.utilities.rank_zeror   !lightning.pytorch.utilities.typesr   r   util	find_spec	tqdm.autor   rS   rT   r]   matplotlib.axesr   rR   	getLoggerrn   rJ   rr   r#   r$   rs   rt   ru   r   r   r   r   r   r<   r=   r   r!   r!   r!   r"   <module>   s|    
 	

d]%"%