class documentation

Noise handling according to [Hansen et al 2009, A Method for Handling Uncertainty in Evolutionary Optimization...]

The interface of this class is yet versatile and subject to changes.

The noise handling follows closely [Hansen et al 2009] in the measurement part, but the implemented treatment is slightly different: for noiseS > 0, evaluations (time) and sigma are increased by alpha. For noiseS < 0, evaluations (time) is decreased by alpha**(1/4).

The (second) parameter evaluations defines the maximal number of evaluations for a single fitness computation. If it is a list, the smallest element defines the minimal number and if the list has three elements, the median value is the start value for evaluations.

NoiseHandler serves to control the noise via steps-size increase and number of re-evaluations, for example via fmin or with ask_and_eval.

Examples

Minimal example together with fmin on a non-noisy function:

>>> import cma
>>> res = cma.fmin(cma.ff.elli, 7 * [1], 1, noise_handler=cma.NoiseHandler(7))  #doctest: +ELLIPSIS
(4_w,9)-aCMA-ES (mu_w=2.8,...
>>> assert res[1] < 1e-8
>>> res = cma.fmin(cma.ff.elli, 6 * [1], 1, {'AdaptSigma':cma.sigma_adaptation.CMAAdaptSigmaTPA},
...          noise_handler=cma.NoiseHandler(6))  #doctest: +ELLIPSIS
(4_w,...
>>> assert res[1] < 1e-8

in dimension 7 (which needs to be given tice). More verbose example in the optimization loop with a noisy function defined in func:

>>> import cma, numpy as np
>>> func = lambda x: cma.ff.sphere(x) * (1 + 4 * np.random.randn() / len(x))  # cma.ff.noisysphere
>>> es = cma.CMAEvolutionStrategy(np.ones(10), 1)  #doctest: +ELLIPSIS
(5_w,10)-aCMA-ES (mu_w=3.2,...
>>> nh = cma.NoiseHandler(es.N, maxevals=[1, 1, 30])
>>> while not es.stop():
...     X, fit_vals = es.ask_and_eval(func, evaluations=nh.evaluations)
...     es.tell(X, fit_vals)  # prepare for next iteration
...     es.sigma *= nh(X, fit_vals, func, es.ask)  # see method __call__
...     es.countevals += nh.evaluations_just_done  # this is a hack, not important though
...     es.logger.add(more_data = [nh.evaluations, nh.noiseS])  # add a data point
...     es.disp()
...     # nh.maxevals = ...  it might be useful to start with smaller values and then increase
...                # doctest: +ELLIPSIS
Iterat...
>>> print(es.stop())
...                # doctest: +ELLIPSIS
{...
>>> print(es.result[-2])  # take mean value, the best solution is totally off
...                # doctest: +ELLIPSIS
[...
>>> assert sum(es.result[-2]**2) < 1e-9
>>> print(X[np.argmin(fit_vals)])  # not bad, but probably worse than the mean
...                # doctest: +ELLIPSIS
[...
>>> # es.logger.plot()

The command logger.plot() will plot the logged data.

The noise options of fmin` control a NoiseHandler instance similar to this example. The command cma.CMAOptions('noise') lists in effect the parameters of __init__ apart from aggregate.

Details

The parameters reevals, theta, c_s, and alpha_t are set differently than in the original publication, see method __init__. For a very small population size, say popsize <= 5, the measurement technique based on rank changes is likely to fail.

Missing Features

In case no noise is found, self.lam_reeval should be adaptive and get at least as low as 1 (however the possible savings from this are rather limited). Another option might be to decide during the first call by a quantitative analysis of fitness values whether lam_reeval is set to zero. More generally, an automatic noise mode detection might also set the covariance matrix learning rates to smaller values.

See Also
fmin, CMAEvolutionStrategy.ask_and_eval
Method __call__ proceed with noise measurement, set anew attributes evaluations (proposed number of evaluations to "treat" noise) and evaluations_just_done and return a factor for increasing sigma.
Method __init__ Parameters are:
Method indices return the set of indices to be reevaluated for noise measurement.
Method reeval store two fitness lists, fit and fitre reevaluating some solutions in X. self.evaluations evaluations are done for each reevaluated fitness value. See __call__, where reeval is called.
Method treat adapt self.evaluations depending on the current measurement value and return sigma_fac in (1.0, self.alphasigma)
Method update_measure updated noise level measure using two fitness lists self.fit and self.fitre, return self.noiseS, all_individual_measures.
Instance Variable alphaevals Undocumented
Instance Variable alphaevalsdown Undocumented
Instance Variable alphasigma Undocumented
Instance Variable cum Undocumented
Instance Variable epsilon Undocumented
Instance Variable evaluations number of f-evaluations to get a single measurement by aggregation
Instance Variable evaluations_just_done Undocumented
Instance Variable f_aggregate Undocumented
Instance Variable fit Undocumented
Instance Variable fitre Undocumented
Instance Variable idx Undocumented
Instance Variable lam_reeval Undocumented
Instance Variable maxevals Undocumented
Instance Variable minevals Undocumented
Instance Variable noiseS Undocumented
Instance Variable parallel Undocumented
Instance Variable theta Undocumented
def __call__(self, X, fit, func, ask=None, args=()):

proceed with noise measurement, set anew attributes evaluations (proposed number of evaluations to "treat" noise) and evaluations_just_done and return a factor for increasing sigma.

Parameters

X
a list/sequence/vector of solutions
fit
the respective list of function values
func
the objective function, fit[i] corresponds to func(X[i], *args)
ask
a method to generate a new, slightly disturbed solution. The argument is (only) mandatory if epsilon is not zero, see __init__.
args
optional additional arguments to func

Details

Calls the methods reeval, update_measure and treat` in this order. ``self.evaluations is adapted within the method treat.

def __init__(self, N, maxevals=[1, 1, 1], aggregate=np.median, reevals=None, epsilon=1e-07, parallel=False):

Parameters are:

N
dimension, (only) necessary to adjust the internal "alpha"-parameters
maxevals
maximal value for self.evaluations, where self.evaluations function calls are aggregated for noise treatment. With maxevals == 0 the noise handler is (temporarily) "switched off". If maxevals is a list, min value and (for >2 elements) median are used to define minimal and initial value of self.evaluations. Choosing maxevals > 1 is only reasonable, if also the original fit values (that are passed to __call__) are computed by aggregation of self.evaluations values (otherwise the values are not comparable), as it is done within fmin.
aggregate
function to aggregate single f-values to a 'fitness', e.g. np.median.
reevals
number of solutions to be reevaluated for noise measurement, can be a float, by default set to 2 + popsize/20, where popsize = len(fit) in __call__. zero switches noise handling off.
epsilon
multiplier for perturbation of the reevaluated solutions
parallel
a single f-call with all resampled solutions
See Also
fmin, CMAOptions, CMAEvolutionStrategy.ask_and_eval
def indices(self, fit):

return the set of indices to be reevaluated for noise measurement.

Given the first values are the earliest, this is a useful policy also with a time changing objective.

def reeval(self, X, fit, func, ask, args=()):

store two fitness lists, fit and fitre reevaluating some solutions in X. self.evaluations evaluations are done for each reevaluated fitness value. See __call__, where reeval is called.

def treat(self):

adapt self.evaluations depending on the current measurement value and return sigma_fac in (1.0, self.alphasigma)

def update_measure(self):

updated noise level measure using two fitness lists self.fit and self.fitre, return self.noiseS, all_individual_measures.

Assumes that self.idx contains the indices where the fitness lists differ.

alphaevals: float =

Undocumented

alphaevalsdown =

Undocumented

alphasigma =

Undocumented

cum: float =

Undocumented

epsilon =

Undocumented

evaluations =

number of f-evaluations to get a single measurement by aggregation

evaluations_just_done =

Undocumented

f_aggregate =

Undocumented

fit =

Undocumented

fitre =

Undocumented

idx =

Undocumented

lam_reeval =

Undocumented

maxevals =

Undocumented

minevals =

Undocumented

noiseS: int =

Undocumented

parallel =

Undocumented

theta: float =

Undocumented