def test_logpdf(): m = Measure() p1 = GP(EQ(), measure=m) p2 = GP(Exp(), measure=m) p3 = p1 + p2 x1 = B.linspace(0, 2, 5) x2 = B.linspace(1, 3, 6) x3 = B.linspace(2, 4, 7) y1, y2, y3 = m.sample(p1(x1), p2(x2), p3(x3)) # Test case that only one process is fed. approx(p1(x1).logpdf(y1), m.logpdf(p1(x1), y1)) approx(p1(x1).logpdf(y1), m.logpdf((p1(x1), y1))) # Compute the logpdf with the product rule. d1 = m d2 = d1 | (p1(x1), y1) d3 = d2 | (p2(x2), y2) approx( d1(p1)(x1).logpdf(y1) + d2(p2)(x2).logpdf(y2) + d3(p3)(x3).logpdf(y3), m.logpdf((p1(x1), y1), (p2(x2), y2), (p3(x3), y3)), ) # Check that `Measure.logpdf` allows `Obs` and `PseudoObs`. obs = Obs(p3(x3), y3) approx(m.logpdf(obs), p3(x3).logpdf(y3)) obs = PseudoObs(p3(x3), p3(x3, 1), y3) approx(m.logpdf(obs), p3(x3, 1).logpdf(y3))
def test_pseudo_conditioning_and_elbo(generate_noise_tuple): m = Measure() p1 = GP(EQ(), measure=m) p2 = GP(Exp(), measure=m) p_sum = p1 + p2 # Sample some data to condition on. x1 = B.linspace(0, 2, 3) n1 = generate_noise_tuple(x1) y1 = p1(x1, *n1).sample() tup1 = (p1(x1, *n1), y1) x_sum = B.linspace(3, 5, 3) n_sum = generate_noise_tuple(x_sum) y_sum = p_sum(x_sum, *n_sum).sample() tup_sum = (p_sum(x_sum, *n_sum), y_sum) # Determine FDDs to check. x_check = B.linspace(0, 5, 5) fdds_check = [ cross(p1, p2, p_sum)(x_check), p1(x_check), p2(x_check), p_sum(x_check), ] # Check conditioning and ELBO on one data set. assert_equal_measures( fdds_check, m | tup_sum, m | PseudoObs(p_sum(x_sum), *tup_sum), m | PseudoObs((p_sum(x_sum), ), *tup_sum), m | PseudoObs((p_sum(x_sum), p1(x1)), *tup_sum), m | PseudoObs(p_sum(x_sum), tup_sum), m | PseudoObs((p_sum(x_sum), ), tup_sum), m.condition(PseudoObs((p_sum(x_sum), p1(x1)), tup_sum)), ) approx( m.logpdf(Obs(*tup_sum)), PseudoObs(p_sum(x_sum), tup_sum).elbo(m), ) # Check conditioning and ELBO on two data sets. assert_equal_measures( fdds_check, m | (tup_sum, tup1), m.condition(PseudoObs((p_sum(x_sum), p1(x1)), tup_sum, tup1)), ) approx( m.logpdf(Obs(tup_sum, tup1)), PseudoObs((p_sum(x_sum), p1(x1)), tup_sum, tup1).elbo(m), ) # The following lose information, so check them separately. assert_equal_measures( fdds_check, m | PseudoObs(p_sum(x_sum), tup_sum, tup1), m | PseudoObs((p_sum(x_sum), ), tup_sum, tup1), ) # Test caching. for name in ["K_z", "elbo", "mu", "A"]: obs = PseudoObs(p_sum(x_sum), *tup_sum) assert getattr(obs, name)(m) is getattr(obs, name)(m) # Test requirement that noise must be diagonal. with pytest.raises(RuntimeError): PseudoObs(p_sum(x_sum), (p_sum(x_sum, p_sum(x_sum).var), y_sum)).elbo(m) # Test that noise on inducing points loses information. with pytest.raises(AssertionError): assert_equal_measures( fdds_check, m | tup_sum, m | PseudoObs(p_sum(x_sum, 0.1), *tup_sum), )