U
    ¯Ê¹jø  ã                   @   s4   d Z ddlZddlmZ ddlZG dd„ deƒZdS )a6   Nvidia NovoGrad Optimizer.
Original impl by Nvidia from Jasper example:
    - https://github.com/NVIDIA/DeepLearningExamples/blob/master/PyTorch/SpeechRecognition/Jasper
Paper: `Stochastic Gradient Methods with Layer-wise Adaptive Moments for Training of Deep Networks`
    - https://arxiv.org/abs/1905.11286
é    N)Ú	Optimizerc                       s@   e Zd ZdZd‡ fdd„	Z‡ fd	d
„Ze ¡ ddd„ƒZ‡  Z	S )Ú
NvNovoGrada(  
    Implements Novograd algorithm.

    Args:
        params (iterable): iterable of parameters to optimize or dicts defining
            parameter groups
        lr (float, optional): learning rate (default: 1e-3)
        betas (Tuple[float, float], optional): coefficients used for computing
            running averages of gradient and its square (default: (0.95, 0.98))
        eps (float, optional): term added to the denominator to improve
            numerical stability (default: 1e-8)
        weight_decay (float, optional): weight decay (L2 penalty) (default: 0)
        grad_averaging: gradient averaging
        amsgrad (boolean, optional): whether to use the AMSGrad variant of this
            algorithm from the paper `On the Convergence of Adam and Beyond`_
            (default: False)
    çü©ñÒMbP?©gffffffî?g\�Âõ(\ï?ç:Œ0âŽyE>r   Fc           	         s®   d|kst d |¡ƒ‚d|ks,t d |¡ƒ‚d|d   krDdk sXn t d |d ¡ƒ‚d|d   krpdk s„n t d |d ¡ƒ‚t||||||d	�}tt| ƒ ||¡ d S )
Ng        zInvalid learning rate: {}zInvalid epsilon value: {}r   g      ð?z%Invalid beta parameter at index 0: {}é   z%Invalid beta parameter at index 1: {})ÚlrÚbetasÚepsÚweight_decayÚgrad_averagingÚamsgrad)Ú
ValueErrorÚformatÚdictÚsuperr   Ú__init__)	ÚselfÚparamsr   r	   r
   r   r   r   Údefaults©Ú	__class__© úT/var/www/html/bwave/python/venv/lib/python3.8/site-packages/timm/optim/nvnovograd.pyr       s    ýzNvNovoGrad.__init__c                    s,   t t| ƒ |¡ | jD ]}| dd¡ qd S )Nr   F)r   r   Ú__setstate__Úparam_groupsÚ
setdefault)r   ÚstateÚgroupr   r   r   r   1   s    
zNvNovoGrad.__setstate__Nc              	   C   sð  d}|dk	r&t  ¡ � |ƒ }W 5 Q R X | jD �]¼}|d D �]¬}|jdkrLq:|j}|jr`tdƒ‚|d }| j| }t|ƒdkrÌd|d< t  |¡|d< t  	g ¡ 
|d j¡|d< |rÌt  	g ¡ 
|d j¡|d	< |d |d  }}	|rê|d	 }
|d
 \}}|d  d7  < t  t  |d¡¡}|	dk�r.|	 |¡ n|	 |¡j|d| d� |�rpt j|
|	|
d� |
 ¡  |d ¡}n|	 ¡  |d ¡}| |¡ |d dk�r¬|j||d d� |d �rÄ| d| ¡ | |¡ |¡ |j||d  d� q:q,|S )z²Performs a single optimization step.

        Arguments:
            closure (callable, optional): A closure that reevaluates the model
            and returns the loss.
        Nr   z#Sparse gradients are not supported.r   r   ÚstepÚexp_avgÚ
exp_avg_sqÚmax_exp_avg_sqr	   r   é   )Úalpha)Úoutr
   r   r   r   )ÚtorchZenable_gradr   ÚgradZ	is_sparseÚRuntimeErrorr   ÚlenZ
zeros_likeZzerosÚtoZdeviceÚsumÚpowZcopy_Zmul_Zadd_ÚmaxÚsqrtZdiv_)r   ÚclosureZlossr   Úpr'   r   r   r    r!   r"   Zbeta1Zbeta2ZnormÚdenomr   r   r   r   6   sP    





zNvNovoGrad.step)r   r   r   r   FF)N)
Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r   r&   Zno_gradr   Ú__classcell__r   r   r   r   r      s         ÿr   )r5   r&   Ztorch.optim.optimizerr   Úmathr   r   r   r   r   Ú<module>   s   