示例#1
0
def test_logpdf(x, w):
    prior = Measure()
    f1, e1 = GP(EQ(), measure=prior), GP(2e-1 * Delta(), measure=prior)
    f2, e2 = GP(Linear(), measure=prior), GP(1e-1 * Delta(), measure=prior)
    gpar = GPAR().add_layer(lambda: (f1, e1)).add_layer(lambda: (f2, e2))

    # Generate some data.
    y = gpar.sample(x, w, latent=True)

    # Compute logpdf.
    x1 = WeightedUnique(x, w[:, 0])
    x2 = WeightedUnique(B.concat(x, y[:, 0:1], axis=1), w[:, 1])
    logpdf1 = (f1 + e1)(x1).logpdf(y[:, 0])
    logpdf2 = (f2 + e2)(x2).logpdf(y[:, 1])

    # Test computation of GPAR.
    assert gpar.logpdf(x, y, w) == logpdf1 + logpdf2
    assert gpar.logpdf(x, y, w, only_last_layer=True) == logpdf2

    # Test resuming computation.
    x_partial, x_ind_partial = gpar.logpdf(x,
                                           y,
                                           w,
                                           return_inputs=True,
                                           outputs=[0])
    assert gpar.logpdf(x_partial, y, w, x_ind=x_ind_partial,
                       outputs=[1]) == logpdf2

    # Test that sampling missing gives a stochastic estimate.
    y[1, 0] = np.nan
    all_different(
        gpar.logpdf(x, y, w, sample_missing=True),
        gpar.logpdf(x, y, w, sample_missing=True),
    )
示例#2
0
def test_obs(x):
    prior = Measure()
    f = GP(EQ(), measure=prior)
    e = GP(1e-1 * Delta(), measure=prior)

    # Generate some data.
    w = B.rand(B.shape(x)[0]) + 1e-2
    y = f(x).sample()

    # Set some observations to be missing.
    y_missing = y.copy()
    y_missing[::2] = np.nan

    # Check dense case.
    gpar = GPAR()
    obs = gpar._obs(x, None, y_missing, w, f, e)
    assert isinstance(obs, Obs)
    approx(
        prior.logpdf(obs),
        (f + e)(WeightedUnique(x[1::2], w[1::2])).logpdf(y[1::2]),
        atol=1e-6,
    )

    # Check sparse case.
    gpar = GPAR(x_ind=x)
    obs = gpar._obs(x, x, y_missing, w, f, e)
    assert isinstance(obs, SparseObs)
    approx(
        prior.logpdf(obs),
        (f + e)(WeightedUnique(x[1::2], w[1::2])).logpdf(y[1::2]),
        atol=1e-6,
    )
示例#3
0
def test_conditioning(x, w):
    prior = Measure()
    f1, e1 = GP(EQ(), measure=prior), GP(1e-10 * Delta(), measure=prior)
    f2, e2 = GP(EQ(), measure=prior), GP(2e-10 * Delta(), measure=prior)
    gpar = GPAR().add_layer(lambda: (f1, e1)).add_layer(lambda: (f2, e2))

    # Generate some data.
    y = B.concat((f1 + e1)(x).sample(), (f2 + e2)(x).sample(), axis=1)

    # Extract posterior processes.
    gpar = gpar | (x, y, w)
    f1_post, e1_post = gpar.layers[0]()
    f2_post, e2_post = gpar.layers[1]()

    # Test independence of noises.
    assert f1_post.measure.kernels[f1_post, e1_post] == ZeroKernel()
    assert f2_post.measure.kernels[f2_post, e2_post] == ZeroKernel()

    # Test form of noises.
    assert e1.mean == e1_post.mean
    assert e1.kernel == e1_post.kernel
    assert e2.mean == e2_post.mean
    assert e2.kernel == e2_post.kernel

    # Test posteriors.
    approx(f1_post.mean(x), y[:, 0:1], atol=1e-3)
    approx(f2_post.mean(B.concat(x, y[:, 0:1], axis=1)), y[:, 1:2], atol=1e-3)
def test_combine():
    x1 = B.linspace(0, 2, 10)
    x2 = B.linspace(2, 4, 10)

    m = Measure()
    p1 = GP(EQ(), measure=m)
    p2 = GP(Matern12(), measure=m)
    y1 = p1(x1).sample()
    y2 = p2(x2).sample()

    # Check the one-argument case.
    assert_equal_normals(combine(p1(x1, 1)), p1(x1, 1))
    fdd_combined, y_combined = combine((p1(x1, 1), B.squeeze(y1)))
    assert_equal_normals(fdd_combined, p1(x1, 1))
    approx(y_combined, y1)

    # Check the two-argument case.
    fdd_combined = combine(p1(x1, 1), p2(x2, 2))
    assert_equal_normals(
        fdd_combined,
        Normal(B.block_diag(p1(x1, 1).var,
                            p2(x2, 2).var)),
    )
    fdd_combined, y_combined = combine((p1(x1, 1), B.squeeze(y1)),
                                       (p2(x2, 2), y2))
    assert_equal_normals(
        fdd_combined,
        Normal(B.block_diag(p1(x1, 1).var,
                            p2(x2, 2).var)),
    )
    approx(y_combined, B.concat(y1, y2, axis=0))
示例#5
0
def test_logpdf():
    graph = Graph()
    f1, e1 = GP(EQ(), graph=graph), GP(2e-1 * Delta(), graph=graph)
    f2, e2 = GP(Linear(), graph=graph), GP(1e-1 * Delta(), graph=graph)
    gpar = GPAR().add_layer(lambda: (f1, e1)).add_layer(lambda: (f2, e2))

    # Sample some data from GPAR.
    x = B.linspace(0, 2, 10, dtype=torch.float64)[:, None]
    y = gpar.sample(x, latent=True)

    # Compute logpdf.
    logpdf1 = (f1 + e1)(x).logpdf(y[:, 0])
    logpdf2 = (f2 + e2)(B.concat([x, y[:, 0:1]], axis=1)).logpdf(y[:, 1])

    # Test computation of GPAR.
    yield eq, gpar.logpdf(x, y), logpdf1 + logpdf2
    yield eq, gpar.logpdf(x, y, only_last_layer=True), logpdf2

    # Test resuming computation.
    x_int, x_ind_int = gpar.logpdf(x, y, return_inputs=True, outputs=[0])
    yield eq, gpar.logpdf(x_int, y, x_ind=x_ind_int, outputs=[1]), logpdf2

    # Test that sampling missing gives a stochastic estimate.
    y[1, 0] = np.nan
    yield ge, \
          B.abs(gpar.logpdf(x, y, sample_missing=True) -
                gpar.logpdf(x, y, sample_missing=True)).numpy(), \
          1e-3
示例#6
0
    def __init__(
        self,
        measure: Measure,
        xs: List[GP],
        h: AbstractMatrix,
        noise_obs: B.Numeric,
        noises_latent: B.Numeric,
    ):
        self.measure = measure
        self.xs = xs
        self.h = h
        self.noise_obs = noise_obs
        self.noises_latent = noises_latent

        # Create noisy latent processes.
        xs_noisy = [
            x + GP(self.noises_latent[i] * Delta(), measure=self.measure)
            for i, x in enumerate(xs)
        ]

        # Create noiseless observed processes.
        self.fs = _matmul(self.h, self.xs)

        # Create observed processes.
        fs_noisy = _matmul(self.h, xs_noisy)
        self.ys = [
            f + GP(self.noise_obs * Delta(), measure=self.measure) for f in fs_noisy
        ]
示例#7
0
def objective(vs, m, x_data, y_data, locs):
    """NLML objective.

    Args:
        vs (:class:`varz.Vars`): Variable container.
        m (int): Number of latent processes.
        x_data (tensor): Time stamps of the observations.
        y_data (tensor): Observations.
        locs (tensor): Spatial locations of observations.

    Returns:
        scalar: Negative log-marginal likelihood.
    """
    y_proj, _, S, noises_obs = project(vs, m, y_data, locs)
    xs, noise_obs, noises_latent = model(vs, m)

    # Add contribution of latent processes.
    lml = 0
    for i, (x, y) in enumerate(zip(xs, y_proj)):
        e_signal = GP((noise_obs / S[i] + noises_latent[i]) * Delta(),
                      graph=x.graph)
        lml += (x + e_signal)(x_data).logpdf(y)

        e_noise = GP(noise_obs / S[i] * Delta(), graph=x.graph)
        lml -= e_noise(x_data).logpdf(y)

    # Add regularisation contribution.
    lml += B.sum(Normal(Diagonal(noises_obs)).logpdf(B.transpose(y_data)))

    # Return negative the evidence, normalised by the number of data points.
    n, p = B.shape(y_data)
    return -lml / (n * p)
示例#8
0
def test_dimensionality():
    m = Measure()
    p1 = GP(EQ(), measure=m)
    p2 = GP(2 * EQ().stretch(2), measure=m)

    k1 = MultiOutputKernel(m, p1, p2)
    k2 = MultiOutputKernel(m, p1, p1)

    assert dimensionality(EQ()) == 1
    assert dimensionality(k1) == 2

    # Test the unpacking of `Wrapped`s and `Join`s.
    assert dimensionality(k1 + k2) == 2
    assert dimensionality(k1 * k2) == 2
    assert dimensionality(k1.periodic(1)) == 2
    assert dimensionality(k1.stretch(2)) == 2

    # Check that dimensionalities must line up.
    with pytest.raises(RuntimeError):
        dimensionality(k1 + EQ())

    # Check `PosteriorKernel`.
    assert dimensionality(PosteriorKernel(EQ(), EQ(), EQ(), None, 0)) == 1
    assert dimensionality(PosteriorKernel(k1, k2, k2, None, 0)) == 2
    assert dimensionality(PosteriorKernel(k1, k2, ADK(EQ()), None, 0)) == 2
    with pytest.raises(RuntimeError):
        assert dimensionality(PosteriorKernel(k1, k2, EQ(), None, 0)) == 2

    # Check `SubspaceKernel`.
    assert dimensionality(SubspaceKernel(EQ(), EQ(), None, 0)) == 1
    assert dimensionality(SubspaceKernel(k1, k2, None, 0)) == 2
    assert dimensionality(SubspaceKernel(k1, ADK(EQ()), None, 0)) == 2
    with pytest.raises(RuntimeError):
        assert dimensionality(SubspaceKernel(k1, EQ(), None, 0)) == 2
示例#9
0
def test_logpdf(x, w):
    prior = Measure()
    f1, noise1 = GP(EQ(), measure=prior), 2e-1
    f2, noise2 = GP(Linear(), measure=prior), 1e-1
    gpar = GPAR().add_layer(lambda: (f1, noise1)).add_layer(lambda: (f2, noise2))

    # Generate some data.
    y = gpar.sample(x, w, latent=True)

    # Compute logpdf.
    x1 = x
    x2 = B.concat(x, y[:, 0:1], axis=1)
    logpdf1 = f1(x1, noise1 / w[:, 0]).logpdf(y[:, 0])
    logpdf2 = f2(x2, noise2 / w[:, 1]).logpdf(y[:, 1])

    # Test computation of GPAR.
    assert gpar.logpdf(x, y, w) == logpdf1 + logpdf2
    assert gpar.logpdf(x, y, w, only_last_layer=True) == logpdf2

    # Test resuming computation.
    x_partial, x_ind_partial = gpar.logpdf(x, y, w, return_inputs=True, outputs=[0])
    assert gpar.logpdf(x_partial, y, w, x_ind=x_ind_partial, outputs=[1]) == logpdf2

    # Test that sampling missing gives a stochastic estimate.
    y[1, 0] = np.nan
    all_different(
        gpar.logpdf(x, y, w, sample_missing=True),
        gpar.logpdf(x, y, w, sample_missing=True),
    )
示例#10
0
def test_conditioning():
    graph = Graph()
    f1, e1 = GP(EQ(), graph=graph), GP(1e-8 * Delta(), graph=graph)
    f2, e2 = GP(EQ(), graph=graph), GP(2e-8 * Delta(), graph=graph)
    gpar = GPAR().add_layer(lambda: (f1, e1)).add_layer(lambda: (f2, e2))

    x = tensor([[1], [2], [3]])
    y = tensor([[4, 5],
                [6, 7],
                [8, 9]])
    gpar = gpar | (x, y)

    # Extract posterior processes.
    f1_post, e1_post = gpar.layers[0]()
    f2_post, e2_post = gpar.layers[1]()

    # Test independence of noises.
    assert graph.kernels[f1_post, e1_post] == ZeroKernel()
    assert graph.kernels[f2_post, e2_post] == ZeroKernel()

    # Test form of noises.
    assert e1.mean == e1_post.mean
    assert e1.kernel == e1_post.kernel
    assert e2.mean == e2_post.mean
    assert e2.kernel == e2_post.kernel

    # Test posteriors.
    approx(f1_post.mean(x), y[:, 0:1])
    approx(f2_post.mean(B.concat(x, y[:, 0:1], axis=1)), y[:, 1:2])
示例#11
0
def test_conditioning():
    graph = Graph()
    f1, e1 = GP(EQ(), graph=graph), GP(1e-8 * Delta(), graph=graph)
    f2, e2 = GP(EQ(), graph=graph), GP(2e-8 * Delta(), graph=graph)
    gpar = GPAR().add_layer(lambda: (f1, e1)).add_layer(lambda: (f2, e2))

    x = array([[1], [2], [3]])
    y = array([[4, 5], [6, 7], [8, 9]])
    gpar = gpar | (x, y)

    # Extract posterior processes.
    f1_post, e1_post = gpar.layers[0]()
    f2_post, e2_post = gpar.layers[1]()

    # Test independence of noises.
    yield eq, graph.kernels[f1_post, e1_post], ZeroKernel()
    yield eq, graph.kernels[f2_post, e2_post], ZeroKernel()

    # Test form of noises.
    yield eq, e1.mean, e1_post.mean
    yield eq, e1.kernel, e1_post.kernel
    yield eq, e2.mean, e2_post.mean
    yield eq, e2.kernel, e2_post.kernel

    # Test posteriors.
    yield approx, f1_post.mean(x), y[:, 0:1]
    yield approx, f2_post.mean(B.concat([x, y[:, 0:1]], axis=1)), y[:, 1:2]
示例#12
0
def test_infer_size():
    x = B.linspace(0, 2, 5)

    m = Measure()
    p1 = GP(EQ(), measure=m)
    p2 = GP(2 * EQ().stretch(2), measure=m)
    k = MultiOutputKernel(m, p1, p2)

    assert infer_size(k, x) == 10
    assert infer_size(k, p1(x)) == 5
    assert infer_size(k, (x, p1(x))) == 15
示例#13
0
def sample(model, t, noise_f):
    """Sample from a model.

    Args:
        model (:class:`gpcm.model.AbstractGPCM`): Model to sample from.
        t (vector): Time points to sample at.
        noise_f (vector): Noise for the sample of the function. Should have the
            same size as `t`.

    Returns:
        tuple[vector, ...]: Tuple containing kernel samples, filter samples, and
            function samples.
    """
    ks, us, fs = [], [], []

    # In the below, we look at the third inducing point, because that is the one
    # determining the value of the filter at zero: the CGPCM adds two extra inducing
    # points to the left.

    # Get a smooth sample.
    u1 = B.ones(model.n_u)
    while B.abs(u1[2]) > 1e-2:
        u1 = B.sample(model.compute_K_u())[:, 0]
    u = GP(model.k_h())
    u = u | (u(model.t_u), u1)
    u1_full = u(t).mean.flatten()

    # Get a rough sample.
    u2 = B.zeros(model.n_u)
    while u2[2] < 0.5:
        u2 = B.sample(model.compute_K_u())[:, 0]
    u = GP(model.k_h())
    u = u | (u(model.t_u), u2)
    u2_full = u(t).mean.flatten()

    with wbml.out.Progress(name="Sampling", total=5) as progress:
        for c in [0, 0.1, 0.23, 0.33, 0.5]:
            # Sample kernel.
            K = model.kernel_approx(t, t, c * u2 + (1 - c) * u1)
            wbml.out.kv("Sampled variance", K[0, 0])
            K = K / K[0, 0]
            ks.append(K[0, :])

            # Store filter.
            us.append(c * u2_full + (1 - c) * u1_full)

            # Sample function.
            f = B.matmul(B.chol(closest_psd(K)), noise_f)
            fs.append(f)

            progress()

    return ks, us, fs
示例#14
0
def test_sample():
    graph = Graph()
    x = array([1, 2, 3])[:, None]

    # Test that it produces random samples. Not sure how to test for
    # correctness.
    f1, e1 = GP(EQ(), graph=graph), GP(1e-1 * Delta(), graph=graph)
    f2, e2 = GP(EQ(), graph=graph), GP(1e-1 * Delta(), graph=graph)
    gpar = GPAR().add_layer(lambda: (f1, e1)).add_layer(lambda: (f2, e2))
    yield ge, B.sum(B.abs(gpar.sample(x) - gpar.sample(x))), 1e-3
    yield ge, \
          B.sum(B.abs(gpar.sample(x, latent=True) -
                      gpar.sample(x, latent=True))), \
          1e-3

    # Test that posterior latent samples are around the data that is
    # conditioned on.
    graph = Graph()
    f1, e1 = GP(EQ(), graph=graph), GP(1e-8 * Delta(), graph=graph)
    f2, e2 = GP(EQ(), graph=graph), GP(1e-8 * Delta(), graph=graph)
    gpar = GPAR().add_layer(lambda: (f1, e1)).add_layer(lambda: (f2, e2))
    y = gpar.sample(x, latent=True)
    gpar = gpar | (x, y)
    yield approx, gpar.sample(x), y, 3
    yield approx, gpar.sample(x, latent=True), y, 3
示例#15
0
 def sample_h(state):
     state, u = self.approximation.p_u.sample(state)
     u = B.mm(self.K_u, u)  # Transform :math:`\hat u` into :math:`u`.
     h = GP(self.k_h())
     h = h | (h(self.t_u), u)  # Condition on sample.
     state, h = h(t_h).sample(state)  # Sample at desired points.
     return state, B.flatten(h)
示例#16
0
    def __or__(self, x_y_w):
        """Condition on data.

        Args:
            x (tensor): Inputs.
            y (tensor): Outputs.
            w (tensor): Weights.

        Returns:
            :class:`.gpar.GPAR`: Updated GPAR model.
        """
        x, y, w = x_y_w
        gpar, x_ind = self.copy(), self.x_ind

        for is_last, ((y, w, mask), model) in last(
                zip(per_output(y, w, keep=self.impute), self.layers)):
            x = x[mask]  # Filter according to mask.
            f, e = model()  # Construct model.
            obs = self._obs(x, x_ind, y, w, f, e)  # Construct observations.

            # Update with posterior.
            post = f.measure | obs
            e_new = GP(e.mean, e.kernel, measure=post)
            gpar.layers.append(construct_model(post(f), e_new))

            # Update inputs.
            if not is_last:
                x, x_ind = self._update_inputs(x, x_ind, y, f, obs)

        return gpar
示例#17
0
文件: model.py 项目: Zhanghq8/gpar
    def __or__(self, x_and_y):
        """Condition on data.

        Args:
            x (tensor): Inputs.
            y (tensor): Outputs.

        Returns:
            :class:`.gpar.GPAR`: Updated GPAR model.
        """
        x, y = x_and_y
        gpar, x_ind = self.copy(), self.x_ind

        for is_last, ((y, mask), model) in \
                last(zip(per_output(y, self.impute), self.layers)):
            x = x[mask]  # Filter according to mask.
            f, e = model()  # Construct model.
            obs = self._obs(x, x_ind, y, f, e)  # Construct observations.

            # Update with posterior.
            f_post = f | obs
            e_new = GP(e.kernel, e.mean, graph=f.graph)
            gpar.layers.append(construct_model(f_post, e_new))

            # Update inputs.
            if not is_last:
                x, x_ind = self._update_inputs(x, x_ind, y, f, obs)

        return gpar
示例#18
0
def test_infer_size():
    x = B.linspace(0, 2, 5)

    m = Measure()
    p1 = GP(EQ(), measure=m)
    p2 = GP(2 * EQ().stretch(2), measure=m)
    k = MultiOutputKernel(m, p1, p2)

    assert infer_size(k, x) == 10
    assert infer_size(k, p1(x)) == 5
    assert infer_size(k, (x, p1(x))) == 15

    # Check that the dimensionality must be inferrable.
    assert infer_size(EQ(), x) == 5
    with pytest.raises(RuntimeError):
        infer_size(ADK(EQ()), x)
示例#19
0
def test_logpdf(x, w):
    # Sample some data from a "sensitive" GPAR.
    reg = GPARRegressor(
        replace=False,
        impute=False,
        nonlinear=True,
        nonlinear_scale=0.1,
        linear=True,
        linear_scale=10.0,
        noise=1e-2,
        normalise_y=False,
    )
    y = reg.sample(x, w, p=2, latent=True)

    # Extract models.
    gpar = _construct_gpar(reg, reg.vs, B.shape(B.uprank(x))[1], 2)
    f1, e1 = gpar.layers[0]()
    f2, e2 = gpar.layers[1]()

    # Test computation under prior.
    x1 = x
    x2 = B.concat(B.uprank(x), y[:, 0:1], axis=1)
    if w is not None:
        x1 = WeightedUnique(x1, w[:, 0])
        x2 = WeightedUnique(x2, w[:, 1])
    logpdf1 = (f1 + e1)(x1).logpdf(y[:, 0])
    logpdf2 = (f2 + e2)(x2).logpdf(y[:, 1])
    approx(reg.logpdf(x, y, w), logpdf1 + logpdf2, atol=1e-6)

    # Test computation under posterior.
    post1 = f1.measure | ((f1 + e1)(x1), y[:, 0])
    post2 = f2.measure | ((f2 + e2)(x2), y[:, 1])
    e1_post = GP(e1.mean, e1.kernel, measure=post1)
    e2_post = GP(e2.mean, e2.kernel, measure=post2)
    logpdf1 = (post1(f1) + e1_post)(x1).logpdf(y[:, 0])
    logpdf2 = (post2(f2) + e2_post)(x2).logpdf(y[:, 1])
    with pytest.raises(RuntimeError):
        reg.logpdf(x, y, w, posterior=True)
    reg.condition(x, y, w)
    approx(reg.logpdf(x, y, w, posterior=True), logpdf1 + logpdf2, atol=1e-6)

    # Test that sampling missing gives a stochastic estimate.
    y[::2, 0] = np.nan
    all_different(
        reg.logpdf(x, y, w, sample_missing=True),
        reg.logpdf(x, y, w, sample_missing=True),
    )
示例#20
0
def test_sample(x, w):
    prior = Measure()

    # Test that it produces random samples.
    f1, noise1 = GP(EQ(), measure=prior), 1e-1
    f2, noise2 = GP(EQ(), measure=prior), 2e-1
    gpar = GPAR().add_layer(lambda: (f1, noise1)).add_layer(lambda: (f2, noise2))
    all_different(gpar.sample(x, w), gpar.sample(x, w))
    all_different(gpar.sample(x, w, latent=True), gpar.sample(x, w, latent=True))

    # Test that posterior latent samples are around the data that is conditioned on.
    prior = Measure()
    f1, noise1 = GP(EQ(), measure=prior), 1e-10
    f2, noise2 = GP(EQ(), measure=prior), 2e-10
    gpar = GPAR().add_layer(lambda: (f1, noise1)).add_layer(lambda: (f2, noise2))
    y = gpar.sample(x, w, latent=True)
    gpar = gpar | (x, y, w)
    approx(gpar.sample(x, w), y, atol=1e-3)
    approx(gpar.sample(x, w, latent=True), y, atol=1e-3)
示例#21
0
def test_dimensionality():
    m = Measure()
    p1 = GP(EQ(), measure=m)
    p2 = GP(2 * EQ().stretch(2), measure=m)

    k1 = MultiOutputKernel(m, p1, p2)
    k2 = MultiOutputKernel(m, p1, p1)

    assert dimensionality(EQ()) == 1
    assert dimensionality(k1) == 2

    # Test the unpacking of `Wrapped`s and `Join`s.
    assert dimensionality(k1 + k2) == 2
    assert dimensionality(k1 * k2) == 2
    assert dimensionality(k1.periodic(1)) == 2
    assert dimensionality(k1.stretch(2)) == 2

    # Test consistency check.
    with pytest.raises(RuntimeError):
        dimensionality(k1 + EQ())
示例#22
0
def test_logpdf():
    # Sample some data from a "sensitive" GPAR.
    reg = GPARRegressor(replace=False,
                        impute=False,
                        nonlinear=True,
                        nonlinear_scale=0.1,
                        linear=True,
                        linear_scale=10.,
                        noise=1e-4,
                        normalise_y=False)
    x = np.linspace(0, 5, 10)
    y = reg.sample(x, p=2, latent=True)

    # Extract models.
    gpar = _construct_gpar(reg, reg.vs, 1, 2)
    f1, e1 = gpar.layers[0]()
    f2, e2 = gpar.layers[1]()

    # Test computation under prior.
    logpdf1 = (f1 + e1)(B.array(x)).logpdf(B.array(y[:, 0]))
    x_stack = np.concatenate([x[:, None], y[:, 0:1]], axis=1)
    logpdf2 = (f2 + e2)(B.array(x_stack)).logpdf(B.array(y[:, 1]))
    yield approx, reg.logpdf(x, y), logpdf1 + logpdf2, 6

    # Test computation under posterior.
    e1_post = GP(e1.kernel, e1.mean, graph=e1.graph)
    e2_post = GP(e2.kernel, e2.mean, graph=e2.graph)
    f1_post = f1 | ((f1 + e1)(B.array(x)), B.array(y[:, 0]))
    f2_post = f2 | ((f2 + e2)(B.array(x_stack)), B.array(y[:, 1]))
    logpdf1 = (f1_post + e1_post)(B.array(x)).logpdf(B.array(y[:, 0]))
    logpdf2 = (f2_post + e2_post)(B.array(x_stack)).logpdf(B.array(y[:, 1]))
    yield raises, RuntimeError, lambda: reg.logpdf(x, y, posterior=True)
    reg.fit(x, y, iters=0)
    yield approx, reg.logpdf(x, y, posterior=True), logpdf1 + logpdf2, 6

    # Test that sampling missing gives a stochastic estimate.
    y[::2, 0] = np.nan
    yield ge, \
          np.abs(reg.logpdf(x, y, sample_missing=True) -
                 reg.logpdf(x, y, sample_missing=True)), \
          1e-3
示例#23
0
def test_conditioning(x, w):
    prior = Measure()
    f1, noise1 = GP(EQ(), measure=prior), 1e-10
    f2, noise2 = GP(EQ(), measure=prior), 2e-10
    gpar = GPAR().add_layer(lambda: (f1, noise1)).add_layer(lambda: (f2, noise2))

    # Generate some data.
    y = B.concat(f1(x, noise1).sample(), f2(x, noise2).sample(), axis=1)

    # Extract posterior processes.
    gpar = gpar | (x, y, w)
    f1_post, noise1_post = gpar.layers[0]()
    f2_post, noise2_post = gpar.layers[1]()

    # Test noises.
    assert noise1 == noise1_post
    assert noise2 == noise2_post

    # Test posteriors.
    approx(f1_post.mean(x), y[:, 0:1], atol=1e-3)
    approx(f2_post.mean(B.concat(x, y[:, 0:1], axis=1)), y[:, 1:2], atol=1e-3)
示例#24
0
    def make_latent_process(i):
        # Long-term trend:
        variance = vs.bnd(0.9, name=f'{i}/long_term/var')
        scale = vs.bnd(2 * 30, name=f'{i}/long_term/scale')
        kernel = variance * EQ().stretch(scale)

        # Short-term trend:
        variance = vs.bnd(0.1, name=f'{i}/short_term/var')
        scale = vs.bnd(20, name=f'{i}/short_term/scale')
        kernel += variance * Matern12().stretch(scale)

        return GP(kernel, graph=g)
示例#25
0
    def __init__(
        self,
        kernels: List[Kernel],
        h: AbstractMatrix,
        noise_obs: B.Numeric,
        noises_latent: B.Numeric,
    ):
        measure = Measure()

        # Create latent processes.
        xs = [GP(k, measure=measure) for k in kernels]
        ILMMPP.__init__(self, measure, xs, h, noise_obs, noises_latent)
示例#26
0
def predict(vs, m, x_data, y_data, locs, x_pred):
    """Make predictions.

    Args:
        vs (:class:`varz.Vars`): Variable container.
        m (int): Number of latent processes.
        x_data (tensor): Time stamps of the observations.
        y_data (tensor): Observations.
        locs (tensor): Spatial locations of observations.
        x_pred (tensor): Time stamps to predict at.

    Returns:
        tuple: Tuple containing the predictions for the latent processes and
            predictions for the observations.
    """
    # Construct model and project data for prediction.
    xs, noise_obs, noises_latent = model(vs, m)
    y_proj, H, S, noises_obs = project(vs, m, y_data, locs)
    L = noise_obs / S + noises_latent

    # Condition latent processes.
    xs_posterior = []
    for x, noise, y in zip(xs, L, y_proj):
        e = GP(noise * Delta(), graph=x.graph)
        xs_posterior.append(x | ((x + e)(x_data), y))
    xs = xs_posterior

    # Extract posterior means and variances of the latent processes.
    x_means, x_vars = zip(*[(x.mean(x_pred)[:, 0], x.kernel.elwise(x_pred)[:,
                                                                           0])
                            for x in xs])

    # Construct predictions for latent processes.
    lat_preds = [
        B.to_numpy(mean, mean - 2 * (var + L[i])**.5,
                   mean + 2 * (var + L[i])**.5)
        for i, (mean, var) in enumerate(zip(x_means, x_vars))
    ]

    # Pull means through mixing matrix.
    x_means = B.stack(*x_means, axis=0)
    y_means = B.matmul(H, x_means)

    # Pull variances through mixing matrix and add noise.
    x_vars = B.stack(*x_vars, axis=0)
    y_vars = B.matmul(H**2, x_vars + noises_latent[:, None]) + noise_obs

    # Construct predictions for observations.
    obs_preds = [(mean, mean - 2 * var**.5, mean + 2 * var**.5)
                 for mean, var in zip(y_means, y_vars)]

    return lat_preds, obs_preds
示例#27
0
def test_fdd_take():
    with Measure():
        f1 = GP(1, EQ())
        f2 = GP(2, Exp())
        f = cross(f1, f2)

    x = B.linspace(0, 3, 5)
    # Build an FDD with a very complicated input specification.
    fdd = f((x, (f2(x), x), f1(x), (f2(x), (f1(x), x))))
    n = infer_size(fdd.p.kernel, fdd.x)
    fdd = f(fdd.x, matrix.Diagonal(B.rand(n)))

    # Flip a coin for every element.
    mask = B.randn(n) > 0
    taken_fdd = B.take(fdd, mask)

    approx(taken_fdd.mean, B.take(fdd.mean, mask))
    approx(taken_fdd.var, B.submatrix(fdd.var, mask))
    approx(taken_fdd.noise, B.submatrix(fdd.noise, mask))
    assert isinstance(taken_fdd.noise, matrix.Diagonal)

    # Test that only masks are supported, for now.
    with pytest.raises(AssertionError):
        B.take(fdd, np.array([1, 2]))
示例#28
0
def test_obs():
    graph = Graph()
    f = GP(EQ(), graph=graph)
    e = GP(1e-8 * Delta(), graph=graph)

    # Check that it produces the correct observations.
    x = B.linspace(0, 0.1, 10, dtype=torch.float64)
    y = f(x).sample()

    # Set some observations to be missing.
    y_missing = y.clone()
    y_missing[::2] = np.nan

    # Check dense case.
    gpar = GPAR()
    obs = gpar._obs(x, None, y_missing, f, e)
    yield eq, type(obs), Obs
    yield approx, y, (f | obs).mean(x)

    # Check sparse case.
    gpar = GPAR(x_ind=x)
    obs = gpar._obs(x, x, y_missing, f, e)
    yield eq, type(obs), SparseObs
    yield approx, y, (f | obs).mean(x)
示例#29
0
def test_fdd():
    p = GP(1, EQ())

    # Test specification without noise.
    for fdd in [p(1), FDD(p, 1)]:
        assert isinstance(fdd, FDD)
        assert identical(fdd.x, 1)
        assert fdd.p is p
        assert isinstance(fdd.noise, matrix.Zero)
        rep = ("<FDD:\n"
               " process=GP(1, EQ()),\n"
               " input=1,\n"
               " noise=<zero matrix: batch=(), shape=(1, 1), dtype=int>>")
        assert str(fdd) == rep
        assert repr(fdd) == rep

        # Check `dtype` and `num_elements`.
        assert B.dtype(fdd) == int
        assert num_elements(fdd) == 1

    # Test specification with noise.
    fdd = p(1.0, np.array([1, 2]))
    assert isinstance(fdd, FDD)
    assert identical(fdd.x, 1.0)
    assert fdd.p is p
    assert isinstance(fdd.noise, matrix.Diagonal)
    assert str(fdd) == (
        "<FDD:\n"
        " process=GP(1, EQ()),\n"
        " input=1.0,\n"
        " noise=<diagonal matrix: batch=(), shape=(2, 2), dtype=int64>>")
    assert repr(fdd) == (
        "<FDD:\n"
        " process=GP(1, EQ()),\n"
        " input=1.0,\n"
        " noise=<diagonal matrix: batch=(), shape=(2, 2), dtype=int64\n"
        "        diag=[1 2]>>")
    assert B.dtype(fdd) == float
    assert num_elements(fdd) == 1

    # Test construction with `id`.
    fdd = FDD(5, 1)
    assert fdd.p is 5
    assert identical(fdd.x, 1)
    assert fdd.noise is None
示例#30
0
def test_fdd_properties():
    p = GP(1, EQ())

    # Sample observations.
    x = B.linspace(0, 5, 5)
    y = p(x, 0.1).sample()

    # Compute posterior.
    p = p | (p(x, 0.1), y)

    fdd = p(B.linspace(0, 5, 10), 0.2)
    mean, var = fdd.mean, fdd.var

    # Check `var_diag`.
    fdd = p(B.linspace(0, 5, 10), 0.2)
    approx(fdd.var_diag, B.diag(var))

    # Check `mean_var`.
    fdd = p(B.linspace(0, 5, 10), 0.2)
    approx(fdd.mean_var, (mean, var))

    # Check `marginals()`.
    fdd = p(B.linspace(0, 5, 10), 0.2)
    approx(fdd.marginals(), (B.flatten(mean), B.diag(var)))