Exemplo n.º 1
0
def _contour_t(mu, Cov, nu, axes=None, scale=4, transpose=False, colors='k'):
    """
    """
    if axes is None:
        axes = plt.gca()

    if np.shape(mu) != (2,) or np.shape(Cov) != (2,2) or np.shape(nu) != ():
        print(np.shape(mu), np.shape(Cov), np.shape(nu))
        raise ValueError("Only 2-d t-distribution allowed")
    
    if transpose:
        mu = mu[[1,0]]
        Cov = Cov[np.ix_([1,0],[1,0])]

    s = np.sqrt(np.diag(Cov))
    x0 = np.linspace(mu[0]-scale*s[0], mu[0]+scale*s[0], num=100)
    x1 = np.linspace(mu[1]-scale*s[1], mu[1]+scale*s[1], num=100)
    X0X1 = misc.grid(x0, x1)
    Y = X0X1 - mu
    L = linalg.chol(Cov)
    logdet_Cov = linalg.chol_logdet(L)
    Z = linalg.chol_solve(L, Y)
    Z = linalg.inner(Y, Z, ndim=1)
    lpdf = random.t_logpdf(Z, logdet_Cov, nu, 2)
    p = np.exp(lpdf)
    shape = (np.size(x0), np.size(x1))
    X0 = np.reshape(X0X1[:,0], shape)
    X1 = np.reshape(X0X1[:,1], shape)
    P = np.reshape(p, shape)
    return axes.contour(X0, X1, P, colors=colors)
Exemplo n.º 2
0
def gaussian_mixture_logpdf(x, w, mu, Sigma):
    # Shape(x)      = (N, D)
    # Shape(w)      = (K,)
    # Shape(mu)     = (K, D)
    # Shape(Sigma)  = (K, D, D)
    # Shape(result) = (N,)

    # Dimensionality
    D = np.shape(x)[-1]

    # Cholesky decomposition of the covariance matrix
    U = linalg.chol(Sigma)

    # Reshape x:
    # Shape(x)     = (N, 1, D)
    x = np.expand_dims(x, axis=-2)

    # (x-mu) and (x-mu)'*inv(Sigma)*(x-mu):
    # Shape(v)     = (N, K, D)
    # Shape(z)     = (N, K)
    v = x - mu
    z = np.einsum('...i,...i', v, linalg.chol_solve(U, v))

    # Log-determinant of Sigma:
    # Shape(ldet)  = (K,)
    ldet = linalg.chol_logdet(U)

    # Compute log pdf for each cluster:
    # Shape(lpdf)  = (N, K)
    lpdf = misc.gaussian_logpdf(z, 0, 0, ldet, D)
Exemplo n.º 3
0
    def check_X(self, mask):
        """
        Check update equations of parent X.

        Use a simple model that has parent nodes and a child node around
        MatrixDot.
        """

        # Parent nodes
        A = Gaussian(self.a.reshape((self.D3,self.D2,1,self.M*self.N)),
                     np.identity(self.M*self.N),
                     name='A')
        X = Gaussian(np.zeros(self.N),
                     np.identity(self.N),
                     plates=(self.D3,1,self.D1),
                     name='X')
        # Node itself
        AX = MatrixDot(A, X, name='AX')
        # Child node
        Y = Gaussian(AX,
                     self.Lambda,
                     plates=(self.D4,self.D3,self.D2,self.D1),
                     name='Y')
        
        # Put in data
        Y.observe(self.y, mask=mask)

        # VB model
        Q = VB(Y, X)
        Q.update(X, repeat=1)
        u = X.get_moments()

        # Compute true solution
        mask = np.ones((self.D4,self.D3,self.D2,self.D1)) * mask
        vv = mask[...,np.newaxis,np.newaxis] * self.vv
        aa = np.einsum('...ki,...kl,...lj->...ij', self.a, vv, self.a)
        aa = aa + np.einsum('...ij,...kl,...kl->...ij', 
                            np.identity(self.N),
                            np.identity(self.M),
                            vv)
        aa = np.sum(aa, axis=2, keepdims=True)
        aa = np.sum(aa, axis=0)
        Cov_X = linalg.chol_inv(linalg.chol(aa + np.identity(self.N)))
        mu_X = np.einsum('...kj,...kl,...l->...j', 
                         self.a,
                         vv,
                         self.y)
        mu_X = np.sum(mu_X, axis=2, keepdims=True)
        mu_X = np.sum(mu_X, axis=0)
        mu_X = np.einsum('...ij,...j->...i', Cov_X, mu_X)

        # Compare VB results to the analytic solution:
        Cov_vb = u[1] - u[0][...,np.newaxis,:]*u[0][...,:,np.newaxis]
        testing.assert_allclose(Cov_vb, Cov_X,
                                err_msg="Incorrect second moment.")
        testing.assert_allclose(u[0], mu_X,
                                err_msg="Incorrect first moment.")
Exemplo n.º 4
0
    def check_A(self, mask):
        """
        Check update equations of parent A.

        Use a simple model that has parent nodes and a child node around
        MatrixDot.
        """

        # Parent nodes
        A = Gaussian(np.zeros(self.M*self.N), 
                     np.identity(self.M*self.N),
                     plates=(self.D3,self.D2,1),
                     name='A')
        X = Gaussian(self.x, np.identity(self.N), name='X')
        # Node itself
        AX = MatrixDot(A, X, name='AX')
        # Child node
        Y = Gaussian(AX,
                     self.Lambda,
                     plates=(self.D4,self.D3,self.D2,self.D1),
                     name='Y')
        
        # Put in data
        Y.observe(self.y, mask=mask)

        # VB model
        Q = VB(Y, A)
        Q.update(A, repeat=1)
        u = A.get_moments()

        # Compute true solution
        mask = np.ones((self.D4,self.D3,self.D2,self.D1)) * mask
        vv = mask[...,np.newaxis,np.newaxis] * self.vv
        xx = (self.x[...,:,np.newaxis] * self.x[...,np.newaxis,:]
              + np.identity(self.N))
        Cov_A = (vv[...,:,np.newaxis,:,np.newaxis] * 
                 xx[...,np.newaxis,:,np.newaxis,:]) # from data
        Cov_A = np.sum(Cov_A, axis=(0,3), keepdims=True)
        Cov_A = np.reshape(Cov_A, 
                           (self.D3,self.D2,1,self.M*self.N,self.M*self.N))
        Cov_A = Cov_A + np.identity(self.M*self.N) # add prior
        Cov_A = linalg.chol_inv(linalg.chol(Cov_A))
        mu_A = np.einsum('...ij,...j,...k->...ik', vv, self.y, self.x)
        mu_A = np.sum(mu_A, axis=(0,3))
        mu_A = np.reshape(mu_A, (self.D3,self.D2,1,self.M*self.N))
        mu_A = np.einsum('...ij,...j->...i', Cov_A, mu_A)


        # Compare VB results to the analytic solution:
        Cov_vb = u[1] - u[0][...,np.newaxis,:]*u[0][...,:,np.newaxis]
        testing.assert_allclose(Cov_vb, Cov_A,
                                err_msg="Incorrect second moment.")
        testing.assert_allclose(u[0], mu_A,
                                err_msg="Incorrect first moment.")
Exemplo n.º 5
0
    def compute_fixed_moments(self, Lambda, gradient=None):
        """ Compute moments for fixed x. """
        L = linalg.chol(Lambda, ndim=self.ndim)
        ldet = linalg.chol_logdet(L, ndim=self.ndim)
        u = [Lambda,
             ldet]

        if gradient is None:
            return u

        du0 = gradient[0]
        du1 = (
            misc.add_trailing_axes(gradient[1], 2*self.ndim)
            * linalg.chol_inv(L, ndim=self.ndim)
        )

        du = du0 + du1

        return (u, du)
Exemplo n.º 6
0
    def compute_fixed_moments_and_f(self, Lambda, mask=True):
        r"""
        Compute u(x) and f(x) for given x.

        .. math:

            u(\Lambda) =
            \begin{bmatrix}
              \Lambda
              \\
              \log |\Lambda|
            \end{bmatrix}
        """
        k = np.shape(Lambda)[-1]
        ldet = linalg.chol_logdet(linalg.chol(Lambda))
        u = [Lambda,
             ldet]
        f = -(k+1)/2 * ldet
        return (u, f)
Exemplo n.º 7
0
    def compute_moments_and_cgf(self, phi, mask=True):
        r"""
        Return moments and cgf for given natural parameters

        .. math::

            \langle u \rangle =
            \begin{bmatrix}
              \phi_2 (-\phi_1)^{-1}
              \\
              -\log|-\phi_1| + \psi_k(\phi_2)
            \end{bmatrix}
            \\
            g(\phi) = \phi_2 \log|-\phi_1| - \log \Gamma_k(\phi_2)
        """
        U = linalg.chol(-phi[0])
        k = np.shape(phi[0])[-1]
        #k = self.dims[0][0]
        logdet_phi0 = linalg.chol_logdet(U)
        u0 = phi[1][...,np.newaxis,np.newaxis] * linalg.chol_inv(U)
        u1 = -logdet_phi0 + misc.multidigamma(phi[1], k)
        u = [u0, u1]
        g = phi[1] * logdet_phi0 - special.multigammaln(phi[1], k)
        return (u, g)
Exemplo n.º 8
0
def kalman_filter(y, U, A, V, mu0, Cov0, out=None):
    """
    Perform Kalman filtering to obtain filtered mean and covariance.

    The parameters of the process may vary in time, thus they are
    given as iterators instead of fixed values.

    Parameters
    ----------
    y : (N,D) array
        "Normalized" noisy observations of the states, that is, the
        observations multiplied by the precision matrix U (and possibly
        other transformation matrices).
    U : (N,D,D) array or N-list of (D,D) arrays
        Precision matrix (i.e., inverse covariance matrix) of the observation 
        noise for each time instance.
    A : (N-1,D,D) array or (N-1)-list of (D,D) arrays
        Dynamic matrix for each time instance.
    V : (N-1,D,D) array or (N-1)-list of (D,D) arrays
        Covariance matrix of the innovation noise for each time instance.

    Returns
    -------
    mu : array
        Filtered mean of the states.
    Cov : array
        Filtered covariance of the states.

    See also
    --------
    rts_smoother
    """
    mu = mu0
    Cov = Cov0

    # Allocate memory for the results
    (N, D) = np.shape(y)
    X = np.empty((N, D))
    CovX = np.empty((N, D, D))

    # Update step for t=0
    M = np.dot(np.dot(Cov, U[0]), Cov) + Cov
    L = linalg.chol(M)
    mu = np.dot(Cov, linalg.chol_solve(L, np.dot(Cov, y[0]) + mu))
    Cov = np.dot(Cov, linalg.chol_solve(L, Cov))
    X[0, :] = mu
    CovX[0, :, :] = Cov

    # for (yn, Un, An, Vn) in zip(y, U, A, V):
    for n in range(len(y) - 1):  # (yn, Un, An, Vn) in zip(y, U, A, V):
        # Prediction step
        mu = np.dot(A[n], mu)
        Cov = np.dot(np.dot(A[n], Cov), A[n].T) + V[n]
        # Update step
        M = np.dot(np.dot(Cov, U[n + 1]), Cov) + Cov
        L = linalg.chol(M)
        mu = np.dot(Cov, linalg.chol_solve(L, np.dot(Cov, y[n + 1]) + mu))
        Cov = np.dot(Cov, linalg.chol_solve(L, Cov))

        # Force symmetric covariance (for numeric inaccuracy)
        Cov = 0.5 * Cov + 0.5 * Cov.T

        # Store results
        X[n + 1, :] = mu
        CovX[n + 1, :, :] = Cov

    return (X, CovX)
Exemplo n.º 9
0
 def compute_fixed_moments(self, Lambda):
     """ Compute moments for fixed x. """
     ldet = linalg.chol_logdet(linalg.chol(Lambda))
     u = [Lambda,
          ldet]
     return u
Exemplo n.º 10
0
 def compute_fixed_moments(self, Lambda):
     """ Compute moments for fixed x. """
     ldet = linalg.chol_logdet(linalg.chol(Lambda))
     u = [Lambda, ldet]
     return u