TrainingLogBase   A
last analyzed

Complexity

Total Complexity 11

Size/Duplication

Total Lines 93
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
dl 0
loc 93
rs 10
c 0
b 0
f 0
wmc 11

7 Methods

Rating   Name   Duplication   Size   Complexity  
A last_epoch_row() 0 3 1
A resume() 0 12 1
A previous_row() 0 3 1
A __init__() 0 11 3
A _check_time() 0 3 3
A current_row() 0 3 1
A h_uuid() 0 8 1
1
"""The event-based main loop of Blocks."""
2
from abc import ABCMeta
3
from collections import defaultdict
4
from numbers import Integral
5
from uuid import uuid4
6
7
import six
8
9
10
@six.add_metaclass(ABCMeta)
11
class TrainingLogBase(object):
12
    """Base class for training log.
13
14
    A training log stores the training timeline, statistics and other
15
    auxiliary information. Training logs can use different backends e.g.
16
    in-memory Python objects or an SQLite database.
17
18
    Information is stored similar to a nested dictionary, so use
19
    ``log[time][key]`` to read data. An entry without stored data will
20
    return an empty dictionary-like object that can be written to,
21
    ``log[time][key] = value``.
22
23
    Depending on the backend, ``log[time] = {'key': 'value'}`` could fail.
24
    Use ``log[time].update({'key': 'value'})`` for compatibility across
25
    backends.
26
27
    In addition to the set of records displaying training dynamics, a
28
    training log has a :attr:`status` attribute, which is a dictionary with
29
    data that is not bound to a particular time.
30
31
    .. warning::
32
33
       Changes to mutable objects might not be reflected in the log,
34
       depending on the backend. So don't use
35
       ``log.status['key'].append(...)``, use ``log.status['key'] = ...``
36
       instead.
37
38
    Parameters
39
    ----------
40
    uuid : :class:`uuid.UUID`, optional
41
        The UUID of this log. For persistent log backends, passing the UUID
42
        will result in an old log being loaded. Otherwise a new, random
43
        UUID will be created.
44
45
    Attributes
46
    ----------
47
    status : dict
48
        A dictionary with data representing the current state of training.
49
        By default it contains ``iterations_done``, ``epochs_done`` and
50
        ``_epoch_ends`` (a list of time stamps when epochs ended).
51
52
    """
53
    def __init__(self, uuid=None):
54
        if uuid is None:
55
            self.uuid = uuid4()
56
        else:
57
            self.uuid = uuid
58
        if uuid is None:
59
            self.status.update({
0 ignored issues
show
Bug introduced by
The Instance of TrainingLogBase does not seem to have a member named status.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
60
                'iterations_done': 0,
61
                'epochs_done': 0,
62
                '_epoch_ends': [],
63
                'resumed_from': None
64
            })
65
66
    @property
67
    def h_uuid(self):
68
        """Return a hexadecimal version of the UUID bytes.
69
70
        This is necessary to store ids in an SQLite database.
71
72
        """
73
        return self.uuid.hex
74
75
    def resume(self):
76
        """Resume a log by setting a new random UUID.
77
78
        Keeps a record of the old log that this is a continuation of. It
79
        copies the status of the old log into the new log.
80
81
        """
82
        old_uuid = self.h_uuid
83
        old_status = dict(self.status)
0 ignored issues
show
Bug introduced by
The Instance of TrainingLogBase does not seem to have a member named status.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
84
        self.uuid = uuid4()
85
        self.status.update(old_status)
0 ignored issues
show
Bug introduced by
The Instance of TrainingLogBase does not seem to have a member named status.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
86
        self.status['resumed_from'] = old_uuid
0 ignored issues
show
Bug introduced by
The Instance of TrainingLogBase does not seem to have a member named status.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
87
88
    def _check_time(self, time):
89
        if not isinstance(time, Integral) or time < 0:
90
            raise ValueError("time must be a non-negative integer")
91
92
    @property
93
    def current_row(self):
94
        return self[self.status['iterations_done']]
0 ignored issues
show
Bug introduced by
The Instance of TrainingLogBase does not seem to have a member named status.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
95
96
    @property
97
    def previous_row(self):
98
        return self[self.status['iterations_done'] - 1]
0 ignored issues
show
Bug introduced by
The Instance of TrainingLogBase does not seem to have a member named status.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
99
100
    @property
101
    def last_epoch_row(self):
102
        return self[self.status['_epoch_ends'][-1]]
0 ignored issues
show
Bug introduced by
The Instance of TrainingLogBase does not seem to have a member named status.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
103
104
105
class TrainingLog(defaultdict, TrainingLogBase):
106
    """Training log using a `defaultdict` as backend.
107
108
    Notes
109
    -----
110
    For analysis of the logs, it can be useful to convert the log to a
111
    Pandas_ data frame:
112
113
    .. code:: python
114
115
       df = DataFrame.from_dict(log, orient='index')
116
117
    .. _Pandas: http://pandas.pydata.org
118
119
    """
120
    def __init__(self):
121
        defaultdict.__init__(self, dict)
122
        self.status = {}
123
        TrainingLogBase.__init__(self)
124
125
    def __reduce__(self):
126
        constructor, args, _, _, items = super(TrainingLog, self).__reduce__()
0 ignored issues
show
Unused Code introduced by
The variable args seems to be unused.
Loading history...
127
        return constructor, (), self.__dict__, _, items
128
129
    def __getitem__(self, time):
130
        self._check_time(time)
131
        return super(TrainingLog, self).__getitem__(time)
132
133
    def __setitem__(self, time, value):
134
        self._check_time(time)
135
        return super(TrainingLog, self).__setitem__(time, value)
136