Passed
Push — master ( b8f359...927840 )
by Simon
03:10
created

hyperactive.optimizers._BaseOptimizer_.search()   A

Complexity

Conditions 1

Size

Total Lines 32
Code Lines 27

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 27
nop 11
dl 0
loc 32
rs 9.232
c 0
b 0
f 0

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
# Author: Simon Blanke
2
# Email: [email protected]
3
# License: MIT License
4
5
import numpy as np
6
import pandas as pd
7
8
from gradient_free_optimizers import (
9
    HillClimbingOptimizer as _HillClimbingOptimizer,
10
    StochasticHillClimbingOptimizer as _StochasticHillClimbingOptimizer,
11
    RepulsingHillClimbingOptimizer as _RepulsingHillClimbingOptimizer,
12
    RandomSearchOptimizer as _RandomSearchOptimizer,
13
    RandomRestartHillClimbingOptimizer as _RandomRestartHillClimbingOptimizer,
14
    RandomAnnealingOptimizer as _RandomAnnealingOptimizer,
15
    SimulatedAnnealingOptimizer as _SimulatedAnnealingOptimizer,
16
    ParallelTemperingOptimizer as _ParallelTemperingOptimizer,
17
    ParticleSwarmOptimizer as _ParticleSwarmOptimizer,
18
    EvolutionStrategyOptimizer as _EvolutionStrategyOptimizer,
19
    BayesianOptimizer as _BayesianOptimizer,
20
    TreeStructuredParzenEstimators as _TreeStructuredParzenEstimators,
21
    DecisionTreeOptimizer as _DecisionTreeOptimizer,
22
    EnsembleOptimizer as _EnsembleOptimizer,
23
)
24
25
from .hyper_gradient_trafo import HyperGradientTrafo
26
27
28
class DictClass:
29
    def __init__(self):
30
        self.para_dict = {}
31
32
    def __getitem__(self, key):
33
        return self.para_dict[key]
34
35
    def keys(self):
36
        return self.para_dict.keys()
37
38
    def values(self):
39
        return self.para_dict.values()
40
41
42
class TrafoClass:
43
    def __init__(self, *args, **kwargs):
44
        pass
45
46
    def _convert_args2gfo(self, memory_warm_start):
47
        memory_warm_start = self.trafo.trafo_memory_warm_start(memory_warm_start)
48
49
        return memory_warm_start
50
51
    def _positions2results(self, positions):
52
        results_dict = {}
53
54
        for para_name in self.conv.para_names:
55
            values_list = self.search_space[para_name]
56
            pos_ = positions[para_name].values
57
            values_ = [values_list[idx] for idx in pos_]
58
            results_dict[para_name] = values_
59
60
        results = pd.DataFrame.from_dict(results_dict)
61
62
        diff_list = np.setdiff1d(positions.columns, results.columns)
63
        results[diff_list] = positions[diff_list]
64
65
        return results
66
67
    def _convert_results2hyper(self):
68
        self.eval_time = np.array(self.optimizer.eval_times).sum()
69
        self.iter_time = np.array(self.optimizer.iter_times).sum()
70
71
        value = self.trafo.para2value(self.optimizer.best_para)
72
        position = self.trafo.position2value(value)
73
        best_para = self.trafo.value2para(position)
74
75
        self.best_para = best_para
76
        self.best_score = self.optimizer.best_score
77
        self.positions = self.optimizer.results
78
79
        self.results = self._positions2results(self.positions)
80
81
        self.memory_positions = self.trafo._memory2dataframe(self.optimizer.memory_dict)
82
        self.memory_values_df = self._positions2results(self.memory_positions)
83
84
85
class _BaseOptimizer_(DictClass, TrafoClass):
86
    def __init__(self, **opt_params):
87
        super().__init__()
88
        self.opt_params = opt_params
89
90
    def init(self, search_space, initialize={"grid": 8, "random": 4, "vertices": 8}):
91
        self.search_space = search_space
92
93
        self.trafo = HyperGradientTrafo(search_space)
94
95
        initialize = self.trafo.trafo_initialize(initialize)
96
        search_space_positions = self.trafo.search_space_positions
97
98
        self.optimizer = self._OptimizerClass(
99
            search_space_positions, initialize, **self.opt_params
100
        )
101
102
        self.conv = self.optimizer.conv
103
104
    def print_info(self, *args):
105
        self.optimizer.print_info(*args)
106
107
    def search(
108
        self,
109
        objective_function,
110
        n_iter,
111
        warm_start=None,
112
        max_time=None,
113
        max_score=None,
114
        memory=True,
115
        memory_warm_start=None,
116
        verbosity={
117
            "progress_bar": True,
118
            "print_results": True,
119
            "print_times": True,
120
        },
121
        random_state=None,
122
        nth_process=None,
123
    ):
124
        memory_warm_start = self._convert_args2gfo(memory_warm_start)
125
126
        self.optimizer.search(
127
            objective_function,
128
            n_iter,
129
            max_time,
130
            max_score,
131
            memory,
132
            memory_warm_start,
133
            verbosity,
134
            random_state,
135
            nth_process,
136
        )
137
138
        self._convert_results2hyper()
139
140
141
class HillClimbingOptimizer(_BaseOptimizer_):
142
    def __init__(self, **opt_params):
143
        super().__init__(**opt_params)
144
        self._OptimizerClass = _HillClimbingOptimizer
145
146
147
class StochasticHillClimbingOptimizer(_BaseOptimizer_):
148
    def __init__(self, **opt_params):
149
        super().__init__(**opt_params)
150
        self._OptimizerClass = _StochasticHillClimbingOptimizer
151
152
153
class RepulsingHillClimbingOptimizer(_BaseOptimizer_):
154
    def __init__(self, **opt_params):
155
        super().__init__(**opt_params)
156
        self._OptimizerClass = _RepulsingHillClimbingOptimizer
157
158
159
class RandomSearchOptimizer(_BaseOptimizer_):
160
    def __init__(self, **opt_params):
161
        super().__init__(**opt_params)
162
        self._OptimizerClass = _RandomSearchOptimizer
163
164
165
class RandomRestartHillClimbingOptimizer(_BaseOptimizer_):
166
    def __init__(self, **opt_params):
167
        super().__init__(**opt_params)
168
        self._OptimizerClass = _RandomRestartHillClimbingOptimizer
169
170
171
class RandomAnnealingOptimizer(_BaseOptimizer_):
172
    def __init__(self, **opt_params):
173
        super().__init__(**opt_params)
174
        self._OptimizerClass = _RandomAnnealingOptimizer
175
176
177
class SimulatedAnnealingOptimizer(_BaseOptimizer_):
178
    def __init__(self, **opt_params):
179
        super().__init__(**opt_params)
180
        self._OptimizerClass = _SimulatedAnnealingOptimizer
181
182
183
class ParallelTemperingOptimizer(_BaseOptimizer_):
184
    def __init__(self, **opt_params):
185
        super().__init__(**opt_params)
186
        self._OptimizerClass = _ParallelTemperingOptimizer
187
188
189
class ParticleSwarmOptimizer(_BaseOptimizer_):
190
    def __init__(self, **opt_params):
191
        super().__init__(**opt_params)
192
        self._OptimizerClass = _ParticleSwarmOptimizer
193
194
195
class EvolutionStrategyOptimizer(_BaseOptimizer_):
196
    def __init__(self, **opt_params):
197
        super().__init__(**opt_params)
198
        self._OptimizerClass = _EvolutionStrategyOptimizer
199
200
201
class BayesianOptimizer(_BaseOptimizer_):
202
    def __init__(self, **opt_params):
203
        super().__init__(**opt_params)
204
        self._OptimizerClass = _BayesianOptimizer
205
206
207
class TreeStructuredParzenEstimators(_BaseOptimizer_):
208
    def __init__(self, **opt_params):
209
        super().__init__(**opt_params)
210
        self._OptimizerClass = _TreeStructuredParzenEstimators
211
212
213
class DecisionTreeOptimizer(_BaseOptimizer_):
214
    def __init__(self, **opt_params):
215
        super().__init__(**opt_params)
216
        self._OptimizerClass = _DecisionTreeOptimizer
217
218
219
class EnsembleOptimizer(_BaseOptimizer_):
220
    def __init__(self, **opt_params):
221
        super().__init__(**opt_params)
222
        self._OptimizerClass = _EnsembleOptimizer
223