Search Space Representation¶
This module provides common building blocks to define a search space.
Search spaces are defined using dictionaries, where the keys are the parameter names and the values their distribution. For example, defining a two parameter search space is done as follow
space = {"x": uniform(-5, 5),
"y": quantized_uniform(-2, 3, 0.5)}
A conditional search space can be seen as a tree, where each condition defines a subtree. For example, in the next figure, three search spaces are presented.
The left tree is the simple two parameter search space defined earlier. The middle tree defines a conditional search space with a single root condition. Two subspaces exist in this search space, one when the condition is a the other when the condition is b. Defining such a search space is done using a list of dictionaries as follow
space = [{"cond": "a", "x": uniform(-5, 5)},
{"cond": "b", "y": quantized_uniform(-2, 3, 0.5)}]
The right most tree has two conditions one at its root and another one when the root condition is a. It has a total of four subspaces. Defining such a search space is done using a hierarchy of dictionaries as follow
space = [{"cond": "a", "sub": {"c": {"x": uniform(-5, 5)},
"d": {"z": log(-5, 5, 10)},
"e": {"w": quantized_log(-2, 7, 1, 10)}}},
{"cond": "b", "y": quantized_uniform(-2, 3, 0.5)}
Note that lists can only be used at the root of conditional search spaces, sub-conditions must use the dictionary form. Moreover, it is not necessary to use the same parameter name for root conditions. For example, the following is a valid search space
space = [{"cond": "a", "x": uniform(-5, 5)},
{"spam": "b", "y": quantized_uniform(-2, 3, 0.5)}]
The only restriction is that each search space must have a unique combination of conditional parameters and values, where conditional parameters have non-distribution values. Finally, one and only one subspace can be defined without condition as follow
space = [{"x": uniform(-5, 5)},
{"cond": "b", "y": quantized_uniform(-2, 3, 0.5)}]
If two or more subspaces share the same conditional key (set of parameters
and values) an AssertionError
will be raised uppon building the
search space specifying the erroneous key.
-
class
chocolate.
Space
(spaces)[source]¶ Representation of the search space.
Encapsulate a multidimentional search space defined on various distributions. Remind that order in standard python dictionary is undefined, thus the keys of the input dictionaries are
sorted()
and put inOrderedDict
s for reproductibility.Parameters: spaces – A dictionary or list of dictionaries of parameter names to their distribution. When a list of multiple dictionaries is provided, the structuring elements of these items must define a set of unique choices. Structuring elements are defined using non-distribution values. See examples below. Raises: AssertionError
– When two keys at the same level are equal.An instance of a space is a callable object wich will return a valid parameter set provided a vector of numbers in the half-open uniform distribution \([0, 1)\).
The number of distinc dimensions can be queried with the
len()
function. When a list of dictionaries is provided, this choice constitute the first dimension and each subsequent conditional choice is also a dimension.Examples
Here is how a simple search space can be defined and the parameters can be retrieved
In [2]: s = Space({"learning_rate": uniform(0.0005, 0.1), "n_estimators" : quantized_uniform(1, 11, 1)}) In [3]: s([0.1, 0.7]) Out[3]: {'learning_rate': 0.01045, 'n_estimators': 8}
A one level conditional multidimentional search space is defined using a list of dictionaries. Here the choices are a SMV with linear kernel and a K-nearest neighbor as defined by the string values. Note the use of class names in the space definition.
In [2]: from sklearn.svm import SVC In [3]: from sklearn.neighbors import KNeighborsClassifier In [4]: s = Space([{"algo": SVC, "kernel": "linear", "C": log(low=-3, high=5, base=10)}, {"algo": KNeighborsClassifier, "n_neighbors": quantized_uniform(low=1, high=20, step=1)}])
The number of dimensions of such search space can be retrieved with the
len()
function.In [5]: len(s) Out[5]: 3
As in the simple search space a valid parameter set can be retrieved by querying the space object with a vector of length equal to the full search space.
In [6]: s([0.1, 0.2, 0.3]) Out[6]: {'C': 0.039810717055349734, 'algo': sklearn.svm.classes.SVC, 'kernel': 'linear'} In [7]: s([0.6, 0.2, 0.3]) Out[7]: {'algo': sklearn.neighbors.classification.KNeighborsClassifier, 'n_neighbors': 6}
Internal conditions can be modeled using nested dictionaries. For example, the SVM from last example can have different kernels. The next search space will share the
C
parameter amongst all SVMs, but will branch on the kernel type with their individual parameters.In [2]: s = Space([{"algo": "svm", "C": log(low=-3, high=5, base=10), "kernel": {"linear": None, "rbf": {"gamma": log(low=-2, high=3, base=10)}}}, {"algo": "knn", "n_neighbors": quantized_uniform(low=1, high=20, step=1)}]) In [3]: len(s) Out[3]: 5 In [4]: x = [0.1, 0.2, 0.7, 0.4, 0.5] In [5]: s(x) Out[5]: {'C': 0.039810717055349734, 'algo': 'svm', 'gamma': 1.0, 'kernel': 'rbf'}
-
names
(unique=True)[source]¶ Returns unique sequential names meant to be used as database column names.
Parameters: unique – Whether or not to return unique mangled names. Subspaces will still be mangled. Examples
If the length of the space is 2 as follow
In [2]: s = Space({"learning_rate": uniform(0.0005, 0.1), "n_estimators" : quantized_uniform(1, 11, 1)}) In [3]: s.names() Out[3]: ['learning_rate', 'n_estimators']
While in conditional spaces, if the length of the space is 5 (one for the choice od subspace and four independent parameters)
In [4]: s = Space([{"algo": "svm", "kernel": "linear", "C": log(low=-3, high=5, base=10)}, {"algo": "svm", "kernel": "rbf", "C": log(low=-3, high=5, base=10), "gamma": log(low=-2, high=3, base=10)}, {"algo": "knn", "n_neighbors": quantized_uniform(low=1, high=20, step=1)}]) In [5]: s.names() Out[5]: ['_subspace', 'algo_svm_kernel_linear_C', 'algo_svm_kernel_rbf_C', 'algo_svm_kernel_rbf_gamma', 'algo_knn_n_neighbors']
When using methods or classes as parameter values for conditional choices the output might be a little bit more verbose, however the names are still there.
In [6]: s = Space([{"algo": SVC, "C": log(low=-3, high=5, base=10), "kernel": {"linear": None, "rbf": {"gamma": log(low=-2, high=3, base=10)}}}, {"algo": KNeighborsClassifier, "n_neighbors": quantized_uniform(low=1, high=20, step=1)}]) In [7]: s.names() Out[7]: ['_subspace', 'algo_<class sklearn_svm_classes_SVC>_C', 'algo_<class sklearn_svm_classes_SVC>_kernel__subspace', 'algo_<class sklearn_svm_classes_SVC>_kernel_kernel_rbf_gamma', 'algo_<class sklearn_neighbors_classification_KNeighborsClassifier>_n_neighbors']
-
isactive
(x)[source]¶ Checks within conditional subspaces if, with the given vector, a parameter is active or not.
Parameters: x – A vector of numbers in the half-open uniform distribution \([0, 1)\). Returns: A list of booleans telling is the parameter is active or not. Example
When using conditional spaces it is often necessary to assess quickly what dimensions are active according to a given vector. For example, with the following conditional space
In [2]: s = Space([{"algo": "svm", "C": log(low=-3, high=5, base=10), "kernel": {"linear": None, "rbf": {"gamma": log(low=-2, high=3, base=10)}}}, {"algo": "knn", "n_neighbors": quantized_uniform(low=1, high=20, step=1)}]) In [3]: s.names() Out[3]: ['_subspace', 'algo_svm_C', 'algo_svm_kernel__subspace', 'algo_svm_kernel_kernel_rbf_gamma', 'algo_knn_n_neighbors'] In [4]: x = [0.1, 0.2, 0.7, 0.4, 0.5] In [5]: s(x) Out[5]: {'C': 0.039810717055349734, 'algo': 'svm', 'gamma': 1.0, 'kernel': 'rbf'} In [6]: s.isactive(x) Out[6]: [True, True, True, True, False] In [6]: x = [0.6, 0.2, 0.7, 0.4, 0.5] In [8]: s(x) Out[8]: {'algo': 'knn', 'n_neighbors': 10} In [9]: s.isactive(x) Out[9]: [True, False, False, False, True]
-
steps
()[source]¶ Returns the steps size between each element of the space dimensions. If a variable is continuous the returned stepsize is
None
.
-
subspaces
()[source]¶ Returns every valid combinaition of conditions of the tree- structured search space. Each combinaition is a list of length equal to the total dimensionality of this search space. Active dimensions are either a fixed value for conditions or a
Distribution
for optimizable parameters. Inactive dimensions areNone
.Example
The following search space has 3 possible subspaces
In [2]: s = Space([{"algo": "svm", "C": log(low=-3, high=5, base=10), "kernel": {"linear": None, "rbf": {"gamma": log(low=-2, high=3, base=10)}}}, {"algo": "knn", "n_neighbors": quantized_uniform(low=1, high=20, step=1)}]) In [3]: s.names() Out[3]: ['_subspace', 'algo_svm_C', 'algo_svm_kernel__subspace', 'algo_svm_kernel_kernel_rbf_gamma', 'algo_knn_n_neighbors'] In [4]: s.subspaces() Out[4]: [[0.0, log(low=-3, high=5, base=10), 0.0, None, None], [0.0, log(low=-3, high=5, base=10), 0.5, log(low=-2, high=3, base=10), None], [0.5, None, None, None, quantized_uniform(low=1, high=20, step=1)]]
-
-
class
chocolate.
ContinuousDistribution
[source]¶ Base class for every Chocolate continuous distributions.
-
class
chocolate.
QuantizedDistribution
[source]¶ Base class for every Chocolate quantized distributions.
-
class
chocolate.
uniform
(low, high)[source]¶ Uniform continuous distribution.
Representation of the uniform continuous distribution in the half-open interval \([\text{low}, \text{high})\).
Parameters: - low – Lower bound of the distribution. All values will be greater or equal than low.
- high – Upper bound of the distribution. All values will be lower than high.
-
class
chocolate.
quantized_uniform
(low, high, step)[source]¶ Uniform discrete distribution.
Representation of the uniform continuous distribution in the half-open interval \([\text{low}, \text{high})\) with regular spacing between samples. If \(\left\lceil \frac{\text{high} - \text{low}}{step} \right\rceil \neq \frac{\text{high} - \text{low}}{step}\), the last interval will have a different probability than the others. It is preferable to use \(\text{high} = N \times \text{step} + \text{low}\) where \(N\) is a whole number.
Parameters: - low – Lower bound of the distribution. All values will be greater or equal than low.
- high – Upper bound of the distribution. All values will be lower than high.
- step – The spacing between each discrete sample.
-
__call__
(x)[source]¶ Transforms x, a uniform number taken from the half-open continuous interval \([0, 1)\), to the represented distribution.
Returns: The corresponding number in the discrete half-open interval \([\text{low}, \text{high})\) alligned on step size. If the output number is whole, this method returns an int
otherwise afloat
.
-
class
chocolate.
log
(low, high, base)[source]¶ Logarithmic uniform continuous distribution.
Representation of the logarithmic uniform continuous distribution in the half-open interval \([\text{base}^\text{low}, \text{base}^\text{high})\).
Parameters: - low – Lower bound of the distribution. All values will be greater or equal than \(\text{base}^\text{low}\).
- high – Upper bound of the distribution. All values will be lower than \(\text{base}^\text{high}\).
- base – Base of the logarithmic function.
-
__call__
(x)[source]¶ Transforms x, a uniform number taken from the half-open continuous interval \([0, 1)\), to the represented distribution.
Returns: The corresponding number in the discrete half-open interval \([\text{base}^\text{low}, \text{base}^\text{high})\) alligned on step size. If the output number is whole, this method returns an int
otherwise afloat
.
-
class
chocolate.
quantized_log
(low, high, step, base)[source]¶ Logarithmic uniform discrete distribution.
Representation of the logarithmic uniform discrete distribution in the half-open interval \([\text{base}^\text{low}, \text{base}^\text{high})\). with regular spacing between sampled exponents.
Parameters: - low – Lower bound of the distribution. All values will be greater or equal than \(\text{base}^\text{low}\).
- high – Upper bound of the distribution. All values will be lower than \(\text{base}^\text{high}\).
- step – The spacing between each discrete sample exponent.
- base – Base of the logarithmic function.
-
__call__
(x)[source]¶ Transforms x, a uniform number taken from the half-open continuous interval \([0, 1)\), to the represented distribution.
Returns: The corresponding number in the discrete half-open interval \([\text{base}^\text{low}, \text{base}^\text{high})\) alligned on step size. If the output number is whole, this method returns an int
otherwise afloat
.
-
__iter__
()¶ Iterate over all possible values of this discrete distribution in the \([0, 1)\) space. This is the same as
numpy.arange(0, 1, step / (high - low))
-
__getitem__
(i)¶ Retrieve the
i
th value of this distribution in the \([0, 1)\) space.
-
__len__
()¶ Get the number of possible values for this distribution.
-
class
chocolate.
choice
(values)[source]¶ Uniform choice distribution between non-numeric samples.
Parameters: values – A list of choices to choose uniformly from. -
__call__
(x)[source]¶ Transforms x, a uniform number taken from the half-open continuous interval \([0, 1)\), to the represented distribution.
Returns: The corresponding choice from the entered values.
-
__iter__
()¶ Iterate over all possible values of this discrete distribution in the \([0, 1)\) space. This is the same as
numpy.arange(0, 1, step / (high - low))
-
__getitem__
(i)¶ Retrieve the
i
th value of this distribution in the \([0, 1)\) space.
-
__len__
()¶ Get the number of possible values for this distribution.
-