Module cma :: Class NoiseHandler
[hide private]
[frames] | no frames]

Class NoiseHandler

source code

object --+
         |
        NoiseHandler

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
>>> cma.fmin(cma.felli, 7 * [1], 1, noise_handler=cma.NoiseHandler(7))

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.fcts.sphere(x) * (1 + 4 * np.random.randn() / len(x))  # cma.Fcts.noisysphere
>>> es = cma.CMAEvolutionStrategy(np.ones(10), 1)
>>> 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
>>> print(es.stop())
>>> print(es.result()[-2])  # take mean value, the best solution is totally off
>>> assert sum(es.result()[-2]**2) < 1e-9
>>> print(X[np.argmin(fit_vals)])  # not bad, but probably worse than the mean
>>> # 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()

Instance Methods [hide private]
 
__init__(self, N, maxevals=[1, 1, 1], aggregate=<function median at 0x10594d6e0>, reevals=None, epsilon=1e-07, parallel=False)
parameters are
source code
 
__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.
source code
 
get_evaluations(self)
return self.evaluations, the number of evalutions to get a single fitness measurement
source code
 
treat(self)
adapt self.evaluations depending on the current measurement value and return sigma_fac in (1.0, self.alphasigma)
source code
 
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.
source code
 
update_measure(self)
updated noise level measure using two fitness lists self.fit and self.fitre, return self.noiseS, all_individual_measures.
source code
 
indices(self, fit)
return the set of indices to be reevaluated for noise measurement.
source code

Inherited from object: __delattr__, __format__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __sizeof__, __str__, __subclasshook__

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

__init__(self, N, maxevals=[1, 1, 1], aggregate=<function median at 0x10594d6e0>, reevals=None, epsilon=1e-07, parallel=False)
(Constructor)

source code 

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
Overrides: object.__init__

__call__(self, X, fit, func, ask=None, args=())
(Call operator)

source code 

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().

update_measure(self)

source code 

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

indices(self, fit)

source code 

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.