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
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
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