Skip to content

Commit

Permalink
Move loggers to loggers.py file
Browse files Browse the repository at this point in the history
This move allows us to stop tracking tests for these two objects and
have the package's coverage report more closely representing what
it should.
  • Loading branch information
fmfn committed Feb 20, 2019
1 parent d34f890 commit 0f56599
Show file tree
Hide file tree
Showing 9 changed files with 146 additions and 142 deletions.
1 change: 1 addition & 0 deletions .coveragerc
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,4 @@ omit =
*/setup.py
examples/*
tests/*
bayes_opt/logger.py
2 changes: 1 addition & 1 deletion bayes_opt/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from .bayesian_optimization import BayesianOptimization, Events
from .util import UtilityFunction
from .observer import ScreenLogger, JSONLogger
from .logger import ScreenLogger, JSONLogger

__all__ = [
"BayesianOptimization",
Expand Down
2 changes: 1 addition & 1 deletion bayes_opt/bayesian_optimization.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

from .target_space import TargetSpace
from .event import Events, DEFAULT_EVENTS
from .observer import _get_default_logger
from .logger import _get_default_logger
from .util import UtilityFunction, acq_max, ensure_rng

from sklearn.gaussian_process.kernels import Matern
Expand Down
129 changes: 129 additions & 0 deletions bayes_opt/logger.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
from __future__ import print_function
import os
import json

from .observer import _Tracker
from .event import Events
from .util import Colours


def _get_default_logger(verbose):
return ScreenLogger(verbose=verbose)


class ScreenLogger(_Tracker):
_default_cell_size = 9
_default_precision = 4

def __init__(self, verbose=2):
self._verbose = verbose
self._header_length = None
super(ScreenLogger, self).__init__()

@property
def verbose(self):
return self._verbose

@verbose.setter
def verbose(self, v):
self._verbose = v

def _format_number(self, x):
if isinstance(x, int):
s = "{x:< {s}}".format(
x=x,
s=self._default_cell_size,
)
else:
s = "{x:< {s}.{p}}".format(
x=x,
s=self._default_cell_size,
p=self._default_precision,
)

if len(s) > self._default_cell_size:
if "." in s:
return s[:self._default_cell_size]
else:
return s[:self._default_cell_size - 3] + "..."
return s

def _format_key(self, key):
s = "{key:^{s}}".format(
key=key,
s=self._default_cell_size
)
if len(s) > self._default_cell_size:
return s[:self._default_cell_size - 3] + "..."
return s

def _step(self, instance, colour=Colours.black):
res = instance.res[-1]
cells = []

cells.append(self._format_number(self._iterations + 1))
cells.append(self._format_number(res["target"]))

for key in instance.space.keys:
cells.append(self._format_number(res["params"][key]))

return "| " + " | ".join(map(colour, cells)) + " |"

def _header(self, instance):
cells = []
cells.append(self._format_key("iter"))
cells.append(self._format_key("target"))
for key in instance.space.keys:
cells.append(self._format_key(key))

line = "| " + " | ".join(cells) + " |"
self._header_length = len(line)
return line + "\n" + ("-" * self._header_length)

def _is_new_max(self, instance):
if self._previous_max is None:
self._previous_max = instance.max["target"]
return instance.max["target"] > self._previous_max

def update(self, event, instance):
if event == Events.OPTMIZATION_START:
line = self._header(instance) + "\n"
elif event == Events.OPTMIZATION_STEP:
is_new_max = self._is_new_max(instance)
if self._verbose == 1 and not is_new_max:
line = ""
else:
colour = Colours.purple if is_new_max else Colours.black
line = self._step(instance, colour=colour) + "\n"
elif event == Events.OPTMIZATION_END:
line = "=" * self._header_length + "\n"

if self._verbose:
print(line, end="")
self._update_tracker(event, instance)


class JSONLogger(_Tracker):
def __init__(self, path):
self._path = path if path[-5:] == ".json" else path + ".json"
try:
os.remove(self._path)
except OSError:
pass
super(JSONLogger, self).__init__()

def update(self, event, instance):
if event == Events.OPTMIZATION_STEP:
data = dict(instance.res[-1])

now, time_elapsed, time_delta = self._time_metrics()
data["datetime"] = {
"datetime": now,
"elapsed": time_elapsed,
"delta": time_delta,
}

with open(self._path, "a") as f:
f.write(json.dumps(data) + "\n")

self._update_tracker(event, instance)
126 changes: 0 additions & 126 deletions bayes_opt/observer.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,8 @@
"""
observers...
"""
from __future__ import print_function
import os
import json
from datetime import datetime

from .event import Events
from .util import Colours


class Observer:
Expand Down Expand Up @@ -51,124 +46,3 @@ def _time_metrics(self):
time_elapsed.total_seconds(),
time_delta.total_seconds()
)


def _get_default_logger(verbose):
return ScreenLogger(verbose=verbose)


class ScreenLogger(_Tracker):
_default_cell_size = 9
_default_precision = 4

def __init__(self, verbose=2):
self._verbose = verbose
self._header_length = None
super(ScreenLogger, self).__init__()

@property
def verbose(self):
return self._verbose

@verbose.setter
def verbose(self, v):
self._verbose = v

def _format_number(self, x):
if isinstance(x, int):
s = "{x:< {s}}".format(
x=x,
s=self._default_cell_size,
)
else:
s = "{x:< {s}.{p}}".format(
x=x,
s=self._default_cell_size,
p=self._default_precision,
)

if len(s) > self._default_cell_size:
if "." in s:
return s[:self._default_cell_size]
else:
return s[:self._default_cell_size - 3] + "..."
return s

def _format_key(self, key):
s = "{key:^{s}}".format(
key=key,
s=self._default_cell_size
)
if len(s) > self._default_cell_size:
return s[:self._default_cell_size - 3] + "..."
return s

def _step(self, instance, colour=Colours.black):
res = instance.res[-1]
cells = []

cells.append(self._format_number(self._iterations + 1))
cells.append(self._format_number(res["target"]))

for key in instance.space.keys:
cells.append(self._format_number(res["params"][key]))

return "| " + " | ".join(map(colour, cells)) + " |"

def _header(self, instance):
cells = []
cells.append(self._format_key("iter"))
cells.append(self._format_key("target"))
for key in instance.space.keys:
cells.append(self._format_key(key))

line = "| " + " | ".join(cells) + " |"
self._header_length = len(line)
return line + "\n" + ("-" * self._header_length)

def _is_new_max(self, instance):
if self._previous_max is None:
self._previous_max = instance.max["target"]
return instance.max["target"] > self._previous_max

def update(self, event, instance):
if event == Events.OPTMIZATION_START:
line = self._header(instance) + "\n"
elif event == Events.OPTMIZATION_STEP:
is_new_max = self._is_new_max(instance)
if self._verbose == 1 and not is_new_max:
line = ""
else:
colour = Colours.purple if is_new_max else Colours.black
line = self._step(instance, colour=colour) + "\n"
elif event == Events.OPTMIZATION_END:
line = "=" * self._header_length + "\n"

if self._verbose:
print(line, end="")
self._update_tracker(event, instance)

class JSONLogger(_Tracker):
def __init__(self, path):
self._path = path if path[-5:] == ".json" else path + ".json"
try:
os.remove(self._path)
except OSError:
pass
super(JSONLogger, self).__init__()

def update(self, event, instance):
if event == Events.OPTMIZATION_STEP:
data = dict(instance.res[-1])

now, time_elapsed, time_delta = self._time_metrics()
data["datetime"] = {
"datetime": now,
"elapsed": time_elapsed,
"delta": time_delta,
}

with open(self._path, "a") as f:
f.write(json.dumps(data) + "\n")

self._update_tracker(event, instance)
2 changes: 1 addition & 1 deletion bayes_opt/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ def _wrap_colour(cls, s, colour):

@classmethod
def black(cls, s):
"""Wrap text in blue."""
"""Wrap text in black."""
return cls._wrap_colour(s, cls.END)

@classmethod
Expand Down
14 changes: 11 additions & 3 deletions tests/test_bayesian_optimization.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import numpy as np
from bayes_opt import UtilityFunction
from bayes_opt import BayesianOptimization
from bayes_opt.observer import ScreenLogger
from bayes_opt.logger import ScreenLogger
from bayes_opt.event import Events, DEFAULT_EVENTS


Expand Down Expand Up @@ -71,7 +71,7 @@ def test_probe_eager():


def test_suggest_at_random():
util = UtilityFunction(kind="ucb", kappa=5, xi=0)
util = UtilityFunction(kind="poi", kappa=5, xi=0)
optimizer = BayesianOptimization(target_func, PBOUNDS, random_state=1)

for _ in range(50):
Expand Down Expand Up @@ -248,7 +248,8 @@ def update_end(self, event, instance):
def reset(self):
self.__init__()

optimizer = BayesianOptimization(target_func, PBOUNDS, random_state=1)
optimizer = BayesianOptimization(target_func, PBOUNDS,
random_state=np.random.RandomState(1))

tracker = Tracker()
optimizer.subscribe(
Expand Down Expand Up @@ -282,6 +283,13 @@ def reset(self):
assert tracker.step_count == 3
assert tracker.end_count == 2

optimizer.maximize(init_points=0, n_iter=2)
assert optimizer._queue.empty
assert len(optimizer.space) == 5
assert tracker.start_count == 3
assert tracker.step_count == 5
assert tracker.end_count == 3


if __name__ == '__main__':
r"""
Expand Down
11 changes: 1 addition & 10 deletions tests/test_observer.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from bayes_opt.bayesian_optimization import Observable
from bayes_opt.observer import ScreenLogger, _Tracker, _get_default_logger
from bayes_opt.observer import _Tracker
from bayes_opt.event import Events


Expand Down Expand Up @@ -112,15 +112,6 @@ def max(self):
assert previous_time < tracker._previous_time


def test_get_default_logger():
logger = _get_default_logger(verbose=1)
assert isinstance(logger, ScreenLogger)
assert logger._verbose == 1

logger = _get_default_logger(verbose=2)
assert logger._verbose == 2


if __name__ == '__main__':
r"""
CommandLine:
Expand Down
1 change: 1 addition & 0 deletions tests/test_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ def f(x, y):

def test_colours():
colour_wrappers = [
(Colours.END, Colours.black),
(Colours.BLUE, Colours.blue),
(Colours.BOLD, Colours.bold),
(Colours.CYAN, Colours.cyan),
Expand Down

0 comments on commit 0f56599

Please sign in to comment.