class CMAAdaptSigmaTPA(CMAAdaptSigmaBase):
Constructor: CMAAdaptSigmaTPA(dimension, opts, **kwargs)
two point adaptation for step-size sigma.
Relies on a specific sampling of the first two offspring, whose
objective function value ranks are used to decide on the step-size
change, see update for the specifics.
Example
>>> import cma >>> cma.CMAOptions('adapt').pprint() # doctest: +ELLIPSIS AdaptSigma='True... >>> es = cma.CMAEvolutionStrategy(10 * [0.2], 0.1, ... {'AdaptSigma': cma.sigma_adaptation.CMAAdaptSigmaTPA, ... 'ftarget': 1e-8}) # doctest: +ELLIPSIS (5_w,10)-aCMA-ES (mu_w=3.2,w_1=45%) in dimension 10 (seed=... >>> es.optimize(cma.ff.rosen) # doctest: +ELLIPSIS Iter... >>> assert 'ftarget' in es.stop() >>> assert es.result[1] <= 1e-8 # should coincide with the above >>> assert es.result[2] < 6500 # typically < 5500
References: loosely based on Hansen 2008, CMA-ES with Two-Point Step-Size Adaptation, more tightly reflecting Hansen et al. 2014, How to Assess Step-Size Adaptation Mechanisms in Randomized Search and Akimoto & Hansen 2020, Diagonal Acceleration for Covariance...
TODO: collect data for ._last_z and/or .s distributions, namely on the stationary sphere with sigma in [sigma_opt, 2 * sigma_opt] or as a function of the convergence rate and depending on popsize: is |s| decreasing with increasing popsize and how? Can we compute hsig based on s instead ps?
| Method | __init__ |
popsize is a valid kwargs |
| Method | check |
make consistency checks with a CMAEvolutionStrategy instance as input |
| Method | initialize |
late initialization based on CMAEvolutionStrategy. |
| Method | initialize |
set parameters in .sp based on an CMAEvolutionStrategy instance |
| Method | update |
update es.sigma *= self.update2(...). |
| Method | update2 |
update state variables and return the step-size multiplier. |
| Instance Variable | delta |
all sigma changes multiplied |
| Instance Variable | dimension |
with the default averaging coefficient, the first two entries dominate all others: c = 1/2 <==> 1/c * 1/2 == 1 meaning the first entry == 1 takes half of the weight c = 0.29289 = 1 - sqrt(1/2) <==> 1/c * 1/2 == 1 + 1-c meaning the first two entries take half of the weight, where "the full" weight is 1/c = sum_{i=0}^infty (1-c)^i... |
| Instance Variable | initialized |
Undocumented |
| Instance Variable | s |
the state/summation variable |
| Instance Variable | sp |
parameter settings |
| Instance Variable | _es |
Undocumented |
| Instance Variable | _last |
Undocumented |
| Instance Variable | _last |
Undocumented |
| Instance Variable | _popsize |
Undocumented |
Inherited from CMAAdaptSigmaBase:
| Method | hsig |
return "OK-signal" for rank-one update. |
| Method | initialize |
set parameters and state variable based on dimension, mueff and possibly further options. |
| Instance Variable | cs |
Undocumented |
| Instance Variable | is |
Undocumented |
| Instance Variable | ps |
Undocumented |
| Method | _update |
update the isotropic evolution path. |
| Instance Variable | _ps |
Undocumented |
late initialization based on CMAEvolutionStrategy.
Argument N is either the dimension (for backward compatibility) or a
CMAEvolutionStrategy instance. opts and popsize are ignored in the
latter case.
Argument opts is equivalent with N.opts, used for
'TPA_dampfac', verbosity behavior and hacking (very versatile).
Unless bool(reset) is True, initialize does not overwrite
parameters or state variables unless their value is None or they are
in the _attributes_to_not_recover_on_init list.
The following mainly tests the (new) reset behavior:
>>> import cma # test sp.damp value and reset behavior (minor) >>> es = cma.CMAEvolutionStrategy(2 * [1], 1, {'verbose':-9, ... 'AdaptSigma': cma.sigma_adaptation.CMAAdaptSigmaTPA}) >>> assert 4.85888 < es.adapt_sigma.sp.damp < 4.85889, es.adapt_sigma.sp.__dict__ >>> es.adapt_sigma.sp.damp = 1.234 >>> _ = es.adapt_sigma.initialize(es) >>> assert es.adapt_sigma.sp.damp == 1.234, es.adapt_sigma.sp.__dict__ >>> _ = es.adapt_sigma.initialize(es) >>> assert es.adapt_sigma.sp.damp == 1.234, es.adapt_sigma.sp.__dict__ >>> es.adapt_sigma.is_initialized = False >>> _ = es.adapt_sigma.initialize(es) >>> assert es.adapt_sigma.sp.damp == 1.234, es.adapt_sigma.sp.__dict__ >>> _ = es.adapt_sigma.initialize(es, reset=True) # reset everything >>> assert 4.85888 < es.adapt_sigma.sp.damp < 4.85889, es.adapt_sigma.sp.__dict__ >>> es.adapt_sigma.sp.damp = 1.234 >>> _ = es.optimize(cma.ff.elli, iterations = 4) >>> assert es.adapt_sigma.sp.damp == 1.234, es.adapt_sigma.sp.__dict__
set parameters in .sp based on an CMAEvolutionStrategy instance
or on the previously stored .dimension, ._es_opts, ._popsize. These
attributes could be modified to compute a respective setting. Any
existing setting is overwritten only if bool(reset) is True or the
respective parameter value in .sp is None.
update es.sigma *= self.update2(...).
The first and second value in function_values must reflect two mirrored solutions.
Legacy method replaced by update2.
update state variables and return the step-size multiplier.
The first and second value in function_values must reflect two mirrored solutions sampled, respectively, in direction and in opposite direction of the previous mean shift.
with the default averaging coefficient, the first two entries dominate all others: c = 1/2 <==> 1/c * 1/2 == 1 meaning the first entry == 1 takes half of the weight c = 0.29289 = 1 - sqrt(1/2) <==> 1/c * 1/2 == 1 + 1-c meaning the first two entries take half of the weight, where "the full" weight is 1/c = sum_{i=0}^infty (1-c)^i