o
    i e                     @   sT   d Z ddlm  mZ ddlmZ ddlmZ edddgdG dd	 d	ej	Z
dS )
zSGD optimizer implementation.    N)optimizer_v2)keras_exportzkeras.optimizers.legacy.SGDzkeras.optimizers.SGD)v1c                       sn   e Zd ZdZdZ				 d fdd	Zdd	 Z fd
dZdddZ fddZ	dddZ
 fddZ  ZS )SGDa
  Gradient descent (with momentum) optimizer.

    Update rule for parameter `w` with gradient `g` when `momentum=0`:

    ```python
    w = w - learning_rate * g
    ```

    Update rule when `momentum` is larger than 0:

    ```python
    velocity = momentum * velocity - learning_rate * g
    w = w + velocity
    ```

    When `nesterov=True`, this rule becomes:

    ```python
    velocity = momentum * velocity - learning_rate * g
    w = w + momentum * velocity - learning_rate * g
    ```

    Args:
      learning_rate: A `Tensor`, floating point value, or a schedule that is a
        `tf.keras.optimizers.schedules.LearningRateSchedule`, or a callable
        that takes no arguments and returns the actual value to use. The
        learning rate. Defaults to `0.01`.
      momentum: float hyperparameter >= 0 that accelerates gradient descent in
        the relevant direction and dampens oscillations. Vanilla gradient
        descent means no momentum. Defaults to `0.`.
      nesterov: boolean. Whether to apply Nesterov momentum.
        Defaults to `False`.
      name: Optional name prefix for the operations created when applying
        gradients.  Defaults to `"SGD"`.
      **kwargs: keyword arguments. Allowed arguments are `clipvalue`,
        `clipnorm`, `global_clipnorm`.
        If `clipvalue` (float) is set, the gradient of each weight
        is clipped to be no higher than this value.
        If `clipnorm` (float) is set, the gradient of each weight
        is individually clipped so that its norm is no higher than this value.
        If `global_clipnorm` (float) is set the gradient of all weights is
        clipped so that their global norm is no higher than this value.

    Usage:

    >>> opt = tf.keras.optimizers.legacy.SGD(learning_rate=0.1)
    >>> var = tf.Variable(1.0)
    >>> loss = lambda: (var ** 2)/2.0         # d(loss)/d(var1) = var1
    >>> step_count = opt.minimize(loss, [var]).numpy()
    >>> # Step is `- learning_rate * grad`
    >>> var.numpy()
    0.9

    >>> opt = tf.keras.optimizers.legacy.SGD(learning_rate=0.1, momentum=0.9)
    >>> var = tf.Variable(1.0)
    >>> val0 = var.value()
    >>> loss = lambda: (var ** 2)/2.0         # d(loss)/d(var1) = var1
    >>> # First step is `- learning_rate * grad`
    >>> step_count = opt.minimize(loss, [var]).numpy()
    >>> val1 = var.value()
    >>> (val0 - val1).numpy()
    0.1
    >>> # On later steps, step-size increases because of momentum
    >>> step_count = opt.minimize(loss, [var]).numpy()
    >>> val2 = var.value()
    >>> (val1 - val2).numpy()
    0.18

    Reference:
        - For `nesterov=True`, See [Sutskever et al., 2013](
          https://github.com/mlresearch/v28/blob/gh-pages/sutskever13.pdf).
    T{Gz?        Fc                    s   t  j|fi | | d|d| | d| j d| _t|tjs,t	|s,|dkr/d| _t|t
tfrK|dk s>|dkrKtd| d	t| d
| d| || _d S )Nlearning_ratelrdecayFr   T   z6`momentum` must be between [0, 1]. Received: momentum=z
 (of type z).momentum)super__init__
_set_hyperget_initial_decay	_momentum
isinstancetfTensorcallableintfloat
ValueErrortypenesterov)selfr   r   r   namekwargs	__class__ [/var/www/myenv/lib/python3.10/site-packages/keras/src/optimizers/legacy/gradient_descent.pyr   j   s*   

zSGD.__init__c                 C   s$   | j r|D ]
}| |d qd S d S Nr   )r   add_slot)r   var_listvarr!   r!   r"   _create_slots   s
   zSGD._create_slotsc                    s2   t  ||| t| d||||f d< d S r#   )r   _prepare_localr   identity
_get_hyper)r   
var_device	var_dtypeapply_stater   r!   r"   r(      s   
zSGD._prepare_localNc              	   C   s   |j |jj}}|pi ||fp| ||}| jr5| |d}tjj	|j
|j
|d ||d | j| jdS tjj|j
|d || jdS )Nr   lr_t)r&   accumr	   gradr   use_lockinguse_nesterov)r&   alphadeltar1   )devicedtype
base_dtyper   _fallback_apply_stater   get_slotr   raw_opsResourceApplyKerasMomentumhandle_use_lockingr   ResourceApplyGradientDescent)r   r0   r&   r-   r+   r,   coefficientsmomentum_varr!   r!   r"   _resource_apply_dense   s.   

zSGD._resource_apply_densec                    sn   | j rt j|||fi |S |j|jj}}|di ||fp'| ||}tj	j
|j|| |d  dS )Nr-   r.   )resourceindicesupdates)r   r   (_resource_apply_sparse_duplicate_indicesr5   r6   r7   r   r8   r   r:   ResourceScatterAddr<   )r   r0   r&   rC   r   r+   r,   r?   r   r!   r"   rE      s"   
z,SGD._resource_apply_sparse_duplicate_indicesc           	   
   C   sf   |j |jj}}|pi ||fp| ||}| |d}tjj|j	|j	|d |||d | j
| jdS )Nr   r.   )r&   r/   r	   r0   rC   r   r1   r2   )r5   r6   r7   r   r8   r9   r   r:    ResourceSparseApplyKerasMomentumr<   r=   r   )	r   r0   r&   rC   r-   r+   r,   r?   r@   r!   r!   r"   _resource_apply_sparse   s"   
zSGD._resource_apply_sparsec                    s2   t   }|| d| j| d| jd |S )Nr   r   )r   r
   r   r   )r   
get_configupdate_serialize_hyperparameterr   r   )r   configr   r!   r"   rI      s   

zSGD.get_config)r   r   Fr   )N)__name__
__module____qualname____doc___HAS_AGGREGATE_GRADr   r'   r(   rA   rE   rH   rI   __classcell__r!   r!   r   r"   r      s    I

r   )rP   tensorflow.compat.v2compatv2r   keras.src.optimizers.legacyr    tensorflow.python.util.tf_exportr   OptimizerV2r   r!   r!   r!   r"   <module>   s   