def fit( self, adjacency: Union[sparse.csr_matrix, np.ndarray]) -> 'LaplacianEmbedding': """Compute the graph embedding. Parameters ---------- adjacency : Adjacency matrix of the graph (symmetric matrix). Returns ------- self: :class:`LaplacianEmbedding` """ adjacency = check_format(adjacency).asfptype() check_square(adjacency) check_symmetry(adjacency) n = adjacency.shape[0] regularize: bool = not (self.regularization is None or self.regularization == 0.) check_scaling(self.scaling, adjacency, regularize) if regularize: solver: EigSolver = LanczosEig() else: solver = set_solver(self.solver, adjacency) n_components = 1 + check_n_components(self.n_components, n - 2) weights = adjacency.dot(np.ones(n)) regularization = self.regularization if regularization: if self.relative_regularization: regularization = regularization * weights.sum() / n**2 weights += regularization * n laplacian = LaplacianOperator(adjacency, regularization) else: weight_diag = sparse.diags(weights, format='csr') laplacian = weight_diag - adjacency solver.which = 'SM' solver.fit(matrix=laplacian, n_components=n_components) eigenvalues = solver.eigenvalues_[1:] eigenvectors = solver.eigenvectors_[:, 1:] embedding = eigenvectors.copy() if self.scaling: eigenvalues_inv_diag = diag_pinv(eigenvalues**self.scaling) embedding = eigenvalues_inv_diag.dot(embedding.T).T if self.normalized: embedding = normalize(embedding, p=2) self.embedding_ = embedding self.eigenvalues_ = eigenvalues self.eigenvectors_ = eigenvectors self.regularization_ = regularization return self
def fit(self, adjacency: Union[sparse.csr_matrix, np.ndarray]) -> 'GSVD': """Compute the embedding of the graph. Parameters ---------- adjacency : Adjacency or biadjacency matrix of the graph. Returns ------- self: :class:`GSVD` """ adjacency = check_format(adjacency).asfptype() n_row, n_col = adjacency.shape n_components = check_n_components(self.n_components, min(n_row, n_col) - 1) if isinstance(self.solver, str): self.solver = set_svd_solver(self.solver, adjacency) regularization = self.regularization if regularization: if self.relative_regularization: regularization = regularization * np.sum( adjacency.data) / (n_row * n_col) adjacency_reg = RegularizedAdjacency(adjacency, regularization) else: adjacency_reg = adjacency weights_row = adjacency_reg.dot(np.ones(n_col)) weights_col = adjacency_reg.T.dot(np.ones(n_row)) diag_row = diag_pinv(np.power(weights_row, self.factor_row)) diag_col = diag_pinv(np.power(weights_col, self.factor_col)) self.solver.fit( safe_sparse_dot(diag_row, safe_sparse_dot(adjacency_reg, diag_col)), n_components) singular_values = self.solver.singular_values_ index = np.argsort(-singular_values) singular_values = singular_values[index] singular_vectors_left = self.solver.singular_vectors_left_[:, index] singular_vectors_right = self.solver.singular_vectors_right_[:, index] singular_left_diag = sparse.diags( np.power(singular_values, 1 - self.factor_singular)) singular_right_diag = sparse.diags( np.power(singular_values, self.factor_singular)) embedding_row = diag_row.dot(singular_vectors_left) embedding_col = diag_col.dot(singular_vectors_right) embedding_row = singular_left_diag.dot(embedding_row.T).T embedding_col = singular_right_diag.dot(embedding_col.T).T if self.normalized: embedding_row = normalize(embedding_row, p=2) embedding_col = normalize(embedding_col, p=2) self.embedding_row_ = embedding_row self.embedding_col_ = embedding_col self.embedding_ = embedding_row self.singular_values_ = singular_values self.singular_vectors_left_ = singular_vectors_left self.singular_vectors_right_ = singular_vectors_right self.regularization_ = regularization self.weights_col_ = weights_col return self
def fit(self, adjacency: Union[sparse.csr_matrix, np.ndarray]) -> 'Spectral': """Compute the graph embedding. Parameters ---------- adjacency : Adjacency matrix of the graph (symmetric matrix). Returns ------- self: :class:`Spectral` """ adjacency = check_format(adjacency).asfptype() check_square(adjacency) check_symmetry(adjacency) n = adjacency.shape[0] solver = set_solver(self.solver, adjacency) n_components = 1 + check_n_components(self.n_components, n - 2) regularize: bool = not (self.regularization is None or self.regularization == 0.) check_scaling(self.scaling, adjacency, regularize) weights = adjacency.dot(np.ones(n)) regularization = self.regularization if regularization: if self.relative_regularization: regularization = regularization * weights.sum() / n**2 weights += regularization * n # Spectral decomposition of the normalized adjacency matrix weights_inv_sqrt_diag = diag_pinv(np.sqrt(weights)) if regularization: norm_adjacency = NormalizedAdjacencyOperator( adjacency, regularization) else: norm_adjacency = weights_inv_sqrt_diag.dot( adjacency.dot(weights_inv_sqrt_diag)) solver.which = 'LA' solver.fit(matrix=norm_adjacency, n_components=n_components) eigenvalues = solver.eigenvalues_ index = np.argsort(-eigenvalues)[1:] # skip first eigenvalue eigenvalues = eigenvalues[index] eigenvectors = weights_inv_sqrt_diag.dot(solver.eigenvectors_[:, index]) embedding = eigenvectors.copy() if self.scaling: eigenvalues_inv_diag = diag_pinv((1 - eigenvalues)**self.scaling) embedding = eigenvalues_inv_diag.dot(embedding.T).T if self.normalized: embedding = normalize(embedding, p=2) self.embedding_ = embedding self.eigenvalues_ = eigenvalues self.eigenvectors_ = eigenvectors self.regularization_ = regularization return self
def fit(self, input_matrix: Union[sparse.csr_matrix, np.ndarray], force_bipartite: bool = False) -> 'Spectral': """Compute the graph embedding. If the input matrix :math:`B` is not square (e.g., biadjacency matrix of a bipartite graph) or not symmetric (e.g., adjacency matrix of a directed graph), use the adjacency matrix :math:`A = \\begin{bmatrix} 0 & B \\\\ B^T & 0 \\end{bmatrix}` and return the embedding for both rows and columns of the input matrix :math:`B`. Parameters ---------- input_matrix : Adjacency matrix or biadjacency matrix of the graph. force_bipartite : bool (default = ``False``) If ``True``, force the input matrix to be considered as a biadjacency matrix. Returns ------- self: :class:`Spectral` """ # input adjacency, self.bipartite = get_adjacency( input_matrix, allow_directed=False, force_bipartite=force_bipartite) n = adjacency.shape[0] # regularization regularization = self._get_regularization(self.regularization, adjacency) self.regularized = regularization > 0 # laplacian laplacian = Laplacian(adjacency, regularization, self.normalized_laplacian) # spectral decomposition n_components = check_n_components(self.n_components, n - 2) + 1 solver = LanczosEig(which='SM') solver.fit(matrix=laplacian, n_components=n_components) index = np.argsort( solver.eigenvalues_)[1:] # increasing order, skip first eigenvalues = solver.eigenvalues_[index] eigenvectors = solver.eigenvectors_[:, index] # embedding if self.normalized_laplacian: embedding = laplacian.norm_diag.dot(eigenvectors) else: embedding = eigenvectors.copy() # output self.embedding_ = embedding self.eigenvalues_ = eigenvalues self.eigenvectors_ = eigenvectors if self.bipartite: self._split_vars(input_matrix.shape) return self
def fit(self, adjacency: Union[sparse.csr_matrix, np.ndarray]) -> 'Spectral': """Compute the graph embedding. Parameters ---------- adjacency : Adjacency matrix of the graph (symmetric matrix). Returns ------- self: :class:`Spectral` """ adjacency = check_format(adjacency).asfptype() check_square(adjacency) check_symmetry(adjacency) n = adjacency.shape[0] if self.solver == 'auto': solver = auto_solver(adjacency.nnz) if solver == 'lanczos': self.solver: EigSolver = LanczosEig() else: # pragma: no cover self.solver: EigSolver = HalkoEig() n_components = check_n_components(self.n_components, n - 2) n_components += 1 if self.equalize and (self.regularization is None or self.regularization == 0.) and not is_connected(adjacency): raise ValueError( "The option 'equalize' is valid only if the graph is connected or with regularization." "Call 'fit' either with 'equalize' = False or positive 'regularization'." ) weights = adjacency.dot(np.ones(n)) regularization = self.regularization if regularization: if self.relative_regularization: regularization = regularization * weights.sum() / n**2 weights += regularization * n if self.normalized_laplacian: # Finding the largest eigenvalues of the normalized adjacency is easier for the solver than finding the # smallest eigenvalues of the normalized laplacian. weights_inv_sqrt_diag = diag_pinv(np.sqrt(weights)) if regularization: norm_adjacency = NormalizedAdjacencyOperator( adjacency, regularization) else: norm_adjacency = weights_inv_sqrt_diag.dot( adjacency.dot(weights_inv_sqrt_diag)) self.solver.which = 'LA' self.solver.fit(matrix=norm_adjacency, n_components=n_components) eigenvalues = 1 - self.solver.eigenvalues_ # eigenvalues of the Laplacian in increasing order index = np.argsort(eigenvalues)[1:] # skip first eigenvalue eigenvalues = eigenvalues[index] # eigenvectors of the Laplacian, skip first eigenvector eigenvectors = np.array( weights_inv_sqrt_diag.dot(self.solver.eigenvectors_[:, index])) else: if regularization: laplacian = LaplacianOperator(adjacency, regularization) else: weight_diag = sparse.diags(weights, format='csr') laplacian = weight_diag - adjacency self.solver.which = 'SM' self.solver.fit(matrix=laplacian, n_components=n_components) eigenvalues = self.solver.eigenvalues_[1:] eigenvectors = self.solver.eigenvectors_[:, 1:] embedding = eigenvectors.copy() if self.equalize: eigenvalues_sqrt_inv_diag = diag_pinv(np.sqrt(eigenvalues)) embedding = eigenvalues_sqrt_inv_diag.dot(embedding.T).T if self.barycenter: eigenvalues_diag = sparse.diags(eigenvalues) subtract = eigenvalues_diag.dot(embedding.T).T if not self.normalized_laplacian: weights_inv_diag = diag_pinv(weights) subtract = weights_inv_diag.dot(subtract) embedding -= subtract if self.normalized: embedding = normalize(embedding, p=2) self.embedding_ = embedding self.eigenvalues_ = eigenvalues self.eigenvectors_ = eigenvectors self.regularization_ = regularization return self