Annotation   A
last analyzed

Complexity

Total Complexity 5

Size/Duplication

Total Lines 103
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
dl 0
loc 103
rs 10
c 0
b 0
f 0
wmc 5

2 Methods

Rating   Name   Duplication   Size   Complexity  
A __init__() 0 3 1
A add_auxiliary_variable() 0 58 4
1
from collections import OrderedDict
2
from ..roles import add_role, AUXILIARY
3
4
5
def add_annotation(var, annotation):
6
    annotations = getattr(var.tag, 'annotations', [])
7
    if any(old_annotation.__class__ == annotation.__class__
8
           for old_annotation in annotations):
9
        raise ValueError
10
    else:
11
        var.tag.annotations = annotations + [annotation]
12
13
14
class Annotation(object):
15
    """Annotations on Theano variables in a graph.
16
17
    In Blocks annotations are automatically attached to variables created
18
    using bricks. One form of annotation is that many variables are
19
    assigned a role (see :class:`.VariableRole`). A second form of
20
    annotation comes in the form of attaching a :class:`Annotation`
21
    instance to the variable's ``tag`` attribute, with auxiliary variables
22
    and/or updates.
23
24
    For example, we might be interested in the mean activation of certain
25
    application of a :class:`.Linear` brick. The variable representing the
26
    mean activation is attached as an auxiliary variable to the annotations
27
    of the input and output variables of this brick. Using the
28
    :class:`ComputationGraph` class (the
29
    :attr:`~ComputationGraph.variables`,
30
    :attr:`~ComputationGraph.auxiliary_variables`, etc.  attributes in
31
    particular) we can retrieve these Theano variables to pass on to the
32
    monitor, use as a regularizer, etc.
33
34
    In most cases, annotations are added on a brick level (e.g. each brick
35
    will assign the weight norm of its weights as an auxiliary value) or on
36
    an application level (e.g. each time a brick is applied, its mean
37
    activation will become an auxiliary variable). However, you can also
38
    add annotations manually, by setting the ``annotation`` value of a
39
    variable's ``tag`` field.
40
41
    Examples
42
    --------
43
    >>> from theano import tensor
44
    >>> x = tensor.vector()
45
    >>> annotation = Annotation()
46
    >>> annotation.add_auxiliary_variable(x + 1, name='x_plus_1')
47
    >>> add_annotation(x, annotation)
48
    >>> y = x ** 2
49
    >>> from blocks.graph import ComputationGraph
50
    >>> cg = ComputationGraph([y])
51
    >>> cg.auxiliary_variables
52
    [x_plus_1]
53
54
    """
55
    def __init__(self):
56
        self.auxiliary_variables = []
57
        self.updates = OrderedDict()
58
59
    def add_auxiliary_variable(self, variable, roles=None, name=None):
60
        """Attach an auxiliary variable to the graph.
61
62
        Auxiliary variables are Theano variables that are not part of a
63
        brick's output, but can be useful nonetheless e.g. as a regularizer
64
        or to monitor during training progress.
65
66
        Parameters
67
        ----------
68
        variable : :class:`~tensor.TensorVariable`
69
            The variable you want to add.
70
        roles : list of :class:`.VariableRole` instances, optional
71
            The roles of this variable. The :const:`.AUXILIARY`
72
            role will automatically be added. Other options are
73
            :const:`.COST`, :const:`.WEIGHT`, etc.
74
        name : str, optional
75
            Name to give to the variable. If the variable already has a
76
            name it will be overwritten.
77
78
        Examples
79
        --------
80
        >>> from blocks.bricks.base import application, Brick
81
        >>> from blocks.roles import COST
82
        >>> from blocks.utils import shared_floatx_nans
83
        >>> class Foo(Brick):
84
        ...     def _allocate(self):
85
        ...         W = shared_floatx_nans((10, 10))
86
        ...         self.add_auxiliary_variable(W.mean(), name='mean_W')
87
        ...     @application
88
        ...     def apply(self, x, application_call):
89
        ...         application_call.add_auxiliary_variable(
90
        ...             x - 1, name='x_minus_1')
91
        ...         application_call.add_auxiliary_variable(
92
        ...             x.mean(), roles=[COST], name='mean_x')
93
        ...         return x + 1
94
        >>> from theano import tensor
95
        >>> x = tensor.vector()
96
        >>> y = Foo().apply(x)
97
        >>> from blocks.graph import ComputationGraph
98
        >>> cg = ComputationGraph([y])
99
        >>> from blocks.filter import VariableFilter
100
        >>> var_filter = VariableFilter(roles=[AUXILIARY])
101
        >>> var_filter(cg.variables)  # doctest: +SKIP
102
        {x_minus_1, mean_W, mean_x}
103
        >>> var_filter = VariableFilter(roles=[COST])
104
        >>> var_filter(cg.variables)  # doctest: +SKIP
105
        {mean_x}
106
107
        """
108
        add_annotation(variable, self)
109
        if name is not None:
110
            variable.name = name
111
            variable.tag.name = name
112
        add_role(variable, AUXILIARY)
113
        if roles is not None:
114
            for role in roles:
115
                add_role(variable, role)
116
        self.auxiliary_variables.append(variable)
117