Passed
Push — master ( 9587b2...72341c )
by Simon
01:53
created

BaseOptimizer._monitor_search_path()   A

Complexity

Conditions 3

Size

Total Lines 22
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 17
dl 0
loc 22
rs 9.55
c 0
b 0
f 0
cc 3
nop 2
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
                self._monitor_search_path(_p_)
130
131
        _cand_ = self._finish_search(self._core_, _cand_, X, y)
132
133
        return _cand_
134
135
    def _monitor_search_path(self, _p_):
136
        pos_list = []
137
        score_list = []
138
        if isinstance(_p_, list):
139
            for p in _p_:
140
                pos_list.append(p.pos_new)
141
                score_list.append(p.score_new)
142
143
                pos_list_ = np.array(pos_list)
144
                score_list_ = np.array(score_list)
145
146
            self.pos_list.append(pos_list_)
0 ignored issues
show
introduced by
The variable pos_list_ does not seem to be defined in case the for loop on line 139 is not entered. Are you sure this can never be the case?
Loading history...
147
            self.score_list.append(score_list_)
0 ignored issues
show
introduced by
The variable score_list_ does not seem to be defined in case the for loop on line 139 is not entered. Are you sure this can never be the case?
Loading history...
148
        else:
149
            pos_list.append(_p_.pos_new)
150
            score_list.append(_p_.score_new)
151
152
            pos_list_ = np.array(pos_list)
153
            score_list_ = np.array(score_list)
154
155
            self.pos_list.append(pos_list_)
156
            self.score_list.append(score_list_)
157
158
    def _process_results(self, X, y, _cand_):
159
        start_point = self._verb_.print_start_point(_cand_)
160
        self.results_params[_cand_.func_] = start_point
161
        self.results_models[_cand_.func_] = _cand_.model_best
162
163
        if self._core_.meta_learn:
164
            self._meta_.collect(X, y, _cand_)
165
166
    def _search_multiprocessing(self, X, y):
167
        """Wrapper for the parallel search. Passes integer that corresponds to process number"""
168
        pool = multiprocessing.Pool(self._core_.n_jobs)
169
        search = partial(self.search, X=X, y=y)
170
171
        _cand_list = pool.map(search, self._core_._n_process_range)
172
173
        return _cand_list
174
175
    def _run_one_job(self, X, y):
176
        _cand_ = self.search(0, X, y)
177
        self._process_results(X, y, _cand_)
178
179
    def _run_multiple_jobs(self, X, y):
180
        _cand_list = self._search_multiprocessing(X, y)
181
182
        for i in range(int(self._core_.n_jobs / 2)):
183
            print("\n")
184
185
        for _cand_ in _cand_list:
186
            self._process_results(X, y, _cand_)
187
188
    def _fit(self, X, y):
189
        """Public method for starting the search with the training data (X, y)
190
191
        Parameters
192
        ----------
193
        X : array-like or sparse matrix of shape = [n_samples, n_features]
194
195
        y : array-like, shape = [n_samples] or [n_samples, n_outputs]
196
197
        Returns
198
        -------
199
        None
200
        """
201
        self.start_time = time.time()
202
        self.results_params = {}
203
        self.results_models = {}
204
205
        if self._core_.n_jobs == 1:
206
            self._run_one_job(X, y)
207
        else:
208
            self._run_multiple_jobs(X, y)
209