Skip to content

Commit 8c28770

Browse files
committed
Merge branch 'dev'
2 parents 0c15769 + 12767db commit 8c28770

17 files changed

Lines changed: 184 additions & 147 deletions

.github/workflows/tests.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ jobs:
3636
python -m pip install --upgrade pip
3737
python -m pip install flake8 pytest coveralls codecov pytest-cov
3838
python -m pip install .
39+
python -m pip install .[distribution]
3940
4041
- name: Test with pytest
4142
run: |

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,11 +120,13 @@ Hyperactive features a collection of optimization algorithms that can be used fo
120120
<ul>
121121
<li><a href="./examples/optimization_techniques/parallel_tempering.py">Parallel Tempering</a></li>
122122
<li><a href="./examples/optimization_techniques/particle_swarm_optimization.py">Particle Swarm Optimizer</li>
123+
<li>Spiral Optimization</li>
123124
<li><a href="./examples/optimization_techniques/evolution_strategy.py">Evolution Strategy</a></li>
124125
</ul><br>
125126
<a><b>Sequential Methods:</b></a>
126127
<ul>
127128
<li><a href="./examples/optimization_techniques/bayesian_optimization.py">Bayesian Optimization</a></li>
129+
<li>Lipschitz Optimization</li>
128130
<li><a href="./examples/optimization_techniques/tpe.py">Tree of Parzen Estimators</a></li>
129131
<li><a href="./examples/optimization_techniques/forest_optimization.py">Forest Optimizer</a>
130132
[<a href="#/./overview#references">dto</a>] </li>
@@ -378,8 +380,10 @@ hyper.run()
378380
- PatternSearch
379381
- ParallelTemperingOptimizer
380382
- ParticleSwarmOptimizer
383+
- SpiralOptimization
381384
- EvolutionStrategyOptimizer
382385
- BayesianOptimizer
386+
- LipschitzOptimizer
383387
- TreeStructuredParzenEstimators
384388
- ForestOptimizer
385389

hyperactive/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
# Email: simon.blanke@yahoo.com
33
# License: MIT License
44

5-
__version__ = "4.2.0"
5+
__version__ = "4.3.0"
66
__license__ = "MIT"
77

88

hyperactive/distribution.py

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,6 @@
22
# Email: simon.blanke@yahoo.com
33
# License: MIT License
44

5-
import multiprocessing as mp
6-
import pathos.multiprocessing as pmp
7-
from joblib import Parallel, delayed
8-
95

106
def single_process(process_func, process_infos):
117
results = [process_func(*info) for info in process_infos]
@@ -14,21 +10,38 @@ def single_process(process_func, process_infos):
1410

1511

1612
def multiprocessing_wrapper(process_func, process_infos, n_processes):
13+
import multiprocessing as mp
14+
1715
pool = mp.Pool(n_processes)
1816
results = pool.map(process_func, process_infos)
1917

2018
return results
2119

2220

2321
def pathos_wrapper(process_func, search_processes_paras, n_processes, **kwargs):
22+
import pathos.multiprocessing as pmp
23+
2424
pool = pmp.Pool(n_processes, **kwargs)
2525
results = pool.map(process_func, search_processes_paras)
2626

2727
return results
2828

2929

3030
def joblib_wrapper(process_func, search_processes_paras, n_processes, **kwargs):
31+
from joblib import Parallel, delayed
32+
3133
jobs = [delayed(process_func)(*info_dict) for info_dict in search_processes_paras]
3234
results = Parallel(n_jobs=n_processes, **kwargs)(jobs)
3335

3436
return results
37+
38+
39+
def ray_wrapper(process_func, process_infos, n_processes, **kwargs):
40+
import ray
41+
from ray.util.multiprocessing import Pool
42+
43+
# ray.init(log_to_driver=False)
44+
pool = Pool(n_processes)
45+
results = pool.map(process_func, process_infos)
46+
47+
return results

hyperactive/hyperactive.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55

66
import multiprocessing as mp
7-
from tqdm import tqdm
87

98
from .optimizers import RandomSearchOptimizer
109
from .run_search import run_search

hyperactive/optimizers/__init__.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,11 @@
1717
PatternSearch,
1818
ParallelTemperingOptimizer,
1919
ParticleSwarmOptimizer,
20+
SpiralOptimization,
2021
EvolutionStrategyOptimizer,
2122
BayesianOptimizer,
23+
LipschitzOptimizer,
24+
DirectAlgorithm,
2225
TreeStructuredParzenEstimators,
2326
ForestOptimizer,
2427
EnsembleOptimizer,
@@ -39,8 +42,11 @@
3942
"PatternSearch",
4043
"ParallelTemperingOptimizer",
4144
"ParticleSwarmOptimizer",
45+
"SpiralOptimization",
4246
"EvolutionStrategyOptimizer",
4347
"BayesianOptimizer",
48+
"LipschitzOptimizer",
49+
"DirectAlgorithm",
4450
"TreeStructuredParzenEstimators",
4551
"ForestOptimizer",
4652
"EnsembleOptimizer",
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# Author: Simon Blanke
2+
# Email: simon.blanke@yahoo.com
3+
# License: MIT License
4+
5+
6+
class BaseOptimizer:
7+
def __init__(self):
8+
pass
9+
10+
def _add_result_attributes(
11+
self,
12+
best_para,
13+
best_score,
14+
best_since_iter,
15+
eval_times,
16+
iter_times,
17+
positions,
18+
search_data,
19+
memory_values_df,
20+
random_seed,
21+
):
22+
self.best_para = best_para
23+
self.best_score = best_score
24+
self.best_since_iter = best_since_iter
25+
self.eval_times = eval_times
26+
self.iter_times = iter_times
27+
self.positions = positions
28+
self.search_data = search_data
29+
self.memory_values_df = memory_values_df
30+
self.random_seed = random_seed

hyperactive/optimizers/exp_opt_wrapper.py

Lines changed: 0 additions & 46 deletions
This file was deleted.

hyperactive/optimizers/hyper_gradient_conv.py

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -96,16 +96,29 @@ def get_list_positions(self, list1_values, search_dim):
9696
list_positions = []
9797

9898
for value2 in list1_values:
99-
try:
100-
list_positions.append(search_dim.index(value2))
101-
except:
102-
raise ValueError
99+
list_positions.append(search_dim.index(value2))
103100

104101
return list_positions
105102

106103
def values2positions(self, values, search_dim):
107104
return np.array(search_dim).searchsorted(values)
108105

106+
def positions2results(self, positions):
107+
results_dict = {}
108+
109+
for para_name in self.s_space.dim_keys:
110+
values_list = self.s_space[para_name]
111+
pos_ = positions[para_name].values
112+
values_ = [values_list[idx] for idx in pos_]
113+
results_dict[para_name] = values_
114+
115+
results = pd.DataFrame.from_dict(results_dict)
116+
117+
diff_list = np.setdiff1d(positions.columns, results.columns)
118+
results[diff_list] = positions[diff_list]
119+
120+
return results
121+
109122
def conv_memory_warm_start(self, results):
110123
if results is None:
111124
return results
Lines changed: 45 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -2,68 +2,16 @@
22
# Email: simon.blanke@yahoo.com
33
# License: MIT License
44

5-
import copy
6-
import inspect
75
import numpy as np
86
import pandas as pd
97

108

119
from .objective_function import ObjectiveFunction
1210
from .hyper_gradient_conv import HyperGradientConv
11+
from .base_optimizer import BaseOptimizer
1312

1413

15-
class TrafoClass:
16-
def __init__(self, *args, **kwargs):
17-
pass
18-
19-
def _convert_args2gfo(self, memory_warm_start):
20-
memory_warm_start = self.hg_conv.conv_memory_warm_start(memory_warm_start)
21-
22-
return memory_warm_start
23-
24-
def _positions2results(self, positions):
25-
results_dict = {}
26-
27-
for para_name in self.conv.para_names:
28-
values_list = self.s_space[para_name]
29-
pos_ = positions[para_name].values
30-
values_ = [values_list[idx] for idx in pos_]
31-
results_dict[para_name] = values_
32-
33-
results = pd.DataFrame.from_dict(results_dict)
34-
35-
diff_list = np.setdiff1d(positions.columns, results.columns)
36-
results[diff_list] = positions[diff_list]
37-
38-
return results
39-
40-
def _convert_results2hyper(self):
41-
self.eval_times = np.array(self._optimizer.eval_times).sum()
42-
self.iter_times = np.array(self._optimizer.iter_times).sum()
43-
44-
if self._optimizer.best_para is not None:
45-
value = self.hg_conv.para2value(self._optimizer.best_para)
46-
position = self.hg_conv.position2value(value)
47-
best_para = self.hg_conv.value2para(position)
48-
49-
self.best_para = best_para
50-
else:
51-
self.best_para = None
52-
53-
self.best_score = self._optimizer.best_score
54-
self.positions = self._optimizer.search_data
55-
56-
self.search_data = self._positions2results(self.positions)
57-
58-
results_dd = self._optimizer.search_data.drop_duplicates(
59-
subset=self.s_space.dim_keys, keep="first"
60-
)
61-
self.memory_values_df = results_dd[
62-
self.s_space.dim_keys + ["score"]
63-
].reset_index(drop=True)
64-
65-
66-
class _BaseOptimizer_(TrafoClass):
14+
class HyperOptimizer(BaseOptimizer):
6715
def __init__(self, **opt_params):
6816
super().__init__()
6917
self.opt_params = opt_params
@@ -104,6 +52,31 @@ def setup_search(
10452
else:
10553
self.verbosity = []
10654

55+
def convert_results2hyper(self):
56+
self.eval_times = np.array(self.opt_algo.eval_times).sum()
57+
self.iter_times = np.array(self.opt_algo.iter_times).sum()
58+
59+
if self.opt_algo.best_para is not None:
60+
value = self.hg_conv.para2value(self.opt_algo.best_para)
61+
position = self.hg_conv.position2value(value)
62+
best_para = self.hg_conv.value2para(position)
63+
64+
self.best_para = best_para
65+
else:
66+
self.best_para = None
67+
68+
self.best_score = self.opt_algo.best_score
69+
self.positions = self.opt_algo.search_data
70+
71+
self.search_data = self.hg_conv.positions2results(self.positions)
72+
73+
results_dd = self.opt_algo.search_data.drop_duplicates(
74+
subset=self.s_space.dim_keys, keep="first"
75+
)
76+
self.memory_values_df = results_dd[
77+
self.s_space.dim_keys + ["score"]
78+
].reset_index(drop=True)
79+
10780
def _setup_process(self, nth_process):
10881
self.nth_process = nth_process
10982

@@ -118,33 +91,33 @@ def _setup_process(self, nth_process):
11891
self.opt_params["warm_start_smbo"]
11992
)
12093

121-
self._optimizer = self._OptimizerClass(
94+
self.opt_algo = self._OptimizerClass(
12295
search_space=search_space_positions,
12396
initialize=initialize,
12497
random_state=self.random_state,
12598
nth_process=nth_process,
12699
**self.opt_params
127100
)
128101

129-
self.conv = self._optimizer.conv
102+
self.conv = self.opt_algo.conv
130103

131104
def search(self, nth_process):
132105
self._setup_process(nth_process)
133106

134107
gfo_wrapper_model = ObjectiveFunction(
135108
objective_function=self.objective_function,
136-
optimizer=self._optimizer,
109+
optimizer=self.opt_algo,
137110
callbacks=self.callbacks,
138111
catch=self.catch,
139112
nth_process=self.nth_process,
140113
)
141114
gfo_wrapper_model.pass_through = self.pass_through
142115

143-
memory_warm_start = self._convert_args2gfo(self.memory_warm_start)
116+
memory_warm_start = self.hg_conv.conv_memory_warm_start(self.memory_warm_start)
144117

145118
gfo_objective_function = gfo_wrapper_model(self.s_space())
146119

147-
self._optimizer.search(
120+
self.opt_algo.search(
148121
objective_function=gfo_objective_function,
149122
n_iter=self.n_iter,
150123
max_time=self.max_time,
@@ -155,5 +128,16 @@ def search(self, nth_process):
155128
verbosity=self.verbosity,
156129
)
157130

158-
self._convert_results2hyper()
159-
self.p_bar = self._optimizer.p_bar
131+
self.convert_results2hyper()
132+
133+
self._add_result_attributes(
134+
self.best_para,
135+
self.best_score,
136+
self.opt_algo.p_bar._best_since_iter,
137+
self.eval_times,
138+
self.iter_times,
139+
self.positions,
140+
self.search_data,
141+
self.memory_values_df,
142+
self.opt_algo.random_seed,
143+
)

0 commit comments

Comments
 (0)