Total Complexity | 6 |
Total Lines | 55 |
Duplicated Lines | 0 % |
Changes | 0 |
1 | """Hyperparameter optimization functionality for backends""" |
||
2 | |||
3 | import abc |
||
4 | import hyperopt |
||
5 | from .backend import AnnifBackend |
||
6 | |||
7 | |||
8 | class HyperparameterOptimizer: |
||
9 | """Base class for hyperparameter optimizers""" |
||
10 | |||
11 | def __init__(self, backend, corpus): |
||
12 | self._backend = backend |
||
13 | self._corpus = corpus |
||
14 | |||
15 | @abc.abstractmethod |
||
16 | def get_hp_space(self): |
||
17 | """Get the hyperparameter space definition of this backend""" |
||
18 | pass # pragma: no cover |
||
19 | |||
20 | def _prepare(self): |
||
21 | """Prepare the optimizer for hyperparameter evaluation""" |
||
22 | pass # pragma: no cover |
||
23 | |||
24 | @abc.abstractmethod |
||
25 | def _test(self, hps): |
||
26 | """Evaluate a set of hyperparameters""" |
||
27 | pass # pragma: no cover |
||
28 | |||
29 | def optimize(self, n_trials): |
||
30 | """Find the optimal hyperparameters by testing up to the given number of |
||
31 | hyperparameter combinations""" |
||
32 | |||
33 | self._prepare() |
||
34 | space = self.get_hp_space() |
||
35 | trials = hyperopt.Trials() |
||
36 | best = hyperopt.fmin( |
||
37 | fn=self._test, |
||
38 | space=space, |
||
39 | algo=hyperopt.tpe.suggest, |
||
40 | max_evals=n_trials, |
||
41 | trials=trials) |
||
42 | return (best, 1 - trials.best_trial['result']['loss']) |
||
43 | |||
44 | |||
45 | class AnnifHyperoptBackend(AnnifBackend): |
||
46 | """Base class for Annif backends that can perform hyperparameter |
||
47 | optimization""" |
||
48 | |||
49 | @abc.abstractmethod |
||
50 | def get_hp_optimizer(self, corpus): |
||
51 | """Get a HyperparameterOptimizer object that can look for |
||
52 | optimal hyperparameter combinations for the given corpus""" |
||
53 | |||
54 | pass # pragma: no cover |
||
55 |