* Add CMake modules to find Bandicoot libraries and includes. * Add initial GitHub Actions to build against Bandicoot and run the tests. * 1. Add type proxies to select the right type based on the used backend and datatype. 2. Update IQN optimizer to build against Armadillo and Bandicoot. 3. Update IQN test cases to test against Armadillo and Bandicoot backend. 4. Update logisitic regression function, to support Armadillo and Bandicoot. * Refactor CNE optimizer and tests cases to work with Armadillo and Bandicoot datatypes. * Refactor Katyusha optimizer and tests cases to work with Armadillo and Bandicoot datatypes. * Refactor optimizers to work with Armadillo and Bandicoot datatypes: 1. AdaBelief 2. AdaBound 3. AMSBound 4. AdaGrad 5. Adam 6. Adamax 7. AMSGrad 8. Nadam 9. Nadamax 10. OptimisticAdam 11. Eve 12. FTML 13. LBFGS 14. Lookahead 15. Padam 16. QHAdam 17. SMORMS3 18. SpaleraSGD 19. SPSA 20. SWATS 21. WNGrad 22. Yogi 23. MomentumSGD 24. NesterovMomentum 25. QuasiHyperbolic 26. SGD 27. SGDR 28. SnapshotSGDR 29. CNE 30. CMAES 31. ActiveCMAES 32. PSO 33. LBestPSO 34. MOEAD 35. AugmentedLagrangian * Refactor optimizers to work with Armadillo and Bandicoot datatypes: 1. AdaDelta 2. AdaSqrt 3. BigBatchSGD 4. CoordinateDescent (CD) 5. GradientDescent 6. GridSearch 7. NSGA2 8. ParallelSGD * Refactor optimizers to work with Armadillo and Bandicoot datatypes: 1. DifferentialEvolution (DE) 2. RMSProp 3. SimulatedAnnealing (SA) 4. SARAH 5. SARAH+ 6. SVRG 7. BarzilaiBorweinDecay 8. DemonAdam 9. DemonSGD * Use inverse transform sampling to replicating arma::randg sampling since randg is not supported in Bandicoot. * Apply suggestions from code review by @rcurtin. Co-authored-by: Ryan Curtin <ryan@ratml.org> * Group test cases and fix indentations. * Update optimizer reference styling. * Add option to build against Bandicoot (by default we build against Bandicoot if found). * Mention AugLagrangianType constructor in the optimizer documentation, that allows to use a different datatype i.e. arma::fvec or coot::fvec. * Use data type specific element type for the bounds parameter. * Make sure we follow the max character line limitation from the style guide. Co-authored-by: Ryan Curtin <ryan@ratml.org> * Remove backports for outdates armadillo versions. * Indentation fixes. * Indentation fixes. * Use the correct data type during testing. * Do not use the namespace twice. * Test against CPU/OpenCL/CUDA backend. * Use the correct test case type. * We don't need Bandicoot when we test against Armadillo (CPU) backend. * Use the correct minimal Bandicoot version. Co-authored-by: Ryan Curtin <ryan@ratml.org> * Comment on the added proxies. * Merge arma and coot traits into a single file. * Apply suggestions from code review. Co-authored-by: Ryan Curtin <ryan@ratml.org> * Refactor ForwardType into two different structures to avoid std::conditional. * Remove unused proxies. * Revert CategoryType to arma::Row<size_t> since that should always stay on the CPU. * Add convenience IsMatrixType<> struct. * Individually accessed vector, so keep vector on the CPU, for faster access. * Apply suggestions from code review Co-authored-by: Ryan Curtin <ryan@ratml.org> * Kepp the indicies on the CPU. * Apply suggestions from code review. Co-authored-by: Ryan Curtin <ryan@ratml.org> * Remove outdated test case. * Use initialization list for the velocity vector. * Apply suggestions from code review Co-authored-by: Ryan Curtin <ryan@ratml.org> * Readd removed test cases for MOEAD. * Use sort_index for sorting that is supported for both armadillo and bandicoot. * Revert changes to Parallel SGD optimizer, no benefit to upload to the GPU. * Only reset if we haven't reached the end of the iterations. * Use accu to the the sum of the vector. * Use clamp instead of min, for a more efficient computation. * Add missing data type. * Use ENS_HAVE_COOT instead of USE_COOT and automatically detect when Bandicoot has already been included. * Fix incorrect initialization list. * Remove unnecessary GetFillType<MatType>::zeros, which does not work for sparse matrices. * Clean up the last few proxy functions. * Refactor problems to avoid adding extra template parameters. * NSGA2: introduce a new Optimize function that takes the front and the paretoSet, so we can avoid introducing new template parameters. * MOEAD: introduce a new Optimize function that takes the front and the paretoSet, so we can avoid introducing new template parameters. * Remove unnecessary lr matrix. * Minor cleanups for SA. * Clean up member initialization for PSO. * Update documentation for multi-objective optimizers. * Update API for Snapshots(). * Keep the MOEAD front indices on the CPU, to be more efficient. * Remove class template parameter for the bound parameter, to make the optimizer class easier. * Use the correct location for the bandicoot wrapper. * No need to set the backend for testing, we will test whatever was available during compilation. * Use the correct def to enable the bandicoot backend. * use the correct name for the def. * Fixes so that Bandicoot actually gets detected and compiled in correctly. * Oops, fix merge. * Oops, don't forget to resize the responses. * Add new Optimize(...) method to AGEMOEA that takes the front and pareto set as input. --------- Co-authored-by: Ryan Curtin <ryan@ratml.org>
222 lines
8.5 KiB
C++
222 lines
8.5 KiB
C++
/**
|
|
* @file adam.hpp
|
|
* @author Ryan Curtin
|
|
* @author Vasanth Kalingeri
|
|
* @author Marcus Edel
|
|
* @author Vivek Pal
|
|
* @author Sourabh Varshney
|
|
* @author Haritha Nair
|
|
*
|
|
* Adam, AdaMax, AMSGrad, Nadam and Nadamax optimizers. Adam is an an algorithm
|
|
* for first-order gradient-based optimization of stochastic objective
|
|
* functions, based on adaptive estimates of lower-order moments. AdaMax is
|
|
* simply a variant of Adam based on the infinity norm. AMSGrad is another
|
|
* variant of Adam with guaranteed convergence. Nadam is another variant of
|
|
* Adam based on NAG. NadaMax is a variant for Nadam based on Infinity form.
|
|
*
|
|
* ensmallen is free software; you may redistribute it and/or modify it under
|
|
* the terms of the 3-clause BSD license. You should have received a copy of
|
|
* the 3-clause BSD license along with ensmallen. If not, see
|
|
* http://www.opensource.org/licenses/BSD-3-Clause for more information.
|
|
*/
|
|
#ifndef ENSMALLEN_ADAM_ADAM_HPP
|
|
#define ENSMALLEN_ADAM_ADAM_HPP
|
|
|
|
#include <ensmallen_bits/sgd/sgd.hpp>
|
|
#include "adam_update.hpp"
|
|
#include "adamax_update.hpp"
|
|
#include "amsgrad_update.hpp"
|
|
#include "nadam_update.hpp"
|
|
#include "nadamax_update.hpp"
|
|
#include "optimisticadam_update.hpp"
|
|
|
|
namespace ens {
|
|
|
|
/**
|
|
* Adam is an optimizer that computes individual adaptive learning rates for
|
|
* different parameters from estimates of first and second moments of the
|
|
* gradients. AdaMax is a variant of Adam based on the infinity norm as given
|
|
* in the section 7 of the following paper. Nadam is an optimizer that
|
|
* combines the Adam and NAG. NadaMax is an variant of Nadam based on Infinity
|
|
* form.
|
|
*
|
|
* For more information, see the following.
|
|
*
|
|
* @code
|
|
* @article{Kingma2014,
|
|
* author = {Diederik P. Kingma and Jimmy Ba},
|
|
* title = {Adam: {A} Method for Stochastic Optimization},
|
|
* journal = {CoRR},
|
|
* year = {2014},
|
|
* url = {http://arxiv.org/abs/1412.6980}
|
|
* }
|
|
* @article{
|
|
* title = {On the convergence of Adam and beyond},
|
|
* url = {https://openreview.net/pdf?id=ryQu7f-RZ}
|
|
* year = {2018}
|
|
* }
|
|
* @endcode
|
|
*
|
|
* Adam, AdaMax, AMSGrad, Nadam, and NadaMax can optimize differentiable
|
|
* separable functions. For more details, see the documentation on function
|
|
* types included with this distribution or on the ensmallen website.
|
|
*
|
|
* @tparam UpdateRule Adam optimizer update rule to be used.
|
|
*/
|
|
template<typename UpdateRule = AdamUpdate>
|
|
class AdamType
|
|
{
|
|
public:
|
|
/**
|
|
* Construct the Adam optimizer with the given function and parameters. The
|
|
* defaults here are not necessarily good for the given problem, so it is
|
|
* suggested that the values used be tailored to the task at hand. The
|
|
* maximum number of iterations refers to the maximum number of points that
|
|
* are processed (i.e., one iteration equals one point; one iteration does not
|
|
* equal one pass over the dataset).
|
|
*
|
|
* @param stepSize Step size for each iteration.
|
|
* @param batchSize Number of points to process in a single step.
|
|
* @param beta1 Exponential decay rate for the first moment estimates.
|
|
* @param beta2 Exponential decay rate for the weighted infinity norm
|
|
estimates.
|
|
* @param eps Value used to initialise the mean squared gradient parameter.
|
|
* @param maxIterations Maximum number of iterations allowed (0 means no
|
|
* limit).
|
|
* @param tolerance Maximum absolute tolerance to terminate algorithm.
|
|
* @param shuffle If true, the function order is shuffled; otherwise, each
|
|
* function is visited in linear order.
|
|
* @param resetPolicy If true, parameters are reset before every Optimize
|
|
* call; otherwise, their values are retained.
|
|
* @param exactObjective Calculate the exact objective (Default: estimate the
|
|
* final objective obtained on the last pass over the data).
|
|
*/
|
|
AdamType(const double stepSize = 0.001,
|
|
const size_t batchSize = 32,
|
|
const double beta1 = 0.9,
|
|
const double beta2 = 0.999,
|
|
const double eps = 1e-8,
|
|
const size_t maxIterations = 100000,
|
|
const double tolerance = 1e-5,
|
|
const bool shuffle = true,
|
|
const bool resetPolicy = true,
|
|
const bool exactObjective = false);
|
|
|
|
/**
|
|
* Optimize the given function using Adam. The given starting point will be
|
|
* modified to store the finishing point of the algorithm, and the final
|
|
* objective value is returned.
|
|
*
|
|
* @tparam SeparableFunctionType Type of the function to be optimized.
|
|
* @tparam MatType Type of matrix to optimize with.
|
|
* @tparam GradType Type of matrix to use to represent function gradients.
|
|
* @tparam CallbackTypes Types of callback functions.
|
|
* @param function Function to optimize.
|
|
* @param iterate Starting point (will be modified).
|
|
* @param callbacks Callback functions.
|
|
* @return Objective value of the final point.
|
|
*/
|
|
template<typename SeparableFunctionType,
|
|
typename MatType,
|
|
typename GradType,
|
|
typename... CallbackTypes>
|
|
typename std::enable_if<IsMatrixType<GradType>::value,
|
|
typename MatType::elem_type>::type
|
|
Optimize(SeparableFunctionType& function,
|
|
MatType& iterate,
|
|
CallbackTypes&&... callbacks)
|
|
{
|
|
return optimizer.template Optimize<
|
|
SeparableFunctionType, MatType, GradType, CallbackTypes...>(
|
|
function, iterate, std::forward<CallbackTypes>(callbacks)...);
|
|
}
|
|
|
|
//! Forward the MatType as GradType.
|
|
template<typename SeparableFunctionType,
|
|
typename MatType,
|
|
typename... CallbackTypes>
|
|
typename MatType::elem_type Optimize(SeparableFunctionType& function,
|
|
MatType& iterate,
|
|
CallbackTypes&&... callbacks)
|
|
{
|
|
return Optimize<SeparableFunctionType, MatType, MatType,
|
|
CallbackTypes...>(function, iterate,
|
|
std::forward<CallbackTypes>(callbacks)...);
|
|
}
|
|
|
|
//! Get the step size.
|
|
double StepSize() const { return optimizer.StepSize(); }
|
|
//! Modify the step size.
|
|
double& StepSize() { return optimizer.StepSize(); }
|
|
|
|
//! Get the batch size.
|
|
size_t BatchSize() const { return optimizer.BatchSize(); }
|
|
//! Modify the batch size.
|
|
size_t& BatchSize() { return optimizer.BatchSize(); }
|
|
|
|
//! Get the smoothing parameter.
|
|
double Beta1() const { return optimizer.UpdatePolicy().Beta1(); }
|
|
//! Modify the smoothing parameter.
|
|
double& Beta1() { return optimizer.UpdatePolicy().Beta1(); }
|
|
|
|
//! Get the second moment coefficient.
|
|
double Beta2() const { return optimizer.UpdatePolicy().Beta2(); }
|
|
//! Modify the second moment coefficient.
|
|
double& Beta2() { return optimizer.UpdatePolicy().Beta2(); }
|
|
|
|
//! Get the value used to initialise the mean squared gradient parameter.
|
|
double Epsilon() const { return optimizer.UpdatePolicy().Epsilon(); }
|
|
//! Modify the value used to initialise the mean squared gradient parameter.
|
|
double& Epsilon() { return optimizer.UpdatePolicy().Epsilon(); }
|
|
|
|
//! Get the maximum number of iterations (0 indicates no limit).
|
|
size_t MaxIterations() const { return optimizer.MaxIterations(); }
|
|
//! Modify the maximum number of iterations (0 indicates no limit).
|
|
size_t& MaxIterations() { return optimizer.MaxIterations(); }
|
|
|
|
//! Get the tolerance for termination.
|
|
double Tolerance() const { return optimizer.Tolerance(); }
|
|
//! Modify the tolerance for termination.
|
|
double& Tolerance() { return optimizer.Tolerance(); }
|
|
|
|
//! Get whether or not the individual functions are shuffled.
|
|
bool Shuffle() const { return optimizer.Shuffle(); }
|
|
//! Modify whether or not the individual functions are shuffled.
|
|
bool& Shuffle() { return optimizer.Shuffle(); }
|
|
|
|
//! Get whether or not the actual objective is calculated.
|
|
bool ExactObjective() const { return optimizer.ExactObjective(); }
|
|
//! Modify whether or not the actual objective is calculated.
|
|
bool& ExactObjective() { return optimizer.ExactObjective(); }
|
|
|
|
//! Get whether or not the update policy parameters
|
|
//! are reset before Optimize call.
|
|
bool ResetPolicy() const { return optimizer.ResetPolicy(); }
|
|
//! Modify whether or not the update policy parameters
|
|
//! are reset before Optimize call.
|
|
bool& ResetPolicy() { return optimizer.ResetPolicy(); }
|
|
|
|
private:
|
|
//! The Stochastic Gradient Descent object with Adam policy.
|
|
SGD<UpdateRule> optimizer;
|
|
};
|
|
|
|
using Adam = AdamType<AdamUpdate>;
|
|
|
|
using AdaMax = AdamType<AdaMaxUpdate>;
|
|
|
|
using AMSGrad = AdamType<AMSGradUpdate>;
|
|
|
|
using Nadam = AdamType<NadamUpdate>;
|
|
|
|
using NadaMax = AdamType<NadaMaxUpdate>;
|
|
|
|
using OptimisticAdam = AdamType<OptimisticAdamUpdate>;
|
|
|
|
} // namespace ens
|
|
|
|
// Include implementation.
|
|
#include "adam_impl.hpp"
|
|
|
|
#endif
|