Passed
Push — master ( e635ae...dcb08f )
by Simon
02:09 queued 10s
created

BaseOptimizer._initialize_search()   A

Complexity

Conditions 2

Size

Total Lines 15
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 11
dl 0
loc 15
rs 9.85
c 0
b 0
f 0
cc 2
nop 5
1
# Author: Simon Blanke
2
# Email: [email protected]
3
# License: MIT License
4
5
import time
6
import numpy as np
7
import multiprocessing
8
9
from functools import partial
10
11
from .base_positioner import BasePositioner
12
from .verb import VerbosityLVL0, VerbosityLVL1, VerbosityLVL2
13
from .util import init_candidate, init_eval
14
from .candidate import Candidate
15
from meta_learn import HyperactiveWrapper
16
17
18
class BaseOptimizer:
19
    def __init__(self, _core_, _arg_):
20
21
        """
22
23
        Parameters
24
        ----------
25
26
        search_config: dict
27
            A dictionary providing the model and hyperparameter search space for the
28
            optimization process.
29
        n_iter: int
30
            The number of iterations the optimizer performs.
31
        n_jobs: int, optional (default: 1)
32
            The number of searches to run in parallel.
33
        verbosity: int, optional (default: 1)
34
            Verbosity level. 1 prints out warm_start points and their scores.
35
        random_state: int, optional (default: None)
36
            Sets the random seed.
37
        warm_start: dict, optional (default: False)
38
            Dictionary that definies a start point for the optimizer.
39
        memory: bool, optional (default: True)
40
            A memory, that saves the evaluation during the optimization to save time when
41
            optimizer returns to position.
42
        scatter_init: int, optional (default: False)
43
            Defines the number n of random positions that should be evaluated with 1/n the
44
            training data, to find a better initial position.
45
46
        Returns
47
        -------
48
        None
49
50
        """
51
52
        self._core_ = _core_
53
        self._arg_ = _arg_
54
        self._meta_ = None
55
56
        self.search_config = self._core_.search_config
57
        self.n_iter = self._core_.n_iter
58
59
        if self._core_.meta_learn:
60
            self._meta_ = HyperactiveWrapper(self._core_.search_config)
61
62
        verbs = [VerbosityLVL0, VerbosityLVL1, VerbosityLVL2]
63
        self._verb_ = verbs[_core_.verbosity]()
64
65
        self.pos_list = []
66
        self.score_list = []
67
68
    def _init_base_positioner(self, _cand_, positioner=None):
69
        if positioner:
70
            _p_ = positioner(**self._arg_.kwargs_opt)
71
        else:
72
            _p_ = BasePositioner(**self._arg_.kwargs_opt)
73
74
        _p_.pos_current = _cand_.pos_best
75
        _p_.score_current = _cand_.score_best
76
77
        return _p_
78
79
    def _update_pos(self, _cand_, _p_):
80
        _cand_.pos_best = _p_.pos_new
81
        _cand_.score_best = _p_.score_new
82
83
        _p_.pos_current = _p_.pos_new
84
        _p_.score_current = _p_.score_new
85
86
        self._verb_.best_since_iter = _cand_.iter
87
88
        return _cand_, _p_
89
90
    def _initialize_search(self, _core_, nth_process, X, y):
91
        _cand_ = init_candidate(_core_, nth_process, Candidate)
92
        _cand_ = init_eval(_cand_, nth_process, X, y)
93
        _p_ = self._init_opt_positioner(_cand_, X, y)
94
        self._verb_.init_p_bar(_cand_, self._core_)
95
96
        if self._meta_:
97
            meta_data = self._meta_.get_func_metadata(_cand_)
98
99
            self._meta_.retrain(_cand_)
100
            para, score = self._meta_.search(X, y, _cand_)
101
102
            _cand_._space_.load_memory(*meta_data)
103
104
        return _core_, _cand_, _p_
105
106
    def _finish_search(self, _core_, _cand_, X, y):
107
        _cand_.eval_pos(_cand_.pos_best, X, y, force_eval=True)
108
        self.eval_time = _cand_.eval_time_sum
109
        self._verb_.close_p_bar()
110
111
        return _cand_
112
113
    def search(self, nth_process, X, y):
114
        self._core_, _cand_, _p_ = self._initialize_search(
115
            self._core_, nth_process, X, y
116
        )
117
118
        for iter in range(self._core_.n_iter):
119
            _cand_.iter = iter
120
            _cand_ = self._iterate(iter, _cand_, _p_, X, y)
121
            self._verb_.update_p_bar(1, _cand_)
122
123
            run_time = time.time() - self.start_time
124
            if self._core_.max_time and run_time > self._core_.max_time:
125
                break
126
127
            # get_search_path
128
            if self._core_.get_search_path:
129
                pos_list = []
130
                score_list = []
131
                if isinstance(_p_, list):
132
                    for p in _p_:
133
                        pos_list.append(p.pos_new)
134
                        score_list.append(p.score_new)
135
136
                        pos_list_ = np.array(pos_list)
137
                        score_list_ = np.array(score_list)
138
139
                    self.pos_list.append(pos_list_)
0 ignored issues
show
introduced by
The variable pos_list_ does not seem to be defined for all execution paths.
Loading history...
140
                    self.score_list.append(score_list_)
0 ignored issues
show
introduced by
The variable score_list_ does not seem to be defined for all execution paths.
Loading history...
141
                else:
142
                    pos_list.append(_p_.pos_new)
143
                    score_list.append(_p_.score_new)
144
145
                    pos_list_ = np.array(pos_list)
146
                    score_list_ = np.array(score_list)
147
148
                    self.pos_list.append(pos_list_)
149
                    self.score_list.append(score_list_)
150
151
        _cand_ = self._finish_search(self._core_, _cand_, X, y)
152
153
        return _cand_
154
155
    def _process_results(self, X, y, _cand_):
156
        start_point = self._verb_.print_start_point(_cand_)
157
        self.results_params[_cand_.func_] = start_point
158
        self.results_models[_cand_.func_] = _cand_.model_best
159
160
        if self._core_.meta_learn:
161
            self._meta_.collect(X, y, _cand_)
162
163
    def _search_multiprocessing(self, X, y):
164
        """Wrapper for the parallel search. Passes integer that corresponds to process number"""
165
        pool = multiprocessing.Pool(self._core_.n_jobs)
166
        search = partial(self.search, X=X, y=y)
167
168
        _cand_list = pool.map(search, self._core_._n_process_range)
169
170
        return _cand_list
171
172
    def _run_one_job(self, X, y):
173
        _cand_ = self.search(0, X, y)
174
        self._process_results(X, y, _cand_)
175
176
    def _run_multiple_jobs(self, X, y):
177
        _cand_list = self._search_multiprocessing(X, y)
178
179
        for i in range(int(self._core_.n_jobs / 2)):
180
            print("\n")
181
182
        for _cand_ in _cand_list:
183
            self._process_results(X, y, _cand_)
184
185
    def _fit(self, X, y):
186
        """Public method for starting the search with the training data (X, y)
187
188
        Parameters
189
        ----------
190
        X : array-like or sparse matrix of shape = [n_samples, n_features]
191
192
        y : array-like, shape = [n_samples] or [n_samples, n_outputs]
193
194
        Returns
195
        -------
196
        None
197
        """
198
        self.start_time = time.time()
199
        self.results_params = {}
200
        self.results_models = {}
201
202
        if self._core_.n_jobs == 1:
203
            self._run_one_job(X, y)
204
        else:
205
            self._run_multiple_jobs(X, y)
206