Skip to content

Commit 0f6aa50

Browse files
authored
Merge pull request #158 from y0z/feature/mocma
Add MoCmaSampler
2 parents 9e353ea + 549b616 commit 0f6aa50

File tree

8 files changed

+1223
-0
lines changed

8 files changed

+1223
-0
lines changed

package/samplers/mocma/LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2024 Yoshihiko Ozaki
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

package/samplers/mocma/README.md

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
---
2+
author: Yoshihiko Ozaki
3+
title: Multi-objective CMA-ES (MO-CMA-ES) Sampler
4+
description: A sampler based on a strong variant of CMA-ES for multi-objective optimization (s-MO-CMA).
5+
tags: [sampler, Multi-Objective Optimization, Evolutionary Algorithm (EA), CMA-ES]
6+
optuna_versions: [4.0.0]
7+
license: MIT License
8+
---
9+
10+
## Abstract
11+
12+
MoCmaSampler provides the implementation of the s-MO-CMA-ES algorithm. This algorithm extends (1+1)-CMA-ES to multi-objective optimization by introducing a selection strategy based on non-domination sorting and contributing hypervolume (S-metric). It inherits important properties of CMA-ES, invariance against order-preserving transformations of the fitness function value and rotation and translation of the search space.
13+
14+
## Class or Function Names
15+
16+
- `MoCmaSampler(*, search_space: dict[str, BaseDistribution] | None = None, popsize: int | None = None, seed: int | None = None)`
17+
- `search_space`: A dictionary containing the search space that defines the parameter space. The keys are the parameter names and the values are [the parameter's distribution](https://optuna.readthedocs.io/en/stable/reference/distributions.html). If the search space is not provided, the sampler will infer the search space dynamically.
18+
Example:
19+
```python
20+
search_space = {
21+
"x": optuna.distributions.FloatDistribution(-5, 5),
22+
"y": optuna.distributions.FloatDistribution(-5, 5),
23+
}
24+
MoCmaSampler(search_space=search_space)
25+
```
26+
- `popsize`: Population size of the CMA-ES algorithm. If not provided, the population size will be set based on the search space dimensionality. If you have a sufficient evaluation budget, it is recommended to increase the popsize.
27+
- `seed`: Seed for random number generator.
28+
29+
Note that because of the limitation of the algorithm, only non-conditional numerical parameters are sampled by the MO-CMA-ES algorithm, and categorical parameters and conditional parameters are handled by random sampling.
30+
31+
## Example
32+
33+
```python
34+
import optuna
35+
import optunahub
36+
37+
38+
def objective(trial: optuna.Trial) -> tuple[float, float]:
39+
x = trial.suggest_float("x", 0, 5)
40+
y = trial.suggest_float("y", 0, 3)
41+
v0 = 4 * x**2 + 4 * y**2
42+
v1 = (x - 5) ** 2 + (y - 5) ** 2
43+
return v0, v1
44+
45+
samplers = [
46+
optunahub.load_local_module("samplers/mocma", registry_root="package").MoCmaSampler(popsize=100, seed=42),
47+
optuna.samplers.NSGAIISampler(population_size=100, seed=42),
48+
]
49+
studies = []
50+
for sampler in samplers:
51+
study = optuna.create_study(
52+
directions=["minimize", "minimize"],
53+
sampler=sampler,
54+
study_name=f"{sampler.__class__.__name__}",
55+
)
56+
study.optimize(objective, n_trials=1000)
57+
studies.append(study)
58+
59+
optunahub.load_module("visualization/plot_pareto_front_multi").plot_pareto_front(
60+
studies
61+
).show()
62+
optunahub.load_module("visualization/plot_hypervolume_history_multi").plot_hypervolume_history(
63+
studies, reference_point=[200.0, 100.0]
64+
).show()
65+
```
66+
67+
![Pareto front](images/pareto_front.png)
68+
![Hypervolume](images/hypervolume.png)
69+
70+
## Others
71+
72+
### Test
73+
74+
To execute the tests for MoCmaSamler, please run the following commands. The test file is provided in the package.
75+
76+
```sh
77+
pip install pytest
78+
```
79+
80+
```python
81+
pytest -s tests/test_sampler.py
82+
```
83+
84+
### Reference
85+
86+
Christian Igel, Nikolaus Hansen, Stefan Roth. Covariance Matrix Adaptation for Multi-objective Optimization, Evolutionary Computatio. (2007) 15 (1): 128. https://doi.org/10.1162/evco.2007.15.1.1.
87+
88+
### BibTeX
89+
90+
```bibtex
91+
@article{igel2007covariance,
92+
title={Covariance matrix adaptation for multi-objective optimization},
93+
author={Igel, Christian and Hansen, Nikolaus and Roth, Stefan},
94+
journal={Evolutionary computation},
95+
volume={15},
96+
number={1},
97+
pages={1--28},
98+
year={2007},
99+
publisher={MIT Press One Rogers Street, Cambridge, MA 02142-1209, USA journals-info~…}
100+
}
101+
```

package/samplers/mocma/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
from .mocma import MoCmaSampler
2+
3+
4+
__all__ = ["MoCmaSampler"]

package/samplers/mocma/example.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import optuna
2+
import optunahub
3+
4+
5+
if __name__ == "__main__":
6+
7+
def objective(trial: optuna.Trial) -> tuple[float, float]:
8+
x = trial.suggest_float("x", 0, 5)
9+
y = trial.suggest_float("y", 0, 3)
10+
v0 = 4 * x**2 + 4 * y**2
11+
v1 = (x - 5) ** 2 + (y - 5) ** 2
12+
return v0, v1
13+
14+
samplers = [
15+
optunahub.load_local_module("samplers/mocma", registry_root="package").MoCmaSampler(
16+
popsize=100,
17+
seed=42,
18+
),
19+
optuna.samplers.NSGAIISampler(population_size=100, seed=42),
20+
]
21+
studies = []
22+
for sampler in samplers:
23+
study = optuna.create_study(
24+
directions=["minimize", "minimize"],
25+
sampler=sampler,
26+
study_name=f"{sampler.__class__.__name__}",
27+
)
28+
study.optimize(objective, n_trials=1000)
29+
studies.append(study)
30+
31+
optunahub.load_module("visualization/plot_pareto_front_multi").plot_pareto_front(
32+
studies
33+
).show()
34+
optunahub.load_module("visualization/plot_hypervolume_history_multi").plot_hypervolume_history(
35+
studies, reference_point=[200.0, 100.0]
36+
).show()
73.8 KB
Loading
89.4 KB
Loading

0 commit comments

Comments
 (0)