Source code for gemben.embedding.hope

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import matplotlib.pyplot as plt
import networkx as nx
import numpy as np
import scipy.io as sio
import scipy.sparse as sp
import scipy.sparse.linalg as lg
from time import time

from .static_graph_embedding import StaticGraphEmbedding
from gemben.utils import graph_util, plot_util
from gemben.evaluation import visualize_embedding as viz


[docs]class HOPE(StaticGraphEmbedding): """`Higher Order Proximity Preserving`_. Higher Order Proximity factorizes the higher order similarity matrix between nodes using generalized singular value decomposition. Args: hyper_dict (object): Hyper parameters. kwargs (dict): keyword arguments, form updating the parameters Examples: >>> from gemben.embedding.hope import HOPE >>> edge_f = 'data/karate.edgelist' >>> G = graph_util.loadGraphFromEdgeListTxt(edge_f, directed=False) >>> G = G.to_directed() >>> res_pre = 'results/testKarate' >>> graph_util.print_graph_stats(G) >>> t1 = time() >>> embedding = HOPE(4, 0.01) >>> embedding.learn_embedding(graph=G, edge_f=None, is_weighted=True, no_python=True) >>> print('HOPE:Training time: %f' % (time() - t1)) >>> viz.plot_embedding2D(embedding.get_embedding()[:, :2], di_graph=G, node_colors=None) >>> plt.show() .. _Higher Order Proximity Preserving: https://www.kdd.org/kdd2016/papers/files/rfp0191-wangAemb.pdf """ def __init__(self, *hyper_dict, **kwargs): ''' Initialize the HOPE class Args: d: dimension of the embedding beta: higher order coefficient ''' hyper_params = { 'method_name': 'hope_gsvd' } hyper_params.update(kwargs) self._sim_fn = "" for key in hyper_params.keys(): self.__setattr__('_%s' % key, hyper_params[key]) for dictionary in hyper_dict: for key in dictionary: self.__setattr__('_%s' % key, dictionary[key])
[docs] def get_method_name(self): return self._method_name
[docs] def get_method_summary(self): return '%s_%d' % (self._method_name, self._d)
[docs] def learn_embedding(self, graph=None, edge_f=None, is_weighted=False, no_python=False): if not graph and not edge_f: raise Exception('graph/edge_f needed') if not graph: graph = graph_util.loadGraphFromEdgeListTxt(edge_f) t1 = time() # A = nx.to_scipy_sparse_matrix(graph) # I = sp.eye(graph.number_of_nodes()) # M_g = I - self._beta*A # M_l = self._beta*A A = nx.to_numpy_matrix(graph) if self._sim_fn == "katz": M_g = np.eye(graph.number_of_nodes()) - self._beta * A M_l = self._beta * A elif self._sim_fn == "pagerank": ## np.matrix can't A = np.array(A) ## in case the sum is 0 row_sums = A.sum(axis=1) + 1e-8 P = A / row_sums[:, np.newaxis] M_g = np.eye(graph.number_of_nodes()) - self._beta * P M_l = (1 - self._beta) * np.eye(graph.number_of_nodes()) elif self._sim_fn == "cn": M_g = np.eye(graph.number_of_nodes()) M_l = np.dot(A, A) elif self._sim_fn == "aa": D = A.sum(axis=1) + A.sum(axis=0) D = np.diag(np.reciprocal(D.astype('float'))) M_g = np.eye(graph.number_of_nodes()) M_l = np.dot(np.dot(A, D), A) else: M_g = np.eye(graph.number_of_nodes()) - self._beta * A M_l = self._beta * A try: S = np.dot(np.linalg.inv(M_g), M_l) u, s, vt = lg.svds(S, k=self._d // 2) X1 = np.dot(u, np.diag(np.sqrt(s))) X2 = np.dot(vt.T, np.diag(np.sqrt(s))) t2 = time() self._X = np.concatenate((X1, X2), axis=1) p_d_p_t = np.dot(u, np.dot(np.diag(s), vt)) eig_err = np.linalg.norm(p_d_p_t - S) print('SVD error (low rank): %f' % eig_err) return self._X, (t2 - t1) except: print ('Singularity Matrix or SVD did not converge. Assigning random emebdding') X1 = np.random.randn(A.shape[0], self._d // 2) X2 = np.random.randn(A.shape[0], self._d // 2) t2 = time() self._X = np.concatenate((X1, X2), axis=1) return self._X, (t2 - t1)
[docs] def get_embedding(self): return self._X
[docs] def get_edge_weight(self, i, j): return np.dot(self._X[i, :self._d // 2], self._X[j, self._d // 2:])
[docs] def get_reconstructed_adj(self, X=None, node_l=None): if X is not None: node_num = X.shape[0] self._X = X else: node_num = self._node_num adj_mtx_r = np.zeros((node_num, node_num)) for v_i in range(node_num): for v_j in range(node_num): if v_i == v_j: continue adj_mtx_r[v_i, v_j] = self.get_edge_weight(v_i, v_j) return adj_mtx_r
if __name__ == '__main__': # load Zachary's Karate graph edge_f = 'data/karate.edgelist' G = graph_util.loadGraphFromEdgeListTxt(edge_f, directed=False) G = G.to_directed() res_pre = 'results/testKarate' graph_util.print_graph_stats(G) t1 = time() embedding = HOPE(4, 0.01) embedding.learn_embedding(graph=G, edge_f=None, is_weighted=True, no_python=True) print('HOPE:\n\tTraining time: %f' % (time() - t1)) viz.plot_embedding2D(embedding.get_embedding()[:, :2], di_graph=G, node_colors=None) plt.show()