Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implementation of Active CMAES #367

Merged
merged 37 commits into from
Aug 21, 2023
Merged
Show file tree
Hide file tree
Changes from 26 commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
670ebb2
attempt to fix current cmaes inconsistencies
SuvarshaChennareddy Jan 2, 2023
f28fd18
update tests
SuvarshaChennareddy Jan 2, 2023
39feebb
fix style, add deprecated constructor, and update tests
SuvarshaChennareddy Jan 16, 2023
4a42820
change test name
SuvarshaChennareddy Jan 16, 2023
21e2e89
remove unused code
SuvarshaChennareddy Jan 19, 2023
43f5146
update documentation, add ens_deprecated, and fix errors
SuvarshaChennareddy Apr 27, 2023
5a00748
update HISTORY.md
SuvarshaChennareddy Apr 27, 2023
ac10206
Merge branch 'master' into cmaes-fix
zoq May 24, 2023
d42f985
Tiny style fix for name of function: initialStepSize -> InitialStepSize.
rcurtin May 29, 2023
c88e0c3
Remove some more tab characters I found...
rcurtin May 29, 2023
46565e7
Compilation fixes for tests.
rcurtin May 29, 2023
716cea6
fix bug and modify tests
SuvarshaChennareddy May 31, 2023
8baccf8
add implementation of active cmaes
SuvarshaChennareddy Jun 9, 2023
52c4d63
add tests
SuvarshaChennareddy Jun 12, 2023
3c9bcfb
fix implementation error and update tests
SuvarshaChennareddy Jun 12, 2023
c937e33
remove empty line
SuvarshaChennareddy Jun 12, 2023
9ae0e6d
update cmaes tests
SuvarshaChennareddy Jun 12, 2023
b518702
Merge branch 'active-cmaes' of https://github.com/SuvarshaChennareddy…
SuvarshaChennareddy Jun 12, 2023
a0843dc
update active cmaes tests
SuvarshaChennareddy Jun 12, 2023
0cc8d0c
update tests
SuvarshaChennareddy Jun 13, 2023
37b342c
update comments
SuvarshaChennareddy Jun 13, 2023
ef63966
Update hyperparameters used in tests
SuvarshaChennareddy Jun 14, 2023
0785776
add missing comment
SuvarshaChennareddy Jul 10, 2023
3eafed5
Merge branch 'master' into active-cmaes
SuvarshaChennareddy Jul 10, 2023
c8719fb
minor comment fix in callbacks_test.cpp
SuvarshaChennareddy Jul 10, 2023
ee7b695
add patience and update termination conditions
SuvarshaChennareddy Jul 12, 2023
caaa926
move NotEmptyTransformation to its own file
SuvarshaChennareddy Aug 7, 2023
5a145e8
Fix style issues and keep the constructor.
zoq Aug 16, 2023
4f6e312
Use the correct element type and style fixes.
zoq Aug 16, 2023
c92b48e
Indentation fixes.
zoq Aug 16, 2023
e4a843b
Use the correct element type and style fixes.
zoq Aug 16, 2023
a0a9400
Make the test more stable by testing multiple times before reporting …
zoq Aug 16, 2023
25ef5ff
Update HISTORY.md.
zoq Aug 16, 2023
7bdf982
Increase number of steps to make the tests more stable.
zoq Aug 17, 2023
e828442
add documentation
SuvarshaChennareddy Aug 18, 2023
9f71c1c
No need to depreciate the CMAES constructor.
zoq Aug 21, 2023
43c0cb3
Use the correct population size.
zoq Aug 21, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions HISTORY.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
### ensmallen ?.??.?: "???"
###### ????-??-??
* LBFGS: avoid generation of NaNs, and add checks for finite values
* Implementation of Active CMAES
([#367](https://github.com/mlpack/ensmallen/pull/367)).

* Fix the current CMAES inconsistencies
([#351](https://github.com/mlpack/ensmallen/pull/351)).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this doesn't look right. the present PR is 367, and has the description of "Implementation of Active CMAES". why mention 351 here?

Copy link
Contributor Author

@SuvarshaChennareddy SuvarshaChennareddy Jul 4, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry about that! The branch of this PR (367) is actually a branch of PR 351's branch 😅. I was trying to find a cleaner way to open this PR, but couldn't really find one (that being said, is there a way?).
I know I'll have to deal with the merge conflicts if PR 351 gets merged.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll update this soon too.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggest to keep PR 351 and this PR as separate (ie. not inter-dependent). if this PR is merged first, PR 351 may then need to be updated (and vice-versa).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand, I believe (between the two if any) PR 351 will get merged first. So I would have to update this PR soon (resolving merge and conflicts and such).


* LBFGS: avoid generation of NaNs, and add checks for finite values
([#368](https://github.com/mlpack/ensmallen/pull/368)).

* Fix CNE test tolerances
* Fix CNE test tolerances
([#360](https://github.com/mlpack/ensmallen/pull/360)).

### ensmallen 2.19.1: "Eight Ball Deluxe"
Expand Down
38 changes: 25 additions & 13 deletions doc/optimizers.md
Original file line number Diff line number Diff line change
Expand Up @@ -696,35 +696,40 @@ matrix within an iterative procedure using the covariance matrix.

#### Constructors

* `CMAES<`_`SelectionPolicyType`_`>()`
* `CMAES<`_`SelectionPolicyType`_`>(`_`lambda, lowerBound, upperBound`_`)`
* `CMAES<`_`SelectionPolicyType`_`>(`_`lambda, lowerBound, upperBound, batchSize`_`)`
* `CMAES<`_`SelectionPolicyType`_`>(`_`lambda, lowerBound, upperBound, batchSize, maxIterations, tolerance, selectionPolicy`_`)`
* `CMAES<`_`SelectionPolicyType, TransformationPolicyType`_`>()`
* `CMAES<`_`SelectionPolicyType, TransformationPolicyType`_`>(`_`lambda, transformationPolicy`_`)`
* `CMAES<`_`SelectionPolicyType, TransformationPolicyType`_`>(`_`lambda, transformationPolicy, batchSize`_`)`
* `CMAES<`_`SelectionPolicyType, TransformationPolicyType`_`>(`_`lambda, transformationPolicy, batchSize, maxIterations, tolerance, selectionPolicy`_`)`
* `CMAES<`_`SelectionPolicyType, TransformationPolicyType`_`>(`_`lambda, transformationPolicy, batchSize, maxIterations, tolerance, selectionPolicy, stepSize`_`)`

The _`SelectionPolicyType`_ template parameter refers to the strategy used to
compute the (approximate) objective function. The `FullSelection` and
`RandomSelection` classes are available for use; custom behavior can be achieved
by implementing a class with the same method signatures.
The _`TransformationPolicyType`_ template parameter refers to transformation
strategy used to map decision variables to the desired domain during fitness
evaluation and optimization termination. The `EmptyTransformation` and
`BoundaryBoxConstraint` classes are available for use; custom behavior can be
achieved by implementing a class with the same method signatures.

For convenience the following types can be used:

* **`CMAES<>`** (equivalent to `CMAES<FullSelection>`): uses all separable functions to compute objective
* **`ApproxCMAES`** (equivalent to `CMAES<RandomSelection>`): uses a small amount of separable functions to compute approximate objective
* **`CMAES<>`** (equivalent to `CMAES<FullSelection, EmptyTransformation<>>`): uses all separable functions to compute objective
* **`ApproxCMAES<>`** (equivalent to `CMAES<RandomSelection, EmptyTransformation<>>`): uses a small amount of separable functions to compute approximate objective

#### Attributes

| **type** | **name** | **description** | **default** |
|----------|----------|-----------------|-------------|
| `size_t` | **`lambda`** | The population size (0 uses a default size). | `0` |
| `double` | **`lowerBound`** | Lower bound of decision variables. | `-10.0` |
| `double` | **`upperBound`** | Upper bound of decision variables. | `10.0` |
| `TransformationPolicyType` | **`transformationPolicy`** | Instantiated transformation policy used to map the coordinates to the desired domain. | `TransformationPolicyType()` |
| `size_t` | **`batchSize`** | Batch size to use for the objective calculation. | `32` |
| `size_t` | **`maxIterations`** | Maximum number of iterations. | `1000` |
| `double` | **`tolerance`** | Maximum absolute tolerance to terminate algorithm. | `1e-5` |
| `SelectionPolicyType` | **`selectionPolicy`** | Instantiated selection policy used to calculate the objective. | `SelectionPolicyType()` |

Attributes of the optimizer may also be changed via the member methods
`Lambda()`, `LowerBound()`, `UpperBound()`, `BatchSize()`, `MaxIterations()`,
`Lambda()`, `TransformationPolicy()`, `BatchSize()`, `MaxIterations()`,
`Tolerance()`, and `SelectionPolicy()`.

The `selectionPolicy` attribute allows an instantiated `SelectionPolicyType` to
Expand All @@ -733,6 +738,12 @@ the option is not relevant when the `CMAES<>` optimizer type is being used; the
`RandomSelection` policy has the constructor `RandomSelection(`_`fraction`_`)`
where _`fraction`_ specifies the percentage of separable functions to use to
estimate the objective function.
The `transformationPolicy` attribute allows an instantiated
`TransformationPolicyType` to be given. The `EmptyTransformation<`_`MatType`_`>`
has no need to be instantiated. `BoundaryBoxConstraint<`_`MatType`_`>` policy has
the constructor `BoundaryBoxConstraint(`_`lowerBound, upperBound`_`)`
where _`lowerBound`_ and _`lowerBound`_ are the lower bound and upper bound of
the coordinates respectively.

#### Examples:

Expand All @@ -744,12 +755,13 @@ estimate the objective function.
RosenbrockFunction f;
arma::mat coordinates = f.GetInitialPoint();

// CMAES with the FullSelection policy.
CMAES<> optimizer(0, -1, 1, 32, 200, 1e-4);
// CMAES with the FullSelection and BoundaryBoxConstraint policies.
BoundaryBoxConstraint b(-1, 1);
CMAES optimizer(0, b, 32, 200, 1e-4);
optimizer.Optimize(f, coordinates);

// CMAES with the RandomSelection policy.
ApproxCMAES<> approxOptimizer(0, -1, 1. 32, 200, 1e-4);
// CMAES with the RandomSelection and BoundaryBoxConstraint policies.
ApproxCMAES<BoundaryBoxConstraint<>> cmaes(0, b, 32, 200, 1e-4);
approxOptimizer.Optimize(f, coordinates);
```

Expand Down
1 change: 1 addition & 0 deletions include/ensmallen.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@
#include "ensmallen_bits/aug_lagrangian/aug_lagrangian.hpp"
#include "ensmallen_bits/bigbatch_sgd/bigbatch_sgd.hpp"
#include "ensmallen_bits/cmaes/cmaes.hpp"
#include "ensmallen_bits/cmaes/active_cmaes.hpp"
#include "ensmallen_bits/cne/cne.hpp"
#include "ensmallen_bits/de/de.hpp"
#include "ensmallen_bits/eve/eve.hpp"
Expand Down
217 changes: 217 additions & 0 deletions include/ensmallen_bits/cmaes/active_cmaes.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,217 @@
/**
* @file active_cmaes.hpp
* @author Marcus Edel
* @author Suvarsha Chennareddy
*
* Definition of the Active Covariance Matrix Adaptation Evolution Strategy
* as proposed by G.A Jastrebski and D.V Arnold in "Improving Evolution
* Strategies through Active Covariance Matrix Adaptation".
*
* 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_ACTIVE_CMAES_CMAES_HPP
#define ENSMALLEN_ACTIVE_CMAES_CMAES_HPP

#include "full_selection.hpp"
#include "random_selection.hpp"
#include "transformation_policies/empty_transformation.hpp"
#include "transformation_policies/boundary_box_constraint.hpp"

namespace ens {

/**
* Active CMA-ES is a variant of the stochastic search algorithm
* CMA-ES - Covariance Matrix Adaptation Evolution Strategy.
* Active CMA-ES actively reduces the uncertainty in unfavourable directions by
* exploiting the information about bad mutations in the covariance matrix
* update step. This isn't for the purpose of accelerating progress, but
* instead for speeding up the adaptation of the covariance matrix (which, in
* turn, will lead to faster progress).
*
* For more information, please refer to:
*
* @code
* @INPROCEEDINGS{1688662,
* author={Jastrebski, G.A. and Arnold, D.V.},
* booktitle={2006 IEEE International Conference on Evolutionary
Computation},
* title={Improving Evolution Strategies through Active Covariance
Matrix Adaptation},
* year={2006},
* volume={},
* number={},
* pages={2814-2821},
* doi={10.1109/CEC.2006.1688662}}
* @endcode
*
* Active CMA-ES can optimize separable functions. For more details, see the
* documentation on function types included with this distribution or on the
* ensmallen website.
*
* @tparam SelectionPolicy The selection strategy used for the evaluation step.
* @tparam TransformationPolicy The transformation strategy used to
* map decision variables to the desired domain during fitness evaluation
* and termination. Use EmptyTransformation if the domain isn't bounded.
*/
template<typename SelectionPolicyType = FullSelection,
typename TransformationPolicyType = EmptyTransformation<>>
class ActiveCMAES
{
public:
/**
* Construct the Active CMA-ES 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 lambda The population size (0 use the default size).
* @param transformationPolicy Instantiated transformation policy used to
* map the coordinates to the desired domain.
* @param batchSize Batch size to use for the objective calculation.
* @param maxIterations Maximum number of iterations allowed (0 means no
* limit).
* @param tolerance Maximum absolute tolerance to terminate algorithm.
* @param selectionPolicy Instantiated selection policy used to calculate the
* objective.
* @param stepSize Starting sigma/step size (will be modified).
*/
ActiveCMAES(const size_t lambda = 0,
const TransformationPolicyType&
transformationPolicy = TransformationPolicyType(),
const size_t batchSize = 32,
const size_t maxIterations = 1000,
const double tolerance = 1e-5,
const SelectionPolicyType& selectionPolicy = SelectionPolicyType(),
double stepSize = 0);

/**
* Construct the Active CMA-ES optimizer with the given function and parameters
* (including lower and upper bounds). 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).
* This constructor is deprecated.
*
* @param lambda The population size(0 use the default size).
* @param lowerBound Lower bound of decision variables.
* @param upperBound Upper bound of decision variables.
* @param batchSize Batch size to use for the objective calculation.
* @param maxIterations Maximum number of iterations allowed(0 means no
limit).
* @param tolerance Maximum absolute tolerance to terminate algorithm.
* @param selectionPolicy Instantiated selection policy used to calculate the
* objective.
* @param stepSize Starting sigma/step size (will be modified).
*/
ens_deprecated ActiveCMAES(const size_t lambda = 0,
const double lowerBound = -10,
const double upperBound = 10,
const size_t batchSize = 32,
const size_t maxIterations = 1000,
const double tolerance = 1e-5,
const SelectionPolicyType& selectionPolicy = SelectionPolicyType(),
double stepSize = 1);

/**
* Optimize the given function using Active CMA-ES. 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.
* @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... CallbackTypes>
typename MatType::elem_type Optimize(SeparableFunctionType& function,
MatType& iterate,
CallbackTypes&&... callbacks);

//! Get the population size.
size_t PopulationSize() const { return lambda; }
//! Modify the population size.
size_t& PopulationSize() { return lambda; }

//! Get the batch size.
size_t BatchSize() const { return batchSize; }
//! Modify the batch size.
size_t& BatchSize() { return batchSize; }

//! Get the maximum number of iterations (0 indicates no limit).
size_t MaxIterations() const { return maxIterations; }
//! Modify the maximum number of iterations (0 indicates no limit).
size_t& MaxIterations() { return maxIterations; }

//! Get the tolerance for termination.
double Tolerance() const { return tolerance; }
//! Modify the tolerance for termination.
double& Tolerance() { return tolerance; }

//! Get the selection policy.
const SelectionPolicyType& SelectionPolicy() const { return selectionPolicy; }
//! Modify the selection policy.
SelectionPolicyType& SelectionPolicy() { return selectionPolicy; }

//! Get the transformation policy.
const TransformationPolicyType& TransformationPolicy() const
{ return transformationPolicy; }
//! Modify the transformation policy.
TransformationPolicyType& TransformationPolicy()
{ return transformationPolicy; }

//! Get the step size.
double StepSize() const
{ return stepSize; }
//! Modify the step size.
double& StepSize()
{ return stepSize; }

private:
//! Population size.
size_t lambda;

//! The batch size for processing.
size_t batchSize;

//! The maximum number of allowed iterations.
size_t maxIterations;

//! The tolerance for termination.
double tolerance;

//! The selection policy used to calculate the objective.
SelectionPolicyType selectionPolicy;

//! The transformationPolicy used to map coordinates to the suitable domain
//! while evaluating fitness. This mapping is also done after optimization
//! has completed.
TransformationPolicyType transformationPolicy;

//! The step size.
double stepSize;
};

/**
* Convenient typedef for Active CMAES approximation.
*/
template<typename TransformationPolicyType = EmptyTransformation<>,
typename SelectionPolicyType = RandomSelection>
using ApproxActiveCMAES = ActiveCMAES<SelectionPolicyType, TransformationPolicyType>;

} // namespace ens

// Include implementation.
#include "active_cmaes_impl.hpp"

#endif
Loading