Yaning1001's picture
Add files using upload-large-folder tool
92b9080 verified
Raw
History Blame Contribute Delete
3.73 kB
from torch.nn.modules.module import Module
import numpy as np
import torch
import scipy.sparse as sp
import os.path as osp
class BaseAttack(Module):
"""Abstract base class for target attack classes.
Parameters
----------
model :
model to attack
nnodes : int
number of nodes in the input graph
attack_structure : bool
whether to attack graph structure
attack_features : bool
whether to attack node features
device: str
'cpu' or 'cuda'
"""
def __init__(self, model, nnodes, attack_structure=True, attack_features=False, device='cpu'):
super(BaseAttack, self).__init__()
self.surrogate = model
self.nnodes = nnodes
self.attack_structure = attack_structure
self.attack_features = attack_features
self.device = device
if model is not None:
self.nclass = model.nclass
self.nfeat = model.nfeat
self.hidden_sizes = model.hidden_sizes
self.modified_adj = None
self.modified_features = None
def attack(self, ori_adj, n_perturbations, **kwargs):
"""Generate perturbations on the input graph.
Parameters
----------
ori_adj : scipy.sparse.csr_matrix
Original (unperturbed) adjacency matrix.
n_perturbations : int
Number of perturbations on the input graph. Perturbations could
be edge removals/additions or feature removals/additions.
Returns
-------
None.
"""
pass
def check_adj(self, adj):
"""Check if the modified adjacency is symmetric and unweighted.
"""
if type(adj) is torch.Tensor:
adj = adj.cpu().numpy()
assert np.abs(adj - adj.T).sum() == 0, "Input graph is not symmetric"
if sp.issparse(adj):
assert adj.tocsr().max() == 1, "Max value should be 1!"
assert adj.tocsr().min() == 0, "Min value should be 0!"
else:
assert adj.max() == 1, "Max value should be 1!"
assert adj.min() == 0, "Min value should be 0!"
def save_adj(self, root=r'/tmp/', name='mod_adj'):
"""Save attacked adjacency matrix.
Parameters
----------
root :
root directory where the variable should be saved
name : str
saved file name
Returns
-------
None.
"""
assert self.modified_adj is not None, \
'modified_adj is None! Please perturb the graph first.'
name = name + '.npz'
modified_adj = self.modified_adj
if type(modified_adj) is torch.Tensor:
modified_adj = utils.to_scipy(modified_adj)
if sp.issparse(modified_adj):
modified_adj = modified_adj.tocsr()
sp.save_npz(osp.join(root, name), modified_adj)
def save_features(self, root=r'/tmp/', name='mod_features'):
"""Save attacked node feature matrix.
Parameters
----------
root :
root directory where the variable should be saved
name : str
saved file name
Returns
-------
None.
"""
assert self.modified_features is not None, \
'modified_features is None! Please perturb the graph first.'
name = name + '.npz'
modified_features = self.modified_features
if type(modified_features) is torch.Tensor:
modified_features = utils.to_scipy(modified_features)
if sp.issparse(modified_features):
modified_features = modified_features.tocsr()
sp.save_npz(osp.join(root, name), modified_features)