Source code for queens.stochastic_optimizers.rms_prop
#
# SPDX-License-Identifier: LGPL-3.0-or-later
# Copyright (c) 2024-2025, QUEENS contributors.
#
# This file is part of QUEENS.
#
# QUEENS is free software: you can redistribute it and/or modify it under the terms of the GNU
# Lesser General Public License as published by the Free Software Foundation, either version 3 of
# the License, or (at your option) any later version. QUEENS is distributed in the hope that it will
# be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You
# should have received a copy of the GNU Lesser General Public License along with QUEENS. If not,
# see <https://www.gnu.org/licenses/>.
#
"""RMSprop optimizer."""
import logging
import numpy as np
from queens.stochastic_optimizers.stochastic_optimizer import StochasticOptimizer
from queens.utils.iterative_averaging_utils import ExponentialAveraging
_logger = logging.getLogger(__name__)
[docs]
class RMSprop(StochasticOptimizer):
r"""RMSprop stochastic optimizer [1].
References:
[1] Tieleman and Hinton. "Lecture 6.5-rmsprop: Divide the gradient by a running average of
its recent magnitude". Coursera. 2012.
Attributes:
beta (float): :math:`\beta` parameter as described in [1].
v (ExponentialAveragingObject): Exponential average of the gradient momentum.
eps (float): Nugget term to avoid a division by values close to zero.
"""
_name = "RMSprop Stochastic Optimizer"
def __init__(
self,
learning_rate,
optimization_type,
rel_l1_change_threshold,
rel_l2_change_threshold,
clip_by_l2_norm_threshold=np.inf,
clip_by_value_threshold=np.inf,
max_iteration=1e6,
beta=0.999,
eps=1e-8,
learning_rate_decay=None,
):
"""Initialize optimizer.
Args:
learning_rate (float): Learning rate for the optimizer
optimization_type (str): "max" in case of maximization and "min" for minimization
rel_l1_change_threshold (float): If the L1 relative change in parameters falls below
this value, this criterion catches.
rel_l2_change_threshold (float): If the L2 relative change in parameters falls below
this value, this criterion catches.
clip_by_l2_norm_threshold (float): Threshold to clip the gradient by L2-norm
clip_by_value_threshold (float): Threshold to clip the gradient components
max_iteration (int): Maximum number of iterations
beta (float): :math:`beta` parameter as described in [1]
eps (float): Nugget term to avoid a division by values close to zero
learning_rate_decay (LearningRateDecay): Object to schedule learning rate decay
"""
super().__init__(
learning_rate=learning_rate,
optimization_type=optimization_type,
rel_l1_change_threshold=rel_l1_change_threshold,
rel_l2_change_threshold=rel_l2_change_threshold,
clip_by_l2_norm_threshold=clip_by_l2_norm_threshold,
clip_by_value_threshold=clip_by_value_threshold,
max_iteration=max_iteration,
learning_rate_decay=learning_rate_decay,
)
self.beta = beta
self.v = ExponentialAveraging(coefficient=beta)
self.eps = eps
[docs]
def scheme_specific_gradient(self, gradient):
"""Rmsprop gradient computation.
Args:
gradient (np.array): Gradient
Returns:
gradient (np.array): RMSprop gradient
"""
if self.iteration == 0:
self.v.current_average = np.zeros(gradient.shape)
v_hat = self.v.update_average(gradient**2)
v_hat /= 1 - self.beta ** (self.iteration + 1)
gradient = gradient / (v_hat**0.5 + self.eps)
return gradient