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

hyperactive.hyperactive.Hyperactive.add_search()   B

Complexity

Conditions 4

Size

Total Lines 43
Code Lines 37

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 37
nop 13
dl 0
loc 43
rs 8.9919
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
6
import multiprocessing
7
from tqdm import tqdm
8
9
from .optimizers import RandomSearchOptimizer
10
from .run_search import run_search
11
12
13
def set_n_jobs(n_jobs):
14
    """Sets the number of jobs to run in parallel"""
15
    num_cores = multiprocessing.cpu_count()
16
    if n_jobs == -1 or n_jobs > num_cores:
17
        return num_cores
18
    else:
19
        return n_jobs
20
21
22
class HyperactiveResults:
23
    def __init__(*args, **kwargs):
24
        pass
25
26
    def _sort_results_objFunc(self, objective_function):
27
        import numpy as np
28
        import pandas as pd
29
30
        best_score = -np.inf
31
        best_para = None
32
        results_list = []
33
34
        for results in self.results_list:
35
            nth_process = results["nth_process"]
36
37
            process_infos = self.process_infos[nth_process]
38
            objective_function_ = process_infos["objective_function"]
39
40
            if objective_function_ != objective_function:
41
                continue
42
43
            if results["best_score"] > best_score:
44
                best_score = results["best_score"]
45
                best_para = results["best_para"]
46
47
            results_list.append(results["results"])
48
49
        results = pd.concat(results_list)
50
51
        self.objFunc2results[objective_function] = {
52
            "best_para": best_para,
53
            "best_score": best_score,
54
            "results": results,
55
        }
56
57
    def _sort_results_search_id(self, search_id):
58
        for results in self.results_list:
59
            nth_process = results["nth_process"]
60
            search_id_ = self.process_infos[nth_process]["search_id"]
61
62
            if search_id_ != search_id:
63
                continue
64
65
            best_score = results["best_score"]
66
            best_para = results["best_para"]
67
            results = results["results"]
68
69
            self.search_id2results[search_id] = {
70
                "best_para": best_para,
71
                "best_score": best_score,
72
                "results": results,
73
            }
74
75
    def _get_one_result(self, id_, result_name):
76
        if isinstance(id_, str):
77
            if id_ not in self.search_id2results:
78
                self._sort_results_search_id(id_)
79
80
            return self.search_id2results[id_][result_name]
81
82
        else:
83
            if id_ not in self.objFunc2results:
84
                self._sort_results_objFunc(id_)
85
86
            return self.objFunc2results[id_][result_name]
87
88
    def best_para(self, id_):
89
        return self._get_one_result(id_, "best_para")
90
91
    def best_score(self, id_):
92
        return self._get_one_result(id_, "best_score")
93
94
    def results(self, id_):
95
        return self._get_one_result(id_, "results")
96
97
98
class HyperactiveLongTermMemory:
99
    def __init__(*args, **kwargs):
100
        pass
101
102
    def _load_ltm(self, memory_warm_start):
103
        if self.long_term_memory is not None:
104
            return self.long_term_memory.load()
105
        else:
106
            return memory_warm_start
107
108
    def _save_ltm(self):
109
        for nth_process in self.process_infos.keys():
110
            long_term_memory = self.process_infos[nth_process]["long_term_memory"]
111
            objective_function = self.process_infos[nth_process]["objective_function"]
112
            memory_results = self.results_list[nth_process]["memory_values_df"]
113
114
            if long_term_memory is not None:
115
                long_term_memory.save(memory_results, objective_function)
116
117
118
class Hyperactive(HyperactiveResults, HyperactiveLongTermMemory):
119
    def __init__(
120
        self,
121
        verbosity=["progress_bar", "print_results", "print_times"],
122
        distribution={
123
            "multiprocessing": {
124
                "initializer": tqdm.set_lock,
125
                "initargs": (tqdm.get_lock(),),
126
            }
127
        },
128
    ):
129
        super().__init__()
130
        if verbosity is False:
131
            verbosity = []
132
133
        self.verbosity = verbosity
134
        self.distribution = distribution
135
        self.search_ids = []
136
137
        self.process_infos = {}
138
139
        self.objFunc2results = {}
140
        self.search_id2results = {}
141
142
    def _add_search_processes(
143
        self,
144
        random_state,
145
        objective_function,
146
        search_space,
147
        optimizer,
148
        n_iter,
149
        n_jobs,
150
        max_score,
151
        memory,
152
        memory_warm_start,
153
        long_term_memory,
154
        search_id,
155
    ):
156
        for nth_job in range(set_n_jobs(n_jobs)):
157
            nth_process = len(self.process_infos)
158
159
            self.process_infos[nth_process] = {
160
                "random_state": random_state,
161
                "verbosity": self.verbosity,
162
                "nth_process": nth_process,
163
                "objective_function": objective_function,
164
                "search_space": search_space,
165
                "optimizer": optimizer,
166
                "n_iter": n_iter,
167
                "max_score": max_score,
168
                "memory": memory,
169
                "memory_warm_start": memory_warm_start,
170
                "long_term_memory": long_term_memory,
171
                "search_id": search_id,
172
            }
173
174
    def add_search(
175
        self,
176
        objective_function,
177
        search_space,
178
        n_iter,
179
        search_id=None,
180
        optimizer="default",
181
        n_jobs=1,
182
        initialize={"grid": 4, "random": 2, "vertices": 4},
183
        max_score=None,
184
        random_state=None,
185
        memory=True,
186
        memory_warm_start=None,
187
        long_term_memory=None,
188
    ):
189
        self.long_term_memory = long_term_memory
190
191
        if isinstance(optimizer, str):
192
            if optimizer == "default":
193
                optimizer = RandomSearchOptimizer()
194
        optimizer.init(search_space, initialize)
195
196
        if search_id is not None:
197
            search_id = search_id
198
            self.search_ids.append(search_id)
199
        else:
200
            search_id = str(len(self.search_ids))
201
            self.search_ids.append(search_id)
202
203
        memory_warm_start = self._load_ltm(memory_warm_start)
204
205
        self._add_search_processes(
206
            random_state,
207
            objective_function,
208
            search_space,
209
            optimizer,
210
            n_iter,
211
            n_jobs,
212
            max_score,
213
            memory,
214
            memory_warm_start,
215
            long_term_memory,
216
            search_id,
217
        )
218
219
    def run(
220
        self,
221
        max_time=None,
222
    ):
223
        for nth_process in self.process_infos.keys():
224
            self.process_infos[nth_process]["max_time"] = max_time
225
226
        self.results_list = run_search(self.process_infos, self.distribution)
227
228
        self._save_ltm()
229