Esempio n. 1
0
    def approximate_cholesky(self, epsilon=1e-6):
        r""" Compute low-rank approximation to the Cholesky decomposition of target matrix.

        The decomposition will be conducted while ensuring that the spectrum of `A_k^{-1}` is positive.

        Parameters
        ----------
        epsilon : float, optional, default 1e-6
            Cutoff for eigenvalue norms. If negative eigenvalues occur, with norms larger than epsilon, the largest
            negative eigenvalue norm will be used instead of epsilon, i.e. a band including all negative eigenvalues
            will be cut off.

        Returns
        -------
        L : ndarray((n,m), dtype=float)
            Cholesky matrix such that `A \approx L L^{\top}`. Number of columns :math:`m` is most at the number of columns
            used in the Nystroem approximation, but may be smaller depending on epsilon.

        """
        # compute the Eigenvalues of C0 using Schur factorization
        Wk = self._C_k[self._columns, :]
        L0 = spd_inv_split(Wk, epsilon=epsilon)
        L = np.dot(self._C_k, L0)

        return L
Esempio n. 2
0
    def _diagonalize(self):
        """Performs SVD on covariance matrices and save left, right singular vectors and values in the model.

        Parameters
        ----------
        scaling : None or string, default=None
            Scaling to be applied to the VAMP modes upon transformation
            * None: no scaling will be applied, variance of the singular
              functions is 1
            * 'kinetic map' or 'km': singular functions are scaled by
              singular value. Note that only the left singular functions
              induce a kinetic map.
        """
        L0 = spd_inv_split(self.C00, epsilon=self.epsilon)
        self._rank0 = L0.shape[1] if L0.ndim == 2 else 1
        Lt = spd_inv_split(self.Ctt, epsilon=self.epsilon)
        self._rankt = Lt.shape[1] if Lt.ndim == 2 else 1

        W = np.dot(L0.T, self.C0t).dot(Lt)
        from scipy.linalg import svd
        A, s, BT = svd(W, compute_uv=True, lapack_driver='gesvd')

        self._singular_values = s

        # don't pass any values in the argument list that call _diagonalize again!!!
        m = VAMPModel._dimension(self._rank0, self._rankt, self.dim,
                                 self._singular_values)

        U = np.dot(L0, A[:, :m])
        V = np.dot(Lt, BT[:m, :].T)

        # scale vectors
        if self.scaling is not None:
            U *= s[np.newaxis,
                   0:m]  # scaled left singular functions induce a kinetic map
            V *= s[
                np.newaxis, 0:
                m]  # scaled right singular functions induce a kinetic map wrt. backward propagator

        self._U = U
        self._V = V
        self._svd_performed = True
Esempio n. 3
0
    def _finish_estimation(self):
        R = spd_inv_split(self._covar.cov, epsilon=self.epsilon, canonical_signs=True)
        # Set the new correlation matrix:
        M = R.shape[1]
        K = np.dot(R.T, np.dot((self._covar.cov_tau), R))
        K = np.vstack((K, np.dot((self._covar.mean_tau - self._covar.mean), R)))
        ex1 = np.zeros((M + 1, 1))
        ex1[M, 0] = 1.0
        self._K = np.hstack((K, ex1))
        self._R = R

        self._estimation_finished = True
        self._estimated = True