def check_lower_bound(shape_mu, shape_alpha, plates_mu=(), **kwargs): M = GaussianARD(np.ones(plates_mu + shape_mu), np.ones(plates_mu + shape_mu), shape=shape_mu, plates=plates_mu) if not ('ndim' in kwargs or 'shape' in kwargs): kwargs['ndim'] = len(shape_mu) X = GaussianARD(M, 2*np.ones(shape_alpha), **kwargs) Y = GaussianARD(X, 3*np.ones(X.get_shape(0)), **kwargs) Y.observe(4*np.ones(Y.get_shape(0))) X.update() Cov = 1/(2+3) mu = Cov * (2*1 + 3*4) x2 = mu**2 + Cov logH_X = (+ 0.5*(1+np.log(2*np.pi)) + 0.5*np.log(Cov)) logp_X = (- 0.5*np.log(2*np.pi) + 0.5*np.log(2) - 0.5*2*(x2 - 2*mu*1 + 1**2+1)) r = np.prod(X.get_shape(0)) self.assertAllClose(r * (logp_X + logH_X), X.lower_bound_contribution())
def test_message_to_parent(self): """ Test the message to parents of Concatenate node. """ # Two parents without shapes X1 = GaussianARD(0, 1, plates=(2, ), shape=()) X2 = GaussianARD(0, 1, plates=(3, ), shape=()) Z = Concatenate(X1, X2) Y = GaussianARD(Z, 1) Y.observe(np.random.randn(*Y.get_shape(0))) m1 = X1._message_from_children() m2 = X2._message_from_children() m = Z._message_from_children() self.assertAllClose((m[0] * np.ones((5, )))[:2], m1[0] * np.ones( (2, ))) self.assertAllClose((m[1] * np.ones((5, )))[:2], m1[1] * np.ones( (2, ))) self.assertAllClose((m[0] * np.ones((5, )))[2:], m2[0] * np.ones( (3, ))) self.assertAllClose((m[1] * np.ones((5, )))[2:], m2[1] * np.ones( (3, ))) # Two parents with shapes with warnings.catch_warnings(): warnings.simplefilter("ignore", FutureWarning) X1 = GaussianARD(0, 1, plates=(2, ), shape=(4, 6)) X2 = GaussianARD(0, 1, plates=(3, ), shape=(4, 6)) Z = Concatenate(X1, X2) Y = GaussianARD(Z, 1) Y.observe(np.random.randn(*Y.get_shape(0))) m1 = X1._message_from_children() m2 = X2._message_from_children() m = Z._message_from_children() self.assertAllClose((m[0] * np.ones((5, 4, 6)))[:2], m1[0] * np.ones((2, 4, 6))) self.assertAllClose((m[1] * np.ones((5, 4, 6, 4, 6)))[:2], m1[1] * np.ones((2, 4, 6, 4, 6))) self.assertAllClose((m[0] * np.ones((5, 4, 6)))[2:], m2[0] * np.ones((3, 4, 6))) self.assertAllClose((m[1] * np.ones((5, 4, 6, 4, 6)))[2:], m2[1] * np.ones((3, 4, 6, 4, 6))) # Two parents with non-default concatenation axis X1 = GaussianARD(0, 1, plates=(2, 4), shape=()) X2 = GaussianARD(0, 1, plates=(3, 4), shape=()) Z = Concatenate(X1, X2, axis=-2) Y = GaussianARD(Z, 1) Y.observe(np.random.randn(*Y.get_shape(0))) m1 = X1._message_from_children() m2 = X2._message_from_children() m = Z._message_from_children() self.assertAllClose((m[0] * np.ones((5, 4)))[:2], m1[0] * np.ones( (2, 4))) self.assertAllClose((m[1] * np.ones((5, 4)))[:2], m1[1] * np.ones( (2, 4))) self.assertAllClose((m[0] * np.ones((5, 4)))[2:], m2[0] * np.ones( (3, 4))) self.assertAllClose((m[1] * np.ones((5, 4)))[2:], m2[1] * np.ones( (3, 4))) # Constant parent X1 = np.random.randn(2, 4, 6) X2 = GaussianARD(0, 1, plates=(3, ), shape=(4, 6)) Z = Concatenate(X1, X2) Y = GaussianARD(Z, 1) Y.observe(np.random.randn(*Y.get_shape(0))) m1 = Z._message_to_parent(0) m2 = X2._message_from_children() m = Z._message_from_children() self.assertAllClose((m[0] * np.ones((5, 4, 6)))[:2], m1[0] * np.ones((2, 4, 6))) self.assertAllClose((m[1] * np.ones((5, 4, 6, 4, 6)))[:2], m1[1] * np.ones((2, 4, 6, 4, 6))) self.assertAllClose((m[0] * np.ones((5, 4, 6)))[2:], m2[0] * np.ones((3, 4, 6))) self.assertAllClose((m[1] * np.ones((5, 4, 6, 4, 6)))[2:], m2[1] * np.ones((3, 4, 6, 4, 6))) pass
def check(indices, plates, shape, axis=-1, use_mask=False): mu = np.random.rand(*(plates+shape)) alpha = np.random.rand(*(plates+shape)) X = GaussianARD(mu, alpha, shape=shape, plates=plates) Y = Take(X, indices, plate_axis=axis) Z = GaussianARD(Y, 1, shape=shape) z = np.random.randn(*(Z.get_shape(0))) if use_mask: mask = np.mod(np.reshape(np.arange(np.prod(Z.plates)), Z.plates), 2) != 0 else: mask = True Z.observe(z, mask=mask) X.update() (x0, x1) = X.get_moments() # For comparison, build the same model brute force X = GaussianARD(mu, alpha, shape=shape, plates=plates) # Number of trailing plate axes before the take axis N = len(X.plates) + axis # Reshape the take axes into a single axis z_shape = X.plates[:axis] + (-1,) if axis < -1: z_shape = z_shape + X.plates[(axis+1):] z_shape = z_shape + shape z = np.reshape(z, z_shape) # Reshape the take axes into a single axis if use_mask: mask_shape = X.plates[:axis] + (-1,) if axis < -1: mask_shape = mask_shape + X.plates[(axis+1):] mask = np.reshape(mask, mask_shape) for (j, i) in enumerate(range(np.size(indices))): ind = np.array(indices).flatten()[i] index_x = N*(slice(None),) + (ind,) index_z = N*(slice(None),) + (j,) # print(index) Xi = X[index_x] zi = z[index_z] Zi = GaussianARD(Xi, 1, ndim=len(shape)) if use_mask: maski = mask[index_z] else: maski = True Zi.observe(zi, mask=maski) X.update() self.assertAllClose( x0, X.get_moments()[0], ) self.assertAllClose( x1, X.get_moments()[1], ) return
def test_message_to_parent(self): """ Test the message to parents of Concatenate node. """ # Two parents without shapes X1 = GaussianARD(0, 1, plates=(2,), shape=()) X2 = GaussianARD(0, 1, plates=(3,), shape=()) Z = Concatenate(X1, X2) Y = GaussianARD(Z, 1) Y.observe(np.random.randn(*Y.get_shape(0))) m1 = X1._message_from_children() m2 = X2._message_from_children() m = Z._message_from_children() self.assertAllClose((m[0]*np.ones((5,)))[:2], m1[0]*np.ones((2,))) self.assertAllClose((m[1]*np.ones((5,)))[:2], m1[1]*np.ones((2,))) self.assertAllClose((m[0]*np.ones((5,)))[2:], m2[0]*np.ones((3,))) self.assertAllClose((m[1]*np.ones((5,)))[2:], m2[1]*np.ones((3,))) # Two parents with shapes with warnings.catch_warnings(): warnings.simplefilter("ignore", FutureWarning) X1 = GaussianARD(0, 1, plates=(2,), shape=(4,6)) X2 = GaussianARD(0, 1, plates=(3,), shape=(4,6)) Z = Concatenate(X1, X2) Y = GaussianARD(Z, 1) Y.observe(np.random.randn(*Y.get_shape(0))) m1 = X1._message_from_children() m2 = X2._message_from_children() m = Z._message_from_children() self.assertAllClose((m[0]*np.ones((5,4,6)))[:2], m1[0]*np.ones((2,4,6))) self.assertAllClose((m[1]*np.ones((5,4,6,4,6)))[:2], m1[1]*np.ones((2,4,6,4,6))) self.assertAllClose((m[0]*np.ones((5,4,6)))[2:], m2[0]*np.ones((3,4,6))) self.assertAllClose((m[1]*np.ones((5,4,6,4,6)))[2:], m2[1]*np.ones((3,4,6,4,6))) # Two parents with non-default concatenation axis X1 = GaussianARD(0, 1, plates=(2,4), shape=()) X2 = GaussianARD(0, 1, plates=(3,4), shape=()) Z = Concatenate(X1, X2, axis=-2) Y = GaussianARD(Z, 1) Y.observe(np.random.randn(*Y.get_shape(0))) m1 = X1._message_from_children() m2 = X2._message_from_children() m = Z._message_from_children() self.assertAllClose((m[0]*np.ones((5,4)))[:2], m1[0]*np.ones((2,4))) self.assertAllClose((m[1]*np.ones((5,4)))[:2], m1[1]*np.ones((2,4))) self.assertAllClose((m[0]*np.ones((5,4)))[2:], m2[0]*np.ones((3,4))) self.assertAllClose((m[1]*np.ones((5,4)))[2:], m2[1]*np.ones((3,4))) # Constant parent X1 = np.random.randn(2,4,6) X2 = GaussianARD(0, 1, plates=(3,), shape=(4,6)) Z = Concatenate(X1, X2) Y = GaussianARD(Z, 1) Y.observe(np.random.randn(*Y.get_shape(0))) m1 = Z._message_to_parent(0) m2 = X2._message_from_children() m = Z._message_from_children() self.assertAllClose((m[0]*np.ones((5,4,6)))[:2], m1[0]*np.ones((2,4,6))) self.assertAllClose((m[1]*np.ones((5,4,6,4,6)))[:2], m1[1]*np.ones((2,4,6,4,6))) self.assertAllClose((m[0]*np.ones((5,4,6)))[2:], m2[0]*np.ones((3,4,6))) self.assertAllClose((m[1]*np.ones((5,4,6,4,6)))[2:], m2[1]*np.ones((3,4,6,4,6))) pass