|
|
import seaborn as sns; sns.set() |
|
|
import matplotlib.pyplot as plt |
|
|
from tqdm import tqdm |
|
|
import os |
|
|
import numpy as np |
|
|
import scipy.sparse as sp |
|
|
|
|
|
def degree_dist(clean_adj, perturbed_adj, savename='degree_dist.pdf'): |
|
|
"""Plot degree distributnio on clean and perturbed graphs. |
|
|
|
|
|
Parameters |
|
|
---------- |
|
|
clean_adj: sp.csr_matrix |
|
|
adjancecy matrix of the clean graph |
|
|
perturbed_adj: sp.csr_matrix |
|
|
adjancecy matrix of the perturbed graph |
|
|
savename: str |
|
|
filename to be saved |
|
|
|
|
|
Returns |
|
|
------- |
|
|
None |
|
|
|
|
|
""" |
|
|
clean_degree = clean_adj.sum(1) |
|
|
perturbed_degree = perturbed_adj.sum(1) |
|
|
fig, ax1 = plt.subplots() |
|
|
sns.distplot(clean_degree, label='Clean Graph', norm_hist=False, ax=ax1) |
|
|
sns.distplot(perturbed_degree, label='Perturbed Graph', norm_hist=False, ax=ax1) |
|
|
ax1.grid(False) |
|
|
plt.legend(prop={'size':18}) |
|
|
plt.ylabel('Density Distribution', fontsize=18) |
|
|
plt.xlabel('Node degree', fontsize=18) |
|
|
plt.xticks(fontsize=14) |
|
|
plt.yticks(fontsize=14) |
|
|
|
|
|
if not os.path.exists('figures/'): |
|
|
os.mkdir('figures') |
|
|
plt.savefig('figures/%s' % savename, bbox_inches='tight') |
|
|
plt.show() |
|
|
|
|
|
def feature_diff(clean_adj, perturbed_adj, features, savename='feature_diff.pdf'): |
|
|
"""Plot feature difference on clean and perturbed graphs. |
|
|
|
|
|
Parameters |
|
|
---------- |
|
|
clean_adj: sp.csr_matrix |
|
|
adjancecy matrix of the clean graph |
|
|
perturbed_adj: sp.csr_matrix |
|
|
adjancecy matrix of the perturbed graph |
|
|
features: sp.csr_matrix or np.array |
|
|
node features |
|
|
savename: str |
|
|
filename to be saved |
|
|
|
|
|
Returns |
|
|
------- |
|
|
None |
|
|
""" |
|
|
|
|
|
fig, ax1 = plt.subplots() |
|
|
sns.distplot(_get_diff(clean_adj, features), label='Normal Edges', norm_hist=True, ax=ax1) |
|
|
delta_adj = perturbed_adj - clean_adj |
|
|
delta_adj[delta_adj < 0] = 0 |
|
|
sns.distplot(_get_diff(delta_adj, features), label='Adversarial Edges', norm_hist=True, ax=ax1) |
|
|
ax1.grid(False) |
|
|
plt.legend(prop={'size':18}) |
|
|
plt.ylabel('Density Distribution', fontsize=18) |
|
|
plt.xlabel('Feature Difference Between Connected Nodes', fontsize=18) |
|
|
plt.xticks(fontsize=14) |
|
|
plt.yticks(fontsize=14) |
|
|
if not os.path.exists('figures/'): |
|
|
os.mkdir('figures') |
|
|
plt.savefig('figures/%s' % savename, bbox_inches='tight') |
|
|
plt.show() |
|
|
|
|
|
|
|
|
def _get_diff(adj, features): |
|
|
isSparse = sp.issparse(features) |
|
|
edges = np.array(adj.nonzero()).T |
|
|
row_degree = adj.sum(0).tolist()[0] |
|
|
diff = [] |
|
|
for edge in tqdm(edges): |
|
|
n1 = edge[0] |
|
|
n2 = edge[1] |
|
|
if n1 > n2: |
|
|
continue |
|
|
d = np.sum((features[n1]/np.sqrt(row_degree[n1]) - features[n2]/np.sqrt(row_degree[n2])).power(2)) |
|
|
diff.append(d) |
|
|
return diff |
|
|
|
|
|
|