Skip to content

Commit

Permalink
Add files via upload
Browse files Browse the repository at this point in the history
  • Loading branch information
F-Bekerman authored Aug 10, 2017
1 parent c79835f commit f00dae1
Showing 1 changed file with 31 additions and 26 deletions.
57 changes: 31 additions & 26 deletions GCN_AE.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,26 +31,30 @@ class VGAE (object):
-------------------
adjacency: The adjacency matrix
norm_adj_mat: The renormalized n_nodes x n_nodes adjacency matrix
feat_max : a n_nodes x n_features matrix - optional
dropout: dropout parameter
"""

def __init__(self,n_hidden,n_latent,n_nodes,learning_rate=0.001):
def __init__(self,n_hidden,n_latent,n_nodes,learning_rate=0.01):
self.n_nodes = n_nodes
self.n_hidden = n_hidden
self.n_latent = n_latent
self.learning_rate = learning_rate


self.shape=[self.n_nodes,self.n_nodes]
self.shape = np.array(self.shape, dtype=np.int64)
self.adjacency = tf.sparse_placeholder(tf.float32,shape=self.shape,name='adjacency')
self.norm_adj_mat = tf.sparse_placeholder(tf.float32,shape=self.shape,name='norm_adj_mat')
#self.keep_prob = tf.placeholder(tf.float32,shape=(),name='dropout')
self.keep_prob = tf.placeholder(tf.float32)


self.W_0_mu = None
self.W_1_mu = None
self.W_2_mu = None

self.W_0_sigma=None
self.W_1_sigma=None
self.W_2_sigma=None

self.mu_np=[]
self.sigma_np=[]
Expand All @@ -62,27 +66,31 @@ def build_VGAE(self):

#Initialize Weights
self.W_0_mu = Initialization.unif_weight_init(shape=[self.n_nodes,self.n_hidden])
self.W_1_mu = Initialization.unif_weight_init(shape=[self.n_hidden,self.n_latent])
self.W_1_mu = Initialization.unif_weight_init(shape=[self.n_hidden,self.n_hidden])
self.W_2_mu = Initialization.unif_weight_init(shape=[self.n_hidden,self.n_latent])

self.W_0_sigma = Initialization.unif_weight_init(shape=[self.n_nodes,self.n_hidden])
self.W_1_sigma = Initialization.unif_weight_init(shape=[self.n_hidden,self.n_latent])
self.W_1_sigma = Initialization.unif_weight_init(shape=[self.n_hidden,self.n_hidden])
self.W_2_sigma = Initialization.unif_weight_init(shape=[self.n_hidden,self.n_latent])


#Compute Graph Convolutional Layers for the mean parameter
hidden_0_mu=tf.nn.relu(tf.sparse_tensor_dense_matmul(self.norm_adj_mat,self.W_0_mu))
self.mu = tf.matmul(tf.sparse_tensor_dense_matmul(self.norm_adj_mat,hidden_0_mu),self.W_1_mu)
hidden_0_mu_=Initialization.gcn_layer_id(self.norm_adj_mat,self.W_0_mu)
hidden_0_mu=tf.nn.dropout(hidden_0_mu_,self.keep_prob)
self.mu = Initialization.gcn_layer(self.norm_adj_mat,hidden_0_mu,self.W_2_mu)

#Compute Graph Convolutional Layers for the variance parameter
hidden_0_sigma=tf.nn.relu(tf.sparse_tensor_dense_matmul(self.norm_adj_mat,self.W_0_sigma))
log_sigma = tf.matmul(tf.sparse_tensor_dense_matmul(self.norm_adj_mat,hidden_0_sigma),self.W_1_sigma)
hidden_0_sigma_=Initialization.gcn_layer_id(self.norm_adj_mat,self.W_0_sigma)
hidden_0_sigma=tf.nn.dropout(hidden_0_sigma_,self.keep_prob)
log_sigma = Initialization.gcn_layer(self.norm_adj_mat,hidden_0_sigma,self.W_2_sigma)
self.sigma=tf.exp(log_sigma)

#Latent Loss Function. It is given by the KL divergence (closed formula)
self.latent_loss = -(0.5 / self.n_nodes) * tf.reduce_mean(tf.reduce_sum(1 + 2 * tf.log(self.sigma)- tf.square(self.mu) - tf.square(self.sigma), 1))

#Reconstruction Loss. We use the weighted cross_entropy to take into account the sparsity of A
dense_adjacency=tf.reshape(tf.sparse_tensor_to_dense(self.adjacency, validate_indices=False), self.shape)
w_1 = (self.n_nodes * self.n_nodes - tf.reduce_sum(dense_adjacency)) / tf.reduce_sum(dense_adjacency)
w_1 = (self.n_nodes * self.n_nodes - tf.reduce_sum(dense_adjacency)) / tf.reduce_sum(dense_adjacency)
w_2 = self.n_nodes * self.n_nodes / (self.n_nodes * self.n_nodes - tf.reduce_sum(dense_adjacency))
self.reconst_loss = w_2* tf.reduce_mean(tf.nn.weighted_cross_entropy_with_logits(targets=dense_adjacency,logits=self.decode(),pos_weight=w_1))

Expand All @@ -98,10 +106,7 @@ def build_VGAE(self):
self.sess = tf.Session()
self.sess.run(init)

#Prediction and Accuracy. The classification treshold to recover the adjacency matrix is chosen arbitrarily.
self.correct_prediction = tf.equal(tf.cast(tf.greater_equal(self.decode(), 1), tf.int8),tf.cast(dense_adjacency, tf.int8))
self.accuracy = tf.reduce_mean(tf.cast(self.correct_prediction, tf.float32))


def encode(self):
'''Generates a latent representation'''
return Initialization.sample_gaussian(self.mu,self.sigma)
Expand All @@ -113,11 +118,11 @@ def decode (self):
return matrix_pred


def train_glob (self,sp_adjacency,norm_adj_mat):
def train_glob (self,sp_adjacency,norm_adj_mat,keep_prob):
'''Performs batch gradient descent'''
feed_dict={self.adjacency: sp_adjacency[0:2],self.norm_adj_mat:norm_adj_mat[0:2]}
_,loss,latent_loss,reconst_loss,accuracy,self.mu_np,self.sigma_np= self.sess.run([self.train_step,self.loss,self.latent_loss,self.reconst_loss,self.accuracy,self.mu,self.sigma],feed_dict=feed_dict)
return loss,latent_loss,reconst_loss,accuracy
feed_dict={self.adjacency: sp_adjacency[0:2],self.norm_adj_mat:norm_adj_mat[0:2],self.keep_prob:keep_prob}
_,loss,latent_loss,reconst_loss,self.mu_np,self.sigma_np= self.sess.run([self.train_step,self.loss,self.latent_loss,self.reconst_loss,self.mu,self.sigma],feed_dict=feed_dict)
return loss,latent_loss,reconst_loss

#The two following methods are similar to encode and decode, except they use the already updated
#mean and variance rather than computing them from the feed dictionnary.
Expand All @@ -135,29 +140,29 @@ def predict(self):

def auc_ap_scores(self,pos_edges,neg_edges):
'''Returns the auc and average precision score on a given test set with positive and negative examples'''
z=self.predict()
pred=self.predict()
s=np.vectorize(Initialization.sigmoid)
z=s(z)
pred=s(pred)
preds=[]
for e in pos_edges:
preds.append(z[e[0],e[1]])
preds.append(pred[e[0],e[1]])
for e in neg_edges:
preds.append(z[e[0],e[1]])
preds.append(pred[e[0],e[1]])
labels=np.hstack([np.ones(len(pos_edges)), np.zeros(len(neg_edges))])
auc_score = roc_auc_score(labels, preds)
ap_score = average_precision_score(labels, preds)
return auc_score, ap_score

def roc_curve_(self,pos_edges,neg_edges):
'''Returns the ROC curve on a given test set with positive and negative examples'''
z=self.predict()
pred=self.predict()
s=np.vectorize(Initialization.sigmoid)
z=s(z)
pred=s(pred)
preds=[]
for e in pos_edges:
preds.append(z[e[0],e[1]])
preds.append(pred[e[0],e[1]])
for e in neg_edges:
preds.append(z[e[0],e[1]])
preds.append(pred[e[0],e[1]])
labels=np.hstack([np.ones(len(pos_edges)), np.zeros(len(neg_edges))])
fpr,tpr,tresholds = roc_curve(labels,preds)
return fpr, tpr,tresholds
Expand Down

0 comments on commit f00dae1

Please sign in to comment.