Пример #1
0
def sorted_eig(mat, thresh=0.0, n=None, sps=True):
    """
    Returns n eigenvalues and vectors sorted
    from largest to smallest eigenvalue
    """

    if sps:
        from scipy.sparse.linalg import eigs as speig

        if n is None:
            k = mat.shape[0] - 1
        else:
            k = n
        val, vec = speig(mat, k=k, tol=thresh)
        val = np.real(val)
        vec = np.real(vec)

        idx = sorted(range(len(val)), key=lambda i: -val[i])

        val = val[idx]
        vec = vec[:, idx]

    else:
        val, vec = np.linalg.eigh(mat)
        val = np.flip(val, axis=0)
        vec = np.flip(vec, axis=1)

    if n is not None and len(val[val < thresh]) < n:
        vec[:, val < thresh] = 0
        val[val < thresh] = 0
    else:
        vec = vec[:, val >= thresh]
        val = val[val >= thresh]

    return val[:n], vec[:, :n]
Пример #2
0
def eig_solver(matrix, n_components=None, tol=1e-12, add_null=False):
    """
    This function returns the eigenpairs corresponding to the `n_components`
    largest eigenvalues.

    :param matrix: Matrix to decompose
    :type matrix: ndarray

    :param n_components: number of eigenpairs to return. If None, full
                         eigendecomposition will be computed / returned
    :type n_components: int, None

    :param tol: value below which to assume an eigenvalue is 0
    :type tol: float

    :param add_null: when the rank of matrix < n_components, whether to add
                     (n_components - rank(matrix)) eigenpairs, defaults to
                     False
    :type add_null: boolean
    """

    if n_components is not None and n_components < matrix.shape[0]:
        v, U = speig(matrix, k=n_components, tol=tol)
    else:
        v, U = np.linalg.eig(matrix)

    U = np.real(U[:, np.argsort(-v)])
    v = np.real(v[np.argsort(-v)])

    if tol is not None:
        U = U[:, v > tol]
        v = v[v > tol]

    if len(v) == 1:
        U = U.reshape(-1, 1)

    if n_components is not None and n_components > len(v):
        if not add_null:

            warnings.warn(f"There are fewer than {n_components} "
                          "significant eigenpair(s). Resulting decomposition"
                          f"will be truncated to {len(v)} eigenpairs.")

        else:

            for i in range(len(v), n_components):
                v = np.array([*v, 0])
                U = np.array([*U.T, np.zeros(U.shape[0])]).T

    return v[:n_components], U[:, :n_components]
Пример #3
0
def pcovr_select(A, n, Y, alpha, k=1, idxs=None, sps=False, **kwargs):
    """
        Selection function which computes the CUR
        indices using the PCovR `Covariance` matrix
    """

    Acopy = A.copy()
    Ycopy = Y.copy()

    if(idxs is None):
        idxs = []  # indexA is initially empty.
    else:
        idxs = list(idxs)

    try:
        for nn in tqdm(range(n)):
            if(len(idxs) <= nn):

                Ct = get_Ct(Acopy, Ycopy, alpha=alpha)

                if(not sps):
                    v_Ct, U_Ct = sorted_eig(Ct, n=k)
                else:
                    v_Ct, U_Ct = speig(Ct, k)
                    U_Ct = U_Ct[:, np.flip(np.argsort(v_Ct))]

                pi = (np.real(U_Ct)[:, :k]**2.0).sum(axis=1)
                pi[idxs] = 0  # eliminate possibility of selecting same column twice
                j = pi.argmax()
                idxs.append(j)

            v = np.linalg.pinv(
                np.matmul(Acopy[:, idxs[:nn+1]].T, Acopy[:, idxs[:nn+1]]))
            v = np.matmul(Acopy[:, idxs[:nn+1]], v)
            v = np.matmul(v, Acopy[:, idxs[:nn+1]].T)

            Ycopy -= np.matmul(v, Ycopy)

            v = Acopy[:, idxs[nn]] / \
                np.sqrt(np.matmul(Acopy[:, idxs[nn]], Acopy[:, idxs[nn]]))


            for i in range(Acopy.shape[1]):
                Acopy[:, i] -= v * np.dot(v, Acopy[:, i])
    except:
        print("INCOMPLETE AT {}/{}".format(len(idxs), n))

    return list(idxs)
Пример #4
0
    def select(self, n):
        """Method for CUR select based upon a product of the input matrices

        Parameters
        ----------
        n : number of selections to make, must be > 0

        Returns
        -------
        idx: list of n selections
        """

        if n <= 0:
            raise ValueError("You must call select(n) with n > 0.")

        if len(self.idx) > n:
            return self.idx[:n]

        for i in self.report_progress(range(len(self.idx), n)):
            if self.iter:
                v, U = speig(self.product, k=self.k, tol=self.tol)
                U = U[:, np.flip(np.argsort(v))]
                pi = (np.real(U)[:, :self.k]**2.0).sum(axis=1)
            pi[self.idx] = 0.0
            self.idx.append(pi.argmax())
            self.pi.append(max(pi))

            self.orthogonalize()
            self.product = self.get_product()

            if np.isnan(self.product).any():
                print(f"The product matrix has rank {i}. " +
                      f"n_select reduced from {n} to {i}.")
                return self.idx

        return self.idx
Пример #5
0
def _eigWrapper(A: spmatrix, k: int):
    # Take magnitude and sort according to largest k eigenvalues
    keigs, vectors = speig(A, k, which="LM", return_eigenvectors=True)
    keigs = keigs.real
    ix = keigs.argsort()[::-1]
    return vectors[:, ix].real, keigs[ix]