Beispiel #1
0
def basis_plot(formula: gammy.formulae.Formula,
               grid_limits,
               input_maps,
               gridsize=20):
    """Plot all basis functions

    """
    # Figure definition
    N = len(formula)
    fig = plt.figure(figsize=(8, max(4 * N // 2, 8)))
    gs = fig.add_gridspec(N, 1)

    # Data and predictions
    grid = (pipe(grid_limits,
                 utils.listmap(lambda x: np.linspace(x[0], x[1], gridsize)),
                 lambda x: np.array(x).T))

    # Plot stuff
    for i, (basis, input_map) in enumerate(zip(formula.terms, input_maps)):
        ax = fig.add_subplot(gs[i])
        x = input_map(grid)
        for f in basis:
            ax.plot(x, f(grid))

    return fig
Beispiel #2
0
 def predict_variance_marginal(self, input_data, i):
     # Not refactored with predict_marginals for perf reasons
     X = self.formula.build_Xi(input_data, i=i)
     F = bp.nodes.SumMultiply("i,i", self.theta_marginal(i), X)
     mu = np.dot(X, self.mean_theta[i])
     sigma = pipe(F, utils.solve_covariance, np.diag)
     return (mu, sigma)
Beispiel #3
0
 def predict_variance_marginals(self, input_data):
     Xs = self.formula.build_Xs(input_data)
     Fs = [
         bp.nodes.SumMultiply("i,i", theta, X)
         for X, theta in zip(Xs, self.theta_marginals)
     ]
     mus = [np.dot(X, c) for X, c in zip(Xs, self.mean_theta)]
     sigmas = [pipe(F, utils.solve_covariance, np.diag) for F in Fs]
     return list(zip(mus, sigmas))
Beispiel #4
0
    def predict_variance(self, input_data) -> tuple:
        """Predict observations with variance

        Returns
        -------
        (μ, σ) : tuple([np.array, np.array])
            ``μ`` is mean of posterior predictive distribution
            ``σ`` is variances of posterior predictive + noise

        """
        X = self.formula.build_X(input_data)
        F = bp.nodes.SumMultiply("i,i", self.theta, X)
        return (F.get_moments()[0],
                pipe(F, utils.solve_covariance, np.diag) + self.inv_mean_tau)
Beispiel #5
0
def gaussian1d_density_plot(model, grid_limits=[0.5, 1.5]):
    """Plot 1-D density for each parameter

    Parameters
    ----------
    grid_limits : list
        Grid of `tau` has endpoints `[grid_limits[0] * mu, grid_limits[1] * mu]`
        where `mu` is the expectation of `tau`.

    """
    N = len(model)
    fig = plt.figure(figsize=(8, max(4 * N // 2, 8)))
    gs = fig.add_gridspec(N + 1, 1)

    # Plot inverse gamma
    ax = fig.add_subplot(gs[0])
    (b, a) = (-model.tau.phi[0], model.tau.phi[1])
    mu = a / b
    grid = np.arange(0.5 * mu, 1.5 * mu, mu / 300)
    ax.plot(grid, model.tau.pdf(grid))
    ax.set_title(r"$\tau$ = noise inverse variance")
    ax.grid(True)

    # Plot marginal thetas
    for i, theta in enumerate(model.theta_marginals):
        ax = fig.add_subplot(gs[i + 1])
        mus = theta.get_moments()[0]
        mus = np.array([mus]) if mus.shape == () else mus
        cov = utils.solve_covariance(theta)
        stds = pipe(
            np.array([cov]) if cov.shape == () else np.diag(cov), np.sqrt)
        left = (mus - 4 * stds).min()
        right = (mus + 4 * stds).max()
        grid = np.arange(left, right, (right - left) / 300)
        for (mu, std) in zip(mus, stds):
            node = bp.nodes.GaussianARD(mu, 1 / std**2)
            ax.plot(grid, node.pdf(grid))
        ax.set_title(r"$\theta_{0}$".format(i))
        ax.grid(True)

    fig.tight_layout()
    return fig
Beispiel #6
0
    def predict_variance_theta(self, input_data):
        """Predict observations with variance from model parameters

        Returns
        -------
        (μ, σ) : tuple([np.array, np.array])
            ``μ`` is mean of posterior predictive distribution
            ``σ`` is variances of posterior predictive

        """
        X = self.formula.build_X(input_data)
        F = bp.nodes.SumMultiply("i,i", self.theta, X)
        # Ensuring correct moments
        #
        # F = F._ensure_moments(
        #     F, bp.inference.vmp.nodes.gaussian.GaussianMoments, ndim=0
        # )
        #
        # NOTE: See also bp.plot.plot_gaussian how std can be calculated
        return (F.get_moments()[0], pipe(F, utils.solve_covariance, np.diag))
Beispiel #7
0
def gaussian1d_density_plot(model: gammy.bayespy.GAM):
    """Plot 1-D density for each parameter

    """
    N = len(model.formula)
    N_rows = 2 + (N + 1) // 2
    fig = plt.figure(figsize=(8, 2 * N_rows))
    gs = fig.add_gridspec(N + 1, 1)

    # Plot inverse gamma
    ax = fig.add_subplot(gs[0])
    (b, a) = (-model.tau.phi[0], model.tau.phi[1])
    mu = a / b
    grid = np.arange(0.5 * mu, 1.5 * mu, mu / 300)
    ax.plot(grid, model.tau.pdf(grid))
    ax.set_title(r"$\tau$ = noise inverse variance")
    ax.grid(True)

    # Plot marginal thetas
    for i, theta in enumerate(model.theta_marginals):
        ax = fig.add_subplot(gs[i + 1])
        mus = theta.get_moments()[0]
        mus = np.array([mus]) if mus.shape == () else mus
        cov = utils.solve_covariance(theta.get_moments())
        stds = pipe(
            np.array([cov]) if cov.shape == () else np.diag(cov), np.sqrt)
        left = (mus - 4 * stds).min()
        right = (mus + 4 * stds).max()
        grid = np.arange(left, right, (right - left) / 300)
        for (mu, std) in zip(mus, stds):
            node = bp.nodes.GaussianARD(mu, 1 / std**2)
            ax.plot(grid, node.pdf(grid))
        ax.set_title(r"$\theta_{0}$".format(i))
        ax.grid(True)

    fig.tight_layout()
    return fig
Beispiel #8
0
def validation_plot(model,
                    input_data,
                    y,
                    grid_limits,
                    input_maps,
                    index=None,
                    xlabels=None,
                    titles=None,
                    ylabel=None,
                    gridsize=20,
                    **kwargs):
    """Generic validation plot for a GAM

    """
    # TODO: Support larger input dimensions
    index = np.arange(len(input_data)) if index is None else index

    # Figure definitions
    N = len(model)
    fig = plt.figure(figsize=(8, max(4 * N // 2, 8)))
    gs = fig.add_gridspec(N // 2 + 3, 2)
    xlabels = xlabels or [None] * len(model)
    titles = titles or [None] * len(model)

    # Data and predictions
    grid = (pipe(grid_limits,
                 utils.listmap(lambda x: np.linspace(x[0], x[1], gridsize)),
                 lambda x: np.array(x).T) if len(input_data.shape) > 1 else
            np.linspace(grid_limits[0], grid_limits[1], gridsize))
    marginals = model.predict_variance_marginals(grid)
    residuals = model.marginal_residuals(input_data, y)

    # Time series plot
    ax = fig.add_subplot(gs[0, :])
    (mu, sigma_theta) = model.predict_variance_theta(input_data)
    lower = mu - 2 * np.sqrt(sigma_theta + model.inv_mean_tau)
    upper = mu + 2 * np.sqrt(sigma_theta + model.inv_mean_tau)
    ax.plot(index, y, linewidth=0, marker="o", alpha=0.3)
    ax.plot(index, mu, color="k")
    ax.fill_between(index, lower, upper, color="k", alpha=0.3)
    ax.grid(True)

    # XY-plot
    ax = fig.add_subplot(gs[1, :])
    ax.plot(mu, y, alpha=0.3, marker="o", lw=0)
    ax.plot([mu.min(), mu.max()], [mu.min(), mu.max()], c="k", label="x=y")
    ax.legend(loc="best")
    ax.grid(True)
    ax.set_xlabel("Predictions")
    ax.set_ylabel("Observations")

    # Partial residual plots
    for i, ((mu, sigma), res, input_map, xlabel, title) in enumerate(
            zip(marginals, residuals, input_maps, xlabels, titles)):
        x = input_map(grid)
        if len(x.shape) == 1 or x.shape[1] == 1:
            ax = fig.add_subplot(gs[2 + i // 2, i % 2])
            (lower, upper) = (mu - 2 * np.sqrt(sigma), mu + 2 * np.sqrt(sigma))
            ax.scatter(input_map(input_data), res, **kwargs)
            ax.plot(x, mu, c='k', lw=2)
            ax.fill_between(x, lower, upper, alpha=0.3, color="k")
            ax.set_xlabel(xlabel)
        elif x.shape[1] == 2:
            ax = fig.add_subplot(gs[2 + i // 2, i % 2], projection="3d")
            u, v = np.meshgrid(x[:, 0], x[:, 1])
            w = np.hstack((u.reshape(-1, 1), v.reshape(-1, 1)))
            # Override mu and sigma on purpose!
            (mu, sigma) = model.predict_variance_marginal(w, i)
            mu_mesh = mu.reshape(u.shape)
            ax.plot_surface(u, v, mu_mesh)
        else:
            raise NotImplementedError("High-dimensional plots not supported.")
        ax.set_title(title)
        ax.grid(True)

    fig.tight_layout()
    return fig
Beispiel #9
0
 def mean_theta(self):
     return pipe(self.theta.get_moments()[0],
                 lambda x: utils.unflatten(x, self.formula.bases),
                 listmap(np.array))
Beispiel #10
0
      [np.array([[1, 2], [4, 5]]), np.array([[9]])]),
     (np.array([[1, 2], [3, 4]]),
      [np.array([[np.nan, np.nan], [np.nan, np.inf]]),
       np.array([])], [np.array([[1, 2], [3, 4]])])])
def test_extract_diag_blocks(x, y, expected):
    assert all([
        array_equal(*args)
        for args in zip(expected, utils.extract_diag_blocks(x, y))
    ])
    return


@pytest.mark.parametrize(
    "mu,Sigma",
    [(np.random.rand(23),
      utils.pipe(np.random.randn(23, 23), lambda A: np.dot(A.T, A)))])
def test_solve_covariance(mu, Sigma):
    node = bp.nodes.Gaussian(mu, np.linalg.inv(Sigma))
    assert_almost_equal(utils.solve_covariance(node.get_moments()),
                        Sigma,
                        decimal=8)
    return


@pytest.mark.parametrize("order,expected",
                         [(
                             1,
                             np.array([0, 1, 2, 3]),
                         ), (2, np.array([-1, 0, 1, 2, 3, 4])),
                          (3, np.array([-2, -1, 0, 1, 2, 3, 4, 5]))])
def test_extend_spline_grid(order, expected):