ade.population.Population(object)
class documentation
Part of ade.population
(View In Hierarchy)
I contain a population of parameter-combination Individual
objects.
Construct me with a callable evaluation func, a sequence of parameter names, and a sequence of bounds containing 2-tuples that each define the lower and upper limits of the values:
-
func: A callable to which an
Individual
can send its parameter values and from which it receives a sum-of-squared error float value as a result. - names: A sequence of parameter names.
- bounds: A list of 2-tuples, one for each parameter name. The first element of each tuple is the lower bound of a parameter in the second the upper bound.
The callable func must accept a single 1-D Numpy array as its sole argument and return the sum of squared errors (SSE) as a single float value. To shut down ade, it can return a negative SSE value. If ade is shutting down, it will use None as the argument, and the callable should act accordingly.
My targetFraction attribute determines how much success challengers must have to maintain the status quo in adaptive mode. Consider the default of 2.5%: In a population of 100, that is reached with a score of 2.5, which can be achieved, for example, with
- ten challengers winning with a rounded improvement ratio of 1; or
- one challenger winning with an rir of 2 and five with an rir of 1; or
- just one challenger winning with an rir of 3.
- Or, if you're somehow positioned at a subtle transition in the fitness landscape along just the right multi-dimensional angle, fully half of the challengers winning with an rir of 0. (Unlikely!)
Parameters | constraints | A single callable object (function, method, class instance with
__call__ method), or a sequence of such objects, that enforce(s) any
constraints on your parameter values. See ParameterManager.passesConstraints .
Instead of a sequence, you can use an instance of constraints.Constraints . |
popsize | The number of individuals per parameter in the population, if not the default. | |
debug | Set True to override my default debug setting and
ensure that I show individuals getting replaced. | |
complaintCallback | A callable that my Reporter calls with an
individual and the non-None result of a complaining reporter callback. See
Reporter.runCallbacks . | |
targetFraction | Set this to a (small) float to override my default target for the total score of improvements in each iteration. | |
See Also | asynqueue.util.DeferredTracker, used to limit concurrency
during population setup . |
Class Variable | N_maxParallel | The maximum number of parallel evaluations during population setup . Uses an
instance of asynqueue.util.DeferredTracker for concurrency
limiting. |
Instance Variable | popsize | The number of individuals per parameter. The population size will scale with the number of parameters, up until Np_max is reached. Default is 10 individuals per parameter. |
Instance Variable | Np_min | Minimum population size, i.e., my total number of individuals. Default is 20. |
Instance Variable | Np_max | Maximum population size. Default is 500, which is really pretty big. |
Instance Variable | Nd | The number of parameters for each individual. |
Instance Variable | targetFraction | The desired total score of improvements in each iteration in order for
ade's adaptive algorithm to not change the current differential
weight. See replacement
and FManager for details.
The default is 2%. (Previously, it was 2.5% but that seemed too strict for
the application the author is mostly using ADE for.) |
Instance Variable | debug | Set True to show individuals getting replaced. (Results in a
very messy log or console display.) |
Instance Variable | running | Indicates my run status: None after instantiation but before
setup ,
True after setup, and False if ade is
aborting. |
Method | __init__ | Population(func, names, bounds, constraints=[], popsize=None,
debug=False, complaintCallback=None) |
Class Method | load | Returns a new instance of me with values initialized from the original version that was pickled and written with BZ2 compression to filePath. |
Method | __getstate__ | For pickling. Note that neither the user-supplied evaluation function nor any complaint callback function is included. |
Method | __setstate__ | For unpickling. |
Method | save | Writes a BZ2-compressed pickled version of me to the specified filePath. |
Method | __getitem__ | Sequence-like access to my individuals. |
Method | __setitem__ | Use only this method (item setting) to replace individuals in my iList. |
Method | __len__ | Sequence-like container of individuals: length. |
Method | __iter__ | Sequence-like container of individuals: iteration. |
Method | __contains__ | Sequence-like container of individuals: "in". |
Method | __bool__ | Sequence-like container of individuals: I am True if I have
any. |
Method | KS 0 | Property: A list of indices to iList, sorted by increasing (worsening) SSE of the individuals there. The best individual will have the first index in KS. |
Method | KS | Property: "Deleting" my SSE-sorted list of indices forces regeneration of it the next time the KS property is accessed. It also "deletes" iSorted. |
Method | iSorted 0 | Property: A list of my individuals, sorted by increasing (worsening) SSE. |
Method | iSorted | Property: "Deleting" my sorted list of individuals forces regeneration of the sorted list that will be returned next time the iSorted property is accessed. |
Method | kBest | Property: The index to iList of the best individual.
None if I have no individuals yet. |
Method | __repr__ | An informative string representation with a text table of my best individuals. |
Method | evalFunc | A wrapper for the user-supplied evaluation function. |
Method | clear | Wipes out any existing population and sets up everything for a brand new one. |
Method | limit | Limits the individual's parameter values to the bounds in the way that
my ParameterManager
is configured to do, modifying the individual in place. |
Method | spawn | Spawns a new Individual with the
supplied values. If fromUnity is set True , the
values are converted from 0-1 range into their proper ranges. |
Method | abort | Aborts my operations ASAP. Repeated calls will release any locks that got acquired since the last call. |
Method | initialize | Invalidates the last sort of my individuals, sets my running flag
to True , and prints/logs a representation of my populated
instance. |
Method | setup | Sets up my initial population using a Latin hypercube to initialize pseudorandom parameter values with minimal clustering. |
Method | addCallback | Adds callable func to my reporter's list of functions to call
each time there is a significantly better Individual . |
Method | setConstraints | Sets the constraint checkers maintained by my ParameterManager
instance pm to the callable function(s), method(s), or object(s)
supplied as one or more args. |
Method | replacement | Records the replacement of an Individual in this
generation or iteration. |
Method | report | Provides a message via the log messenger about the supplied Individual ,
optionally with a comparison to another one. |
Method | waitForReports | Returns a Deferred that fires when all reporter callbacks
have finished. (And also History updates.) |
Method | showFailedConstraint | Outputs a progress character to indicate a failed constraint. |
Method | push | Pushes the supplied Individual i
onto my population and kicks out the worst individual there to make
room. |
Method | sample | Returns a sample of N indices from my population that are unique from each other and from any excluded indices supplied as additional arguments. |
Method | individuals | Immediately returns a list of the individuals at the specified integer index or indices. |
Method | lock | Obtains the locks for individuals at the specified indices, submits a
request to acquire them, and returns a Deferred that fires
when all of them have been acquired. |
Method | release | Releases any active lock for individuals at the specified index or indices. |
Method | best | Returns my best individual, or None if I have no
individuals yet. |
Method | evalTimes | Returns a list of the most recent elapsed evaluation times for each of my individuals that have done evaluations. |
Method | _keepStatusQuo | Returns True with a probability that increases as
score approaches my statusQuoteScore. |
setup
. Uses an
instance of asynqueue.util.DeferredTracker
for concurrency
limiting.
replacement
and FManager
for details.
The default is 2%. (Previously, it was 2.5% but that seemed too strict for
the application the author is mostly using ADE for.)
True
to show individuals getting replaced. (Results in a
very messy log or console display.)
None
after instantiation but before
setup
,
True
after setup, and False
if ade is
aborting.
Population(func, names, bounds, constraints=[], popsize=None,
debug=False, complaintCallback=None)
def load(cls, filePath, **kw):
Returns a new instance of me with values initialized from the original version that was pickled and written with BZ2 compression to filePath.
The pickled version will not have a reference to the evaluation func that was supplied to the original version in its constructor, nor to any complaintCallback. If you want to do further evaluations, you can supply a reference to those functions (or even a different one, though that would be weird) with the func and complaintCallback keywords.
Note: For some mysterious reason, the DE algorithm seems to run significantly slower when resuming with a population that has been loaded using this method than with one initialized from scratch.
Parameters | func | Evaluation function, specify if you want to resume evaluations. All individuals in the loaded population should have their SSEs re-evaluated if anything at all has changed about that function. |
complaintCallback | Callback function for complaining about new-best reports during resumed evaluations. | |
bounds | A list of bounds to update my restored ParameterManager object with.
Specify if you refined the parameter bounds since the last run and want to
resume evaluations with the refined bounds. Each Individual in the
new instance will have its values limited to the new bounds with a call to
Population.limit . | |
See Also | save for the
way to create compressed pickles of an instance of me. |
For pickling. Note that neither the user-supplied evaluation function nor any complaint callback function is included.
Writes a BZ2-compressed pickled version of me to the specified filePath.
Note that the user-supplied evaluation function will not be included in
the pickled version. However, you can supply it as a keyword to load
.
Use only this method (item setting) to replace individuals in my iList.
The only other place my iList is ever manipulated directly is the
addIndividual
function of setup
.
Sequence-like container of individuals: length.
My length will be equal to my Np attribute unless setup has not been completed.
def KS 0(self):
Property: A list of indices to iList, sorted by increasing (worsening) SSE of the individuals there. The best individual will have the first index in KS.
def KS(self):
Property: "Deleting" my SSE-sorted list of indices forces regeneration of it the next time the KS property is accessed. It also "deletes" iSorted.
def iSorted 0(self):
Property: A list of my individuals, sorted by increasing (worsening) SSE.
def iSorted(self):
Property: "Deleting" my sorted list of individuals forces regeneration of the sorted list that will be returned next time the iSorted property is accessed.
def kBest(self):
Property: The index to iList of the best individual.
None
if I have no individuals yet.
Limits the individual's parameter values to the bounds in the way that
my ParameterManager
is configured to do, modifying the individual in place.
Note: The individual's population status is not considered or
affected. If it's a population member, you will want to re-evaluate it and
invalidate my sort with a del self.KS
or del
self.iSorted
if its SSE has changed.
Spawns a new Individual
with the
supplied values. If fromUnity is set True
, the
values are converted from 0-1 range into their proper ranges.
Aborts my operations ASAP. Repeated calls will release any locks that got acquired since the last call.
Reporter.abort
calls this with ignoreReporter set True
to avoid
infinite recursion.
Invalidates the last sort of my individuals, sets my running flag
to True
, and prints/logs a representation of my populated
instance.
Sets up my initial population using a Latin hypercube to initialize pseudorandom parameter values with minimal clustering.
Unless uniform is set, that is. Then each parameter values is just uniformly random without regard to the others.
With parameter constraints, the Latin hypercube doesn't work that well. The initial values matrix must be refreshed, perhaps many times. But it may still be better than uniform initial population sampling.
Sets my running flag True
and returns a
Deferred
that fires when the population has been set up, with
True
if it's ready to go and setup didn't get aborted.
Parameters | uniform | Use uniform random variates instead of a Latin hypercube (LHS). Using LHS (the default) is usually better because initializes pseudorandom parameter values with minimal clustering. |
blank | Set True to give the initial individuals an infinite
placeholder SSE instead of being evaluated. |
Adds callable func to my reporter's list of functions to call
each time there is a significantly better Individual
.
See Also | Reporter.addCallback . |
Sets the constraint checkers maintained by my ParameterManager
instance pm to the callable function(s), method(s), or object(s)
supplied as one or more args.
What you supply as arguments will replace any constraint checking already in place, so make sure you everything you want is included.
All constraints, and only those constraints, defined by this call will need to be be satisfied with each parameter combination. To clear any existing constraints, call with no args.
See Also | ParameterManager.setConstraints . |
Returns True
with a probability that increases as
score approaches my statusQuoteScore.
Records the replacement of an Individual
in this
generation or iteration.
Call with an integer rounded improvement ratio in a loser's SSE vs. the successful challenger's SSE, unless you are calling to inquire about whether the status quo F value(s) should be maintained or to set my statusQuoteScore with the sqs keyword.
Three types of calls
The rounded improvement ratio rir indicates how much better the challenger is than the individual it replaced. I use that ratio to adjust a running score for the current iteration to inform the status quo inquiry that will occur when the iteration is done, unless I'm not running in adaptive mode.
You can set my target statusQuoScore by setting sqs to a (small) float value. That will replace my default value for future evaluation of replacement individuals.
Finally, a status quo inquiry is a call with no keywords set. I will
determine if the replacements that occurred in the previous
generation/iteration were enough to warrant maintaining the status quo,
and then reset the record. You will receive a result of True
if the status quote should be maintained.
The status quo should be maintained if several small improvements are made, or fewer larger ones, with the required number and/or size increasing for a larger population. For small populations where even a single improvement would be significant, the probability of status quo maintenance increases with smaller population and will sometimes happen even with no improvements for a given generation or iteration.
Improvement Ratios
An rir of 1 indicates that the successful challenger was better (i.e., lower) and not considered equivalent to that of the individual it replaced, and that its SSE was no better than 1.5x as good (2/3 as high) as the replaced individual's SSE. An rir of 2 indicates that the challenger had an SSE between 1.5x and 2.5x better than (2/5 to 2/3 as high as) the individual it replaced.
I give very little weight to an rir of zero, which indicates
that the challenger was better but still has an equivalent SSE, i.e., is
no more than 2% better with the default value of Reporter.minDiff.
See Reporter.isEquivSSE
.
I give five times much weight to an rir of 1, though it's still
pretty small. The improvement is modest and could be as little as 2%
(assuming Reporter.minDiff
=0.02, the default). An rir
of 2 gets three times as much weight as that.
An rir of 3 also gets disproportionately more weight, five times as much as rir=1. Beyond that, though, the weight scales in a nearly linear fashion. For example, an rir of 9 adds just a little more than three times to the score (3.4x) as rir=3 does.
Here's a practical example, with a population of 100 individuals: If you see 10 "1" characters on the screen for one iteration with other 90 being "X," your ratio score for that iteration will be 5.0. But if you see just one non-X individual with a "8" character, the score will be 7.5. That one amazing success story counts more in a sea of failures than a bunch of marginal improvements, which is kind of how evolution works in real life. (See the literature around "hopeful monsters.")
Parameters | rir | A rounded improvement ratio obtained from a call to Reporter.msgRatio ,
where the numerator is the SSE of the individual that was replaced and the
denominator is the SSE of its successful challenger. |
See Also | report ,
which calls this. |
Provides a message via the log messenger about the supplied Individual
,
optionally with a comparison to another one.
If no second individual is supplied, the comparison will be with the best individual thus far reported on.
If no individual at all is supplied, reports on my best one, forcing callbacks to run even if the best individual's SSE is equivalent to the last-reported one's.
Gets the ratio from a call to my Reporter
instance, and
does a call to replacement
with it if the new individual is better. Returns (for unit testing
convenience) the ratio.
Parameters | noProgress | Set True to suppress printing/logging a progress character. |
force | Set True to force callbacks to run even if the reported SSE is
considered equivalent to the previous best one. | |
See Also | Reporter . |
Returns a Deferred
that fires when all reporter callbacks
have finished. (And also History
updates.)
Pushes the supplied Individual
i
onto my population and kicks out the worst individual there to make
room.
Returns a sample of N indices from my population that are unique from each other and from any excluded indices supplied as additional arguments.
The randomBase keyword lets you use a significant improvement
offered by ADE: Non-uniform probability of base individual selection.
Implementation is done by an instance of ProbabilitySampler
.
The traditional DE/best/1/bin and DE/rand/1/bin are really opposite extremes of what can be a continuous range of base individual selection regimes. By specifying a float value for randomBase between 0.0 and 1.0, you can select a regime anywhere in that range.
The higher the value, the more uniform the probability distribution is. Setting it to near 0.0 makes it much more likely that the index of the best individual or one nearly as good will be chosen. Setting it to near 1.0 makes the worst individual nearly as likely to be chosen as the best.
A randomBase value of 0.5 is a compromise between DE/best/1/bin and DE/rand/1/bin. With that setting, the probability of an individual having its index selected will gradually drop as it gets worse in the SSE rankings. As randomBase goes above 0.5, the probability will take longer to start dropping, until at 1.0 it doesn't drop at all. As randomBase goes below 0.5, the probability will start dropping sooner, until at 0.0 it drops to zero for anything but the best individual.
Parameters | randomBase | Sample probability uniformity value between 0.0 (only the best individual is ever selected) and 1.0 (uniform probability). Setting it False is equivalent to 0.0, and setting it True (the default) is equivalent to 1.0. |
Immediately returns a list of the individuals at the specified integer index or indices.
Obtains the locks for individuals at the specified indices, submits a
request to acquire them, and returns a Deferred
that fires
when all of them have been acquired.
Release the locks (as soon as possible) by calling release
with
the indices that are locked.
If I'm shutting down, the returned Deferred
fires
immediately.