File: point_estimate.py

package info (click to toggle)
python-bayespy 0.6.2-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,132 kB
  • sloc: python: 22,402; makefile: 156
file content (198 lines) | stat: -rw-r--r-- 5,228 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
################################################################################
# Copyright (C) 2015 Jaakko Luttinen
#
# This file is licensed under the MIT License.
################################################################################


import numpy as np

from .node import Node, Moments
from .stochastic import Stochastic
from .deterministic import Deterministic


class DeltaMoments(Moments):
    r"""
    Class for the moments of constants or delta distributed variables
    """


    def compute_fixed_moments(self, x):
        r"""
        Compute the moments for a fixed value
        """
        return [x]


    def compute_dims_from_values(self, x):
        r"""
        Return the shape of the moments for a fixed value.
        """
        return ((),)


class DeltaToAny(Deterministic):
    r"""
    Special converter of delta moments to any moments
    """


    def __init__(self, X, moments):
        r"""
        """
        self._moments = moments
        self._parent_moments = [DeltaMoments()]
        #(plates, dims) = moments.compute_plates_and_dims(X.get_shape(0))
        dims = moments.compute_dims_from_shape(X.get_shape(0))
        super().__init__(X, dims=dims, **kwargs)
            

    def _compute_moments(self, u_X):
        r"""
        """
        x = u_X[0]
        return self._moments.compute_fixed_moments(x)
    

    def _compute_message_to_parent(self, index, m_child, u_X):
        r"""
        """
        # Convert child message array to a gradient function
        raise NotImplementedError()
        if index == 0:
            m = m_child[:2]
            return m
        else:
            raise ValueError("Invalid parent index")


    def _compute_weights_to_parent(self, index, weights):
        r"""
        """
        raise NotImplementedError()
        if index == 0:
            raise NotImplementedError()
        else:
            raise ValueError("Invalid parent index")


    def _plates_to_parent(self, index):
        r"""
        """
        
        raise NotImplementedError()
        if index == 0:
            self.get_shape(0)
            raise NotImplementedError()
        else:
            raise ValueError("Invalid parent index")


    def _plates_from_parent(self, index):
        r"""
        """
        raise NotImplementedError()
        if index == 0:
            return self.__cached_plates
            raise NotImplementedError()
        else:
            raise ValueError("Invalid parent index")



class Scalar(Stochastic):


    def __init__(self, plates=None):
        dims = [()]
        raise NotImplementedError()


    def get_riemannian_gradient(self):
        m_children = self._message_from_children()
        g = self.annealing * m_children[0]
        return g


    def get_gradient(self, rg):
        return rg


    def get_parameters(self):
        return self.u


    def set_parameters(self, x):
        if len(x) != 1:
            raise Exception("Wrong number of parameters. Should be 1, is {0}".format(len(x)))
        self.u = [x[0]]
        return


class PositiveScalar(Stochastic):
    pass


class Constant(Node):
    r"""
    Node for presenting constant values.

    The node wraps arrays into proper node type.
    """

    def __init__(self, moments, x, **kwargs):
        if not isinstance(moments, Moments) and issubclass(moments, Moments):
            raise ValueError("Give moments as an object instance instead of a class")
        self._moments = moments
        x = np.asanyarray(x)
        # Compute moments
        self.u = self._moments.compute_fixed_moments(x)
        # Dimensions of the moments
        dims = self._moments.compute_dims_from_values(x)
        # Resolve plates
        D = len(dims[0])
        if D > 0:
            plates = np.shape(self.u[0])[:-D]
        else:
            plates = np.shape(self.u[0])
        # Parent constructor
        super().__init__(dims=dims, plates=plates, **kwargs)


    def _get_id_list(self):
        """
        Returns the stochastic ID list.

        This method is used to check that same stochastic nodes are not direct
        parents of a node several times. It is only valid if there are
        intermediate stochastic nodes.

        To put it another way: each ID corresponds to one factor q(..) in the
        posterior approximation. Different IDs mean different factors, thus they
        mean independence. The parents must have independent factors.

        Stochastic nodes should return their unique ID. Deterministic nodes
        should return the IDs of their parents. Constant nodes should return
        empty list of IDs.
        """
        return []

    
    def get_moments(self):
        return self.u


    def set_value(self, x):
        x = np.asanyarray(x)
        shapes = [np.shape(ui) for ui in self.u]
        self.u = self._moments.compute_fixed_moments(x)
        for (i, shape) in enumerate(shapes):
            if np.shape(self.u[i]) != shape:
                raise ValueError("Incorrect shape for the array")


    def lower_bound_contribution(self, gradient=False, **kwargs):
        # Deterministic functions are delta distributions so the lower bound
        # contribuion is zero.
        return 0