def test_nans(self): """ Test multinomial mixture """ # The probabilities p1 cause problems p0 = [0.1, 0.9] p1 = [1.0-1e-50, 1e-50] Z = Categorical([1-1e-10, 1e-10]) X = Mixture(Z, Multinomial, 10, [p0, p1]) u = X._message_to_child() self.assertAllClose(u[0], [1, 9]) p0 = [0.1, 0.9] p1 = [1.0-1e-10, 1e-10] Z = Categorical([1-1e-50, 1e-50]) X = Mixture(Z, Multinomial, 10, [p0, p1]) u = X._message_to_child() self.assertAllClose(u[0], [1, 9]) with warnings.catch_warnings(): warnings.simplefilter("ignore", RuntimeWarning) warnings.simplefilter("ignore", UserWarning) p0 = [0.1, 0.9] p1 = [1.0, 0.0] X = Mixture(0, Multinomial, 10, [p0, p1]) u = X._message_to_child() self.assertAllClose(u[0], np.nan*np.ones(2)) pass
def test_constant(self): """ Test constant categorical nodes """ # Basic test Y = Mixture(2, Gamma, [1, 2, 3], [1, 1, 1]) u = Y._message_to_child() self.assertAllClose(u[0], 3/1) # Test with one plate axis alpha = [[1, 2, 3], [4, 5, 6]] Y = Mixture([2, 1], Gamma, alpha, 1) u = Y._message_to_child() self.assertAllClose(u[0], [3, 5]) # Test with two plate axes alpha = [ [[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]] ] Y = Mixture([[2, 1], [0, 2]], Gamma, alpha, 1) u = Y._message_to_child() self.assertAllClose(u[0], [[3, 5], [7, 12]]) pass
def test_nans(self): """ Test multinomial mixture """ # The probabilities p1 cause problems p0 = [0.1, 0.9] p1 = [1.0 - 1e-50, 1e-50] Z = Categorical([1 - 1e-10, 1e-10]) X = Mixture(Z, Multinomial, 10, [p0, p1]) u = X._message_to_child() self.assertAllClose(u[0], [1, 9]) p0 = [0.1, 0.9] p1 = [1.0 - 1e-10, 1e-10] Z = Categorical([1 - 1e-50, 1e-50]) X = Mixture(Z, Multinomial, 10, [p0, p1]) u = X._message_to_child() self.assertAllClose(u[0], [1, 9]) with warnings.catch_warnings(): warnings.simplefilter("ignore", RuntimeWarning) warnings.simplefilter("ignore", UserWarning) p0 = [0.1, 0.9] p1 = [1.0, 0.0] X = Mixture(0, Multinomial, 10, [p0, p1]) u = X._message_to_child() self.assertAllClose(u[0], np.nan * np.ones(2)) pass
def test_constant(self): """ Test constant categorical nodes """ # Basic test Y = Mixture(2, Gamma, [1, 2, 3], [1, 1, 1]) u = Y._message_to_child() self.assertAllClose(u[0], 3/1) # Test with one plate axis alpha = [[1, 2, 3], [4, 5, 6]] Y = Mixture([2, 1], Gamma, alpha, 1) u = Y._message_to_child() self.assertAllClose(u[0], [3, 5]) # Test with two plate axes alpha = [ [[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]] ] Y = Mixture([[2, 1], [0, 2]], Gamma, alpha, 1) u = Y._message_to_child() self.assertAllClose(u[0], [[3, 5], [7, 12]]) pass
def test_mixture_with_count_array(self): """ Test binomial mixture with varying number of trials """ p0 = 0.6 p1 = 0.9 p2 = 0.3 counts = [[10], [5], [3]] X = Mixture(2, Binomial, counts, [p0, p1, p2]) u = X._message_to_child() self.assertAllClose(u[0], np.array(counts)[:, 0] * np.array(p2)) # Multi-mixture and count array # Shape(p) = (2, 1, 3) + () p = [ [[0.6, 0.9, 0.8]], [[0.1, 0.2, 0.3]], ] # Shape(Z1) = (1, 3) + (2,) -> () + (2,) Z1 = 1 # Shape(Z2) = (1,) + (3,) -> () + (3,) Z2 = 2 # Shape(counts) = (5, 1) counts = [[10], [5], [3], [2], [4]] # Shape(X) = (5,) + () X = Mixture( Z1, Mixture, Z2, Binomial, counts, p, # NOTE: We mix over axes -3 and -1. But as we first mix over the # default (-1), then the next mixing happens over -2 (because one # axis was already dropped). cluster_plate=-2, ) self.assertAllClose(X._message_to_child()[0], np.array(counts)[:, 0] * np.array(p)[Z1, :, Z2]) # Can't have non-singleton axis in counts over the mixed axis p0 = 0.6 p1 = 0.9 p2 = 0.3 counts = [10, 5, 3] self.assertRaises( ValueError, Mixture, 2, Binomial, counts, [p0, p1, p2], ) return
def test_message_to_child(self): """ Test the message to child of Mixture node. """ K = 3 # # Estimate moments from parents only # # Simple case mu = GaussianARD([0,2,4], 1, ndim=0, plates=(K,)) alpha = Gamma(1, 1, plates=(K,)) z = Categorical(np.ones(K)/K) X = Mixture(z, GaussianARD, mu, alpha) self.assertEqual(X.plates, ()) self.assertEqual(X.dims, ( (), () )) u = X._message_to_child() self.assertAllClose(u[0], 2) self.assertAllClose(u[1], 2**2+1) # Broadcasting the moments on the cluster axis mu = GaussianARD(2, 1, ndim=0, plates=(K,)) alpha = Gamma(1, 1, plates=(K,)) z = Categorical(np.ones(K)/K) X = Mixture(z, GaussianARD, mu, alpha) self.assertEqual(X.plates, ()) self.assertEqual(X.dims, ( (), () )) u = X._message_to_child() self.assertAllClose(u[0], 2) self.assertAllClose(u[1], 2**2+1) # # Estimate moments with observed children # pass
def test_message_to_child(self): """ Test the message to child of Mixture node. """ K = 3 # # Estimate moments from parents only # # Simple case mu = GaussianARD([0,2,4], 1, ndim=0, plates=(K,)) alpha = Gamma(1, 1, plates=(K,)) z = Categorical(np.ones(K)/K) X = Mixture(z, GaussianARD, mu, alpha) self.assertEqual(X.plates, ()) self.assertEqual(X.dims, ( (), () )) u = X._message_to_child() self.assertAllClose(u[0], 2) self.assertAllClose(u[1], 2**2+1) # Broadcasting the moments on the cluster axis mu = GaussianARD(2, 1, ndim=0, plates=(K,)) alpha = Gamma(1, 1, plates=(K,)) z = Categorical(np.ones(K)/K) X = Mixture(z, GaussianARD, mu, alpha) self.assertEqual(X.plates, ()) self.assertEqual(X.dims, ( (), () )) u = X._message_to_child() self.assertAllClose(u[0], 2) self.assertAllClose(u[1], 2**2+1) # # Estimate moments with observed children # pass
def test_mixture(self): """ Test mixture of Bernoulli """ P = Mixture([2, 0, 0], Bernoulli, [0.1, 0.2, 0.3]) u = P._message_to_child() self.assertEqual(len(u), 1) self.assertAllClose(u[0], [0.3, 0.1, 0.1]) pass
def test_mixture(self): """ Test mixture of Bernoulli """ P = Mixture([2,0,0], Bernoulli, [0.1, 0.2, 0.3]) u = P._message_to_child() self.assertEqual(len(u), 1) self.assertAllClose(u[0], [0.3, 0.1, 0.1]) pass
def test_mixture(self): """ Test binomial mixture """ X = Mixture(2, Binomial, 10, [0.1, 0.2, 0.3, 0.4]) u = X._message_to_child() self.assertAllClose(u[0], 3.0) pass
def test_mixture(self): """ Test binomial mixture """ X = Mixture(2, Binomial, 10, [0.1, 0.2, 0.3, 0.4]) u = X._message_to_child() self.assertAllClose(u[0], 3.0) pass
def test_mixture(self): """ Test multinomial mixture """ p0 = [0.1, 0.5, 0.2, 0.2] p1 = [0.5, 0.1, 0.1, 0.3] p2 = [0.3, 0.2, 0.1, 0.4] X = Mixture(2, Multinomial, 10, [p0, p1, p2]) u = X._message_to_child() self.assertAllClose(u[0], 10 * np.array(p2)) pass
def test_mixture(self): """ Test multinomial mixture """ p0 = [0.1, 0.5, 0.2, 0.2] p1 = [0.5, 0.1, 0.1, 0.3] p2 = [0.3, 0.2, 0.1, 0.4] X = Mixture(2, Multinomial, 10, [p0, p1, p2]) u = X._message_to_child() self.assertAllClose(u[0], 10*np.array(p2)) pass
def test_message_to_parent(self): """ Test the message to parents of Mixture node. """ K = 3 # Broadcasting the moments on the cluster axis Mu = GaussianARD(2, 1, ndim=0, plates=(K, )) (mu, mumu) = Mu._message_to_child() Alpha = Gamma(3, 1, plates=(K, )) (alpha, logalpha) = Alpha._message_to_child() z = Categorical(np.ones(K) / K) X = Mixture(z, GaussianARD, Mu, Alpha) tau = 4 Y = GaussianARD(X, tau) y = 5 Y.observe(y) (x, xx) = X._message_to_child() m = z._message_from_children() self.assertAllClose( m[0] * np.ones(K), random.gaussian_logpdf(xx * alpha, x * alpha * mu, mumu * alpha, logalpha, 0) * np.ones(K)) m = Mu._message_from_children() self.assertAllClose(m[0], 1 / K * (alpha * x) * np.ones(3)) self.assertAllClose(m[1], -0.5 * 1 / K * alpha * np.ones(3)) # Some parameters do not have cluster plate axis Mu = GaussianARD(2, 1, ndim=0, plates=(K, )) (mu, mumu) = Mu._message_to_child() Alpha = Gamma(3, 1) # Note: no cluster plate axis! (alpha, logalpha) = Alpha._message_to_child() z = Categorical(np.ones(K) / K) X = Mixture(z, GaussianARD, Mu, Alpha) tau = 4 Y = GaussianARD(X, tau) y = 5 Y.observe(y) (x, xx) = X._message_to_child() m = z._message_from_children() self.assertAllClose( m[0] * np.ones(K), random.gaussian_logpdf(xx * alpha, x * alpha * mu, mumu * alpha, logalpha, 0) * np.ones(K)) m = Mu._message_from_children() self.assertAllClose(m[0], 1 / K * (alpha * x) * np.ones(3)) self.assertAllClose(m[1], -0.5 * 1 / K * alpha * np.ones(3)) # Cluster assignments do not have as many plate axes as parameters. M = 2 Mu = GaussianARD(2, 1, ndim=0, plates=(K, M)) (mu, mumu) = Mu._message_to_child() Alpha = Gamma(3, 1, plates=(K, M)) (alpha, logalpha) = Alpha._message_to_child() z = Categorical(np.ones(K) / K) X = Mixture(z, GaussianARD, Mu, Alpha, cluster_plate=-2) tau = 4 Y = GaussianARD(X, tau) y = 5 * np.ones(M) Y.observe(y) (x, xx) = X._message_to_child() m = z._message_from_children() self.assertAllClose( m[0] * np.ones(K), np.sum(random.gaussian_logpdf(xx * alpha, x * alpha * mu, mumu * alpha, logalpha, 0) * np.ones( (K, M)), axis=-1)) m = Mu._message_from_children() self.assertAllClose(m[0] * np.ones((K, M)), 1 / K * (alpha * x) * np.ones((K, M))) self.assertAllClose(m[1] * np.ones((K, M)), -0.5 * 1 / K * alpha * np.ones((K, M))) # Mixed distribution broadcasts g # This tests for a found bug. The bug caused an error. Z = Categorical([0.3, 0.5, 0.2]) X = Mixture(Z, Categorical, [[0.2, 0.8], [0.1, 0.9], [0.3, 0.7]]) m = Z._message_from_children() pass
def test_message_to_parent(self): """ Test the message to parents of Mixture node. """ K = 3 # Broadcasting the moments on the cluster axis Mu = GaussianARD(2, 1, ndim=0, plates=(K,)) (mu, mumu) = Mu._message_to_child() Alpha = Gamma(3, 1, plates=(K,)) (alpha, logalpha) = Alpha._message_to_child() z = Categorical(np.ones(K)/K) X = Mixture(z, GaussianARD, Mu, Alpha) tau = 4 Y = GaussianARD(X, tau) y = 5 Y.observe(y) (x, xx) = X._message_to_child() m = X._message_to_parent(0) self.assertAllClose(m[0], random.gaussian_logpdf(xx*alpha, x*alpha*mu, mumu*alpha, logalpha, 0)) m = X._message_to_parent(1) self.assertAllClose(m[0], 1/K * (alpha*x) * np.ones(3)) self.assertAllClose(m[1], -0.5 * 1/K * alpha * np.ones(3)) # Some parameters do not have cluster plate axis Mu = GaussianARD(2, 1, ndim=0, plates=(K,)) (mu, mumu) = Mu._message_to_child() Alpha = Gamma(3, 1) # Note: no cluster plate axis! (alpha, logalpha) = Alpha._message_to_child() z = Categorical(np.ones(K)/K) X = Mixture(z, GaussianARD, Mu, Alpha) tau = 4 Y = GaussianARD(X, tau) y = 5 Y.observe(y) (x, xx) = X._message_to_child() m = X._message_to_parent(0) self.assertAllClose(m[0], random.gaussian_logpdf(xx*alpha, x*alpha*mu, mumu*alpha, logalpha, 0)) m = X._message_to_parent(1) self.assertAllClose(m[0], 1/K * (alpha*x) * np.ones(3)) self.assertAllClose(m[1], -0.5 * 1/K * alpha * np.ones(3)) # Cluster assignments do not have as many plate axes as parameters. M = 2 Mu = GaussianARD(2, 1, ndim=0, plates=(K,M)) (mu, mumu) = Mu._message_to_child() Alpha = Gamma(3, 1, plates=(K,M)) (alpha, logalpha) = Alpha._message_to_child() z = Categorical(np.ones(K)/K) X = Mixture(z, GaussianARD, Mu, Alpha, cluster_plate=-2) tau = 4 Y = GaussianARD(X, tau) y = 5 * np.ones(M) Y.observe(y) (x, xx) = X._message_to_child() m = X._message_to_parent(0) self.assertAllClose(m[0]*np.ones(K), np.sum(random.gaussian_logpdf(xx*alpha, x*alpha*mu, mumu*alpha, logalpha, 0) * np.ones((K,M)), axis=-1)) m = X._message_to_parent(1) self.assertAllClose(m[0] * np.ones((K,M)), 1/K * (alpha*x) * np.ones((K,M))) self.assertAllClose(m[1] * np.ones((K,M)), -0.5 * 1/K * alpha * np.ones((K,M))) pass
def test_message_to_parent(self): """ Test the message to parents of Mixture node. """ K = 3 # Broadcasting the moments on the cluster axis Mu = GaussianARD(2, 1, ndim=0, plates=(K,)) (mu, mumu) = Mu._message_to_child() Alpha = Gamma(3, 1, plates=(K,)) (alpha, logalpha) = Alpha._message_to_child() z = Categorical(np.ones(K)/K) X = Mixture(z, GaussianARD, Mu, Alpha) tau = 4 Y = GaussianARD(X, tau) y = 5 Y.observe(y) (x, xx) = X._message_to_child() m = z._message_from_children() self.assertAllClose(m[0] * np.ones(K), random.gaussian_logpdf(xx*alpha, x*alpha*mu, mumu*alpha, logalpha, 0) * np.ones(K)) m = Mu._message_from_children() self.assertAllClose(m[0], 1/K * (alpha*x) * np.ones(3)) self.assertAllClose(m[1], -0.5 * 1/K * alpha * np.ones(3)) # Some parameters do not have cluster plate axis Mu = GaussianARD(2, 1, ndim=0, plates=(K,)) (mu, mumu) = Mu._message_to_child() Alpha = Gamma(3, 1) # Note: no cluster plate axis! (alpha, logalpha) = Alpha._message_to_child() z = Categorical(np.ones(K)/K) X = Mixture(z, GaussianARD, Mu, Alpha) tau = 4 Y = GaussianARD(X, tau) y = 5 Y.observe(y) (x, xx) = X._message_to_child() m = z._message_from_children() self.assertAllClose(m[0] * np.ones(K), random.gaussian_logpdf(xx*alpha, x*alpha*mu, mumu*alpha, logalpha, 0) * np.ones(K)) m = Mu._message_from_children() self.assertAllClose(m[0], 1/K * (alpha*x) * np.ones(3)) self.assertAllClose(m[1], -0.5 * 1/K * alpha * np.ones(3)) # Cluster assignments do not have as many plate axes as parameters. M = 2 Mu = GaussianARD(2, 1, ndim=0, plates=(K,M)) (mu, mumu) = Mu._message_to_child() Alpha = Gamma(3, 1, plates=(K,M)) (alpha, logalpha) = Alpha._message_to_child() z = Categorical(np.ones(K)/K) X = Mixture(z, GaussianARD, Mu, Alpha, cluster_plate=-2) tau = 4 Y = GaussianARD(X, tau) y = 5 * np.ones(M) Y.observe(y) (x, xx) = X._message_to_child() m = z._message_from_children() self.assertAllClose(m[0]*np.ones(K), np.sum(random.gaussian_logpdf(xx*alpha, x*alpha*mu, mumu*alpha, logalpha, 0) * np.ones((K,M)), axis=-1)) m = Mu._message_from_children() self.assertAllClose(m[0] * np.ones((K,M)), 1/K * (alpha*x) * np.ones((K,M))) self.assertAllClose(m[1] * np.ones((K,M)), -0.5 * 1/K * alpha * np.ones((K,M))) # Mixed distribution broadcasts g # This tests for a found bug. The bug caused an error. Z = Categorical([0.3, 0.5, 0.2]) X = Mixture(Z, Categorical, [[0.2,0.8], [0.1,0.9], [0.3,0.7]]) m = Z._message_from_children() # # Test nested mixtures # t1 = [1, 1, 0, 3, 3] t2 = [2] p = Dirichlet([1, 1], plates=(4, 3)) X = Mixture(t1, Mixture, t2, Categorical, p) X.observe([1, 1, 0, 0, 0]) p.update() self.assertAllClose( p.phi[0], [ [[1, 1], [1, 1], [2, 1]], [[1, 1], [1, 1], [1, 3]], [[1, 1], [1, 1], [1, 1]], [[1, 1], [1, 1], [3, 1]], ] ) # Test sample plates in nested mixtures t1 = Categorical([0.3, 0.7], plates=(5,)) t2 = [[1], [1], [0], [3], [3]] t3 = 2 p = Dirichlet([1, 1], plates=(2, 4, 3)) X = Mixture(t1, Mixture, t2, Mixture, t3, Categorical, p) X.observe([1, 1, 0, 0, 0]) p.update() self.assertAllClose( p.phi[0], [ [ [[1, 1], [1, 1], [1.3, 1]], [[1, 1], [1, 1], [1, 1.6]], [[1, 1], [1, 1], [1, 1]], [[1, 1], [1, 1], [1.6, 1]], ], [ [[1, 1], [1, 1], [1.7, 1]], [[1, 1], [1, 1], [1, 2.4]], [[1, 1], [1, 1], [1, 1]], [[1, 1], [1, 1], [2.4, 1]], ] ] ) # Check that Gate and nested Mixture are equal t1 = Categorical([0.3, 0.7], plates=(5,)) t2 = Categorical([0.1, 0.3, 0.6], plates=(5, 1)) p = Dirichlet([1, 2, 3, 4], plates=(2, 3)) X = Mixture(t1, Mixture, t2, Categorical, p) X.observe([3, 3, 1, 2, 2]) t1_msg = t1._message_from_children() t2_msg = t2._message_from_children() p_msg = p._message_from_children() t1 = Categorical([0.3, 0.7], plates=(5,)) t2 = Categorical([0.1, 0.3, 0.6], plates=(5, 1)) p = Dirichlet([1, 2, 3, 4], plates=(2, 3)) X = Categorical(Gate(t1, Gate(t2, p))) X.observe([3, 3, 1, 2, 2]) t1_msg2 = t1._message_from_children() t2_msg2 = t2._message_from_children() p_msg2 = p._message_from_children() self.assertAllClose(t1_msg[0], t1_msg2[0]) self.assertAllClose(t2_msg[0], t2_msg2[0]) self.assertAllClose(p_msg[0], p_msg2[0]) pass
def test_message_to_parent(self): """ Test the message to parents of Mixture node. """ K = 3 # Broadcasting the moments on the cluster axis Mu = GaussianARD(2, 1, ndim=0, plates=(K,)) (mu, mumu) = Mu._message_to_child() Alpha = Gamma(3, 1, plates=(K,)) (alpha, logalpha) = Alpha._message_to_child() z = Categorical(np.ones(K)/K) X = Mixture(z, GaussianARD, Mu, Alpha) tau = 4 Y = GaussianARD(X, tau) y = 5 Y.observe(y) (x, xx) = X._message_to_child() m = z._message_from_children() self.assertAllClose(m[0] * np.ones(K), random.gaussian_logpdf(xx*alpha, x*alpha*mu, mumu*alpha, logalpha, 0) * np.ones(K)) m = Mu._message_from_children() self.assertAllClose(m[0], 1/K * (alpha*x) * np.ones(3)) self.assertAllClose(m[1], -0.5 * 1/K * alpha * np.ones(3)) # Some parameters do not have cluster plate axis Mu = GaussianARD(2, 1, ndim=0, plates=(K,)) (mu, mumu) = Mu._message_to_child() Alpha = Gamma(3, 1) # Note: no cluster plate axis! (alpha, logalpha) = Alpha._message_to_child() z = Categorical(np.ones(K)/K) X = Mixture(z, GaussianARD, Mu, Alpha) tau = 4 Y = GaussianARD(X, tau) y = 5 Y.observe(y) (x, xx) = X._message_to_child() m = z._message_from_children() self.assertAllClose(m[0] * np.ones(K), random.gaussian_logpdf(xx*alpha, x*alpha*mu, mumu*alpha, logalpha, 0) * np.ones(K)) m = Mu._message_from_children() self.assertAllClose(m[0], 1/K * (alpha*x) * np.ones(3)) self.assertAllClose(m[1], -0.5 * 1/K * alpha * np.ones(3)) # Cluster assignments do not have as many plate axes as parameters. M = 2 Mu = GaussianARD(2, 1, ndim=0, plates=(K,M)) (mu, mumu) = Mu._message_to_child() Alpha = Gamma(3, 1, plates=(K,M)) (alpha, logalpha) = Alpha._message_to_child() z = Categorical(np.ones(K)/K) X = Mixture(z, GaussianARD, Mu, Alpha, cluster_plate=-2) tau = 4 Y = GaussianARD(X, tau) y = 5 * np.ones(M) Y.observe(y) (x, xx) = X._message_to_child() m = z._message_from_children() self.assertAllClose(m[0]*np.ones(K), np.sum(random.gaussian_logpdf(xx*alpha, x*alpha*mu, mumu*alpha, logalpha, 0) * np.ones((K,M)), axis=-1)) m = Mu._message_from_children() self.assertAllClose(m[0] * np.ones((K,M)), 1/K * (alpha*x) * np.ones((K,M))) self.assertAllClose(m[1] * np.ones((K,M)), -0.5 * 1/K * alpha * np.ones((K,M))) # Mixed distribution broadcasts g # This tests for a found bug. The bug caused an error. Z = Categorical([0.3, 0.5, 0.2]) X = Mixture(Z, Categorical, [[0.2,0.8], [0.1,0.9], [0.3,0.7]]) m = Z._message_from_children() pass