Code Monkey home page Code Monkey logo

deeprobust's Introduction

logo


GitHub last commit GitHub issues GitHub Contributing Tweet

Documentation | Paper | Samples

[AAAI 2021] DeepRobust is a PyTorch adversarial library for attack and defense methods on images and graphs.

  • If you are new to DeepRobust, we highly suggest you read the documentation page or the following content in this README to learn how to use it.
  • If you have any questions or suggestions regarding this library, feel free to create an issue here. We will reply as soon as possible :)

List of including algorithms can be found in [Image Package] and [Graph Package].

Environment & Installation

Usage

Acknowledgement

For more details about attacks and defenses, you can read the following papers.

If our work could help your research, please cite: DeepRobust: A PyTorch Library for Adversarial Attacks and Defenses

@article{li2020deeprobust,
  title={Deeprobust: A pytorch library for adversarial attacks and defenses},
  author={Li, Yaxin and Jin, Wei and Xu, Han and Tang, Jiliang},
  journal={arXiv preprint arXiv:2005.06149},
  year={2020}
}

Changelog

  • [11/2023] Try git clone https://github.com/DSE-MSU/DeepRobust.git; cd DeepRobust; python setup_empty.py install to directly install DeepRobust without installing dependency packages.
  • [11/2023] DeepRobust 0.2.9 Released. Please try pip install deeprobust==0.2.9. We have fixed the OOM issue of metattack on new pytorch versions.
  • [06/2023] We have added a backdoor attack UGBA, WWW'23 to graph package. We can now use UGBA to conduct unnoticeable backdoor attack on large-scale graphs such as ogb-arxiv (see example in test_ugba.py)!
  • [02/2023] DeepRobust 0.2.8 Released. Please try pip install deeprobust==0.2.8! We have added a scalable attack PRBCD, NeurIPS'21 to graph package. We can now use PRBCD to attack large-scale graphs such as ogb-arxiv (see example in test_prbcd.py)!
  • [02/2023] Add a robust model AirGNN, NeurIPS'21 to graph package. Try python examples/graph/test_airgnn.py! See details in test_airgnn.py
  • [11/2022] DeepRobust 0.2.6 Released. Please try pip install deeprobust==0.2.6! We have more updates coming. Please stay tuned!
  • [11/2021] A subpackage that includes popular black box attacks in image domain is released. Find it here. Link
  • [11/2021] DeepRobust 0.2.4 Released. Please try pip install deeprobust==0.2.4!
  • [10/2021] add scalable attack and MedianGCN. Thank Jintang for his contribution!
  • [06/2021] [Image Package] Add preprocessing method: APE-GAN.
  • [05/2021] DeepRobust is published at AAAI 2021. Check here!
  • [05/2021] DeepRobust 0.2.2 Released. Please try pip install deeprobust==0.2.2!
  • [04/2021] [Image Package] Add support for ImageNet. See details in test_ImageNet.py
  • [04/2021] [Graph Package] Add support for OGB datasets. See more details in the tutorial page.
  • [03/2021] [Graph Package] Added node embedding attack and victim models! See this tutorial page.
  • [02/2021] [Graph Package] DeepRobust now provides tools for converting the datasets between Pytorch Geometric and DeepRobust. See more details in the tutorial page! DeepRobust now also support GAT, Chebnet and SGC based on pyg; see details in test_gat.py, test_chebnet.py and test_sgc.py
  • [12/2020] DeepRobust now can be installed via pip! Try pip install deeprobust!
  • [12/2020] [Graph Package] Add four more datasets and one defense algorithm. More details can be found here. More datasets and algorithms will be added later. Stay tuned :)
  • [07/2020] Add documentation page!
  • [06/2020] Add docstring to both image and graph package

Basic Environment

  • python >= 3.6 (python 3.5 should also work)
  • pytorch >= 1.2.0

see setup.py or requirements.txt for more information.

Installation

Install from pip

pip install deeprobust 

Install from source

git clone https://github.com/DSE-MSU/DeepRobust.git
cd DeepRobust
python setup.py install

If you find the dependencies are hard to install, please try the following: python setup_empty.py install (only install deeprobust without installing other packages)

Test Examples

python examples/image/test_PGD.py
python examples/image/test_pgdtraining.py
python examples/graph/test_gcn_jaccard.py --dataset cora
python examples/graph/test_mettack.py --dataset cora --ptb_rate 0.05

Usage

Image Attack and Defense

  1. Train model

    Example: Train a simple CNN model on MNIST dataset for 20 epoch on gpu.

    import deeprobust.image.netmodels.train_model as trainmodel
    trainmodel.train('CNN', 'MNIST', 'cuda', 20)

    Model would be saved in deeprobust/trained_models/.

  2. Instantiated attack methods and defense methods.

    Example: Generate adversary example with PGD attack.

    from deeprobust.image.attack.pgd import PGD
    from deeprobust.image.config import attack_params
    from deeprobust.image.utils import download_model
    import torch
    import deeprobust.image.netmodels.resnet as resnet
    from torchvision import transforms,datasets
    
    URL = "https://github.com/I-am-Bot/deeprobust_model/raw/master/CIFAR10_ResNet18_epoch_20.pt"
    download_model(URL, "$MODEL_PATH$")
    
    model = resnet.ResNet18().to('cuda')
    model.load_state_dict(torch.load("$MODEL_PATH$"))
    model.eval()
    
    transform_val = transforms.Compose([transforms.ToTensor()])
    test_loader  = torch.utils.data.DataLoader(
                    datasets.CIFAR10('deeprobust/image/data', train = False, download=True,
                    transform = transform_val),
                    batch_size = 10, shuffle=True)
    
    x, y = next(iter(test_loader))
    x = x.to('cuda').float()
    
    adversary = PGD(model, 'cuda')
    Adv_img = adversary.generate(x, y, **attack_params['PGD_CIFAR10'])

    Example: Train defense model.

    from deeprobust.image.defense.pgdtraining import PGDtraining
    from deeprobust.image.config import defense_params
    from deeprobust.image.netmodels.CNN import Net
    import torch
    from torchvision import datasets, transforms 
    
    model = Net()
    train_loader = torch.utils.data.DataLoader(
                    datasets.MNIST('deeprobust/image/defense/data', train=True, download=True,
                                    transform=transforms.Compose([transforms.ToTensor()])),
                                    batch_size=100,shuffle=True)
    
    test_loader = torch.utils.data.DataLoader(
                  datasets.MNIST('deeprobust/image/defense/data', train=False,
                                transform=transforms.Compose([transforms.ToTensor()])),
                                batch_size=1000,shuffle=True)
    
    defense = PGDtraining(model, 'cuda')
    defense.generate(train_loader, test_loader, **defense_params["PGDtraining_MNIST"])

    More example code can be found in deeprobust/examples.

  3. Use our evulation program to test attack algorithm against defense.

    Example:

    cd DeepRobust
    python examples/image/test_train.py
    python deeprobust/image/evaluation_attack.py
    

Graph Attack and Defense

Attacking Graph Neural Networks

  1. Load dataset

    import torch
    import numpy as np
    from deeprobust.graph.data import Dataset
    from deeprobust.graph.defense import GCN
    from deeprobust.graph.global_attack import Metattack
    
    data = Dataset(root='/tmp/', name='cora', setting='nettack')
    adj, features, labels = data.adj, data.features, data.labels
    idx_train, idx_val, idx_test = data.idx_train, data.idx_val, data.idx_test
    idx_unlabeled = np.union1d(idx_val, idx_test)
  2. Set up surrogate model

    device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
    surrogate = GCN(nfeat=features.shape[1], nclass=labels.max().item()+1, nhid=16,
                    with_relu=False, device=device)
    surrogate = surrogate.to(device)
    surrogate.fit(features, adj, labels, idx_train)
  3. Set up attack model and generate perturbations

    model = Metattack(model=surrogate, nnodes=adj.shape[0], feature_shape=features.shape, device=device)
    model = model.to(device)
    perturbations = int(0.05 * (adj.sum() // 2))
    model.attack(features, adj, labels, idx_train, idx_unlabeled, perturbations, ll_constraint=False)
    modified_adj = model.modified_adj

For more details please refer to mettack.py or run python examples/graph/test_mettack.py --dataset cora --ptb_rate 0.05

Defending Against Graph Attacks

  1. Load dataset
    import torch
    from deeprobust.graph.data import Dataset, PtbDataset
    from deeprobust.graph.defense import GCN, GCNJaccard
    import numpy as np
    np.random.seed(15)
    
    # load clean graph
    data = Dataset(root='/tmp/', name='cora', setting='nettack')
    adj, features, labels = data.adj, data.features, data.labels
    idx_train, idx_val, idx_test = data.idx_train, data.idx_val, data.idx_test
    
    # load pre-attacked graph by mettack
    perturbed_data = PtbDataset(root='/tmp/', name='cora')
    perturbed_adj = perturbed_data.adj
  2. Test
    # Set up defense model and test performance
    device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
    model = GCNJaccard(nfeat=features.shape[1], nclass=labels.max()+1, nhid=16, device=device)
    model = model.to(device)
    model.fit(features, perturbed_adj, labels, idx_train)
    model.eval()
    output = model.test(idx_test)
    
    # Test on GCN
    model = GCN(nfeat=features.shape[1], nclass=labels.max()+1, nhid=16, device=device)
    model = model.to(device)
    model.fit(features, perturbed_adj, labels, idx_train)
    model.eval()
    output = model.test(idx_test)

For more details please refer to test_gcn_jaccard.py or run python examples/graph/test_gcn_jaccard.py --dataset cora

Sample Results

adversary examples generated by fgsm:

Left:original, classified as 6; Right:adversary, classified as 4.

Serveral trained models can be found here: https://drive.google.com/open?id=1uGLiuCyd8zCAQ8tPz9DDUQH6zm-C4tEL

Acknowledgement

Some of the algorithms are referred to paper authors' implementations. References can be found at the top of each file.

Implementation of network structure are referred to weiaicunzai's github. Original code can be found here: pytorch-cifar100

Thanks to their outstanding works!

deeprobust's People

Contributors

aravind-gk avatar chandlerbang avatar dse-msu avatar edisonleeeee avatar eltociear avatar enderdzz avatar finamintoastcrunch avatar hannxu123 avatar helloworldlty avatar henrykenlay avatar i-am-bot avatar kaiguo20 avatar marblet avatar ocrinz avatar pmixer avatar rand0musername avatar sqrhussain avatar ventr1c avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

deeprobust's Issues

To normalize or not to normalize?

Hi there, I'm reading test_PGD.py and notice that you don't normalize the input images. On the other hand, attack_params['PGD_CIFAR10'] contains {'clip_max': 2.514087988136431, 'clip_min': -2.4290657439446366, which look very much like the min and max values of normalized intensities. So, is it supposed to be normalized or not?

The experimental results of the two papers differ significantly

Hi Jin!

I'm confused that why the experimental results of the two papers(DeepRobust and Pro-GNN) are largely different.
For instance, Jaccard shows really good robustness in DeepRobust. Even the acc does not decrease with increasing perturbation rate in citeseer. On contrary, it drops rappidly in another paper(Pro-GNN or SimP-GCN). Other robust models also show varying degrees of variation.

Topology Attack also considers main diagonal (twice)

Hi,

I fear there is an issue with the topology attack. From what I understand you initialize as many elements in self.adj_changes as the upper half of the adjacency matrix without the main diagonal. I agree that this is correct. However, in get_modified_adj(...) you get the indices including the main diagonal but exclude the node with the highest index. I believe tril_indices = torch.tril_indices(row=self.n, col=self.n, offset=-1) should fix it.

Some error in 'base_attack.py'

Hi. There seems to be some error in file base_attack.py. I didn't find the definition of x/y.

64 elif type(x).__name__ == 'ndarray':
74 label = torch.tensor(y)

Bro, you'd better check it.

Support Running GNNs on Specific GPU

Hi DeepRobust Team,

I've encountered a problem when testing GNNs on devices other than cuda:0. To reproduce, simply modifying line 18 in test_gcn.py to

device = torch.device("cuda:2" if torch.cuda.is_available() else "cpu")

Then the error message is prompted as follows:

RuntimeError: Expected all tensors to be on the same device, but found at least two devices

I found it's caused by normalize_adj_tensor and degree_normalize_adj_tensor, where the device is set to be cuda:0 by default wherever adj is. Though many people run experiments on cuda:0 by default, it could be even better to support running GNNs in DeepRobust on other devices specified via the device variable.

Could you add this feature in the next update? Thank you. 😀

About the use of large matrix causes Memory Error

不好意思打搅了, 我在使用较大的图, 调用deeprobust.graph.utils.preprocess时, 出现了内存超限的错误, 在调用时将sparse参数置为True会影响后面的训练吗, 谢谢!

Excuse me, I used a larger graph and called the function deeprobust.graph.utils.preprocess, which caused https://github.com/DSE-MSU/DeepRobust/blob/master/deeprobust/graph/utils.py#L32 to throw the Memory Error.

If I set sparse to True: adj, features, labels = preprocess(adj, features, labels, sparse=True), does it affect the training behind? Thank you!

image

Issue with test_nettack.py

In line 149, accuracy is calculated as acc_test = accuracy(output[[target_node]], labels[target_node]) but labels[target_node] is an integer here. The accuracy() function in utils.py expects a list in labels argument. If an integer is passed instead, say n - labels = torch.LongTensor(labels) will create a list of size n instead of a list with single item. Therefore in many instances acc_test holds fractional values instead of the expected 0 or 1.
Either accuracy should be calculated as acc_test = accuracy(output[[target_node]], [labels[target_node]]) or accuracy() function be modified to accept integer values in label parameter.

Quesiton abort computer consine similarity.

def _cosine_similarity(self, a, b):
inner_product = (features[n1] * features[n2]).sum()
C = inner_product / np.sqrt(np.square(a).sum() + np.square(b).sum())

Q1:In L288, Features[n1] and features[n2] may be a and b?
Q2:Given two vectors of attributes, A and B, the cosine similarity, cos(θ), is represented using a dot product and magnitude as

So, in L289 np.sqrt(np.square(a).sum() + np.square(b).sum()) Why does it use addition instead of multiplication?

中文介绍文章

参加KDD的图数据攻防比赛开始熟悉这个包,里面有很多不错的代码。我写了篇中文介绍的文章。
https://zhuanlan.zhihu.com/p/148282580

另外pytorch 不支持对稀疏矩阵的求导。可以通过矩阵分解的方式实现稀疏矩阵下增加节点的梯度计算。如果这里面直接支持就好了。

GCNSVD predict()

As GCNSVD model will process the input adjacency matrix using truncatedSVD(), we cannot directly use the predict() function inherited from GCN.

This is my personal implementation,

 def predict(self, features=None, adj=None):
        self.eval()
        if features is None and adj is None:
            return self.forward(self.features, self.adj_norm)
        else:
            modified_adj = self.truncatedSVD(adj, k=self.k)
            features, modified_adj, labels = utils.to_tensor(features, modified_adj, self.labels, device=self.device)
            if utils.is_sparse_tensor(modified_adj):
                modified_adj = utils.normalize_adj_tensor(modified_adj, sparse=True)
            else:
                modified_adj = utils.normalize_adj_tensor(modified_adj)
            
            return self.forward(features, modified_adj)

Questions about RL-S2V

Hi, I changed the number of modification on the graph to get a better attack effect with dataset Cora, but it didn't work. How could I re-emerge the results which is when we increase Number of Perturbations Per Node the acc of attacked Nodes will get reduce in the paper
And How to attack my own dataset by RL-S2V?
Sorry, poor English.

Failed to load target_nodes.

self.adj = self.load_data()
self.target_nodes = None
def load_data(self):
if not osp.exists(self.data_filename):
self.download_npz()
print('Loading {} dataset perturbed by {} {}...'.format(self.name, self.ptb_rate, self.attack_method))
if self.attack_method == 'meta':
warnings.warn("the pre-attacked graph is perturbed, using the data splits under seed 15 (default seed), so if you are going to verify the attacking performance, you should use the same data splits.")
adj = sp.load_npz(self.data_filename)
if self.attack_method == 'nettack':
# assert True, "Will update pre-attacked data by nettack soon"
warnings.warn("the pre-attacked graph is perturbed, using the data splits under seed 15 (default seed), so if you are going to verify the attacking performance, you should use the same seed (15).")
adj = sp.load_npz(self.data_filename)
self.target_nodes = self.get_target_nodes()
return adj

Should L127 be before L126? Otherwise, self.target_nodes will always be None.

A question about r_gcn

When trying to train a r_gcn model with the following code:

from deeprobust.graph.data import Dataset from deeprobust.graph.defense import RGCN data = Dataset(root='/tmp/', name='cora') adj, features, labels = data.adj, data.features, data.labels idx_train, idx_val, idx_test = data.idx_train, data.idx_val, data.idx_test rgcn = RGCN(nnodes=adj.shape[0],nfeat=features.shape[1], nhid=16, nclass=labels.max().item() + 1, dropout=0.5, device='cuda') rgcn.fit(features, adj, labels, idx_train) # train without earlystopping rgcn.fit(features, adj, labels, idx_train, idx_val, patience=30) # train with earlystopping rgcn.test(idx_test)

I encountered the following error:

RuntimeError: Expected all tensors to be on the same device, but found at least two devices, cuda:0 and cpu! (when checking arugment for argument mat2 in method wrapper_mm)

I also tried the codes in the official document by changing the parameter "device='cpu'" into "device='cuda'", it also raised the same error.

ModuleNotFoundError: No module named 'node2vec'

ModuleNotFoundError                       Traceback (most recent call last)
<ipython-input-1-ab061214f9c6> in <module>
      7 import torch.optim as optim
      8 from deeprobust.graph.utils import accuracy
----> 9 from deeprobust.graph.defense.pgd import PGD, prox_operators
     10 import warnings
     11 

~/DeepRobust/deeprobust/graph/defense/__init__.py in <module>
      4 from .prognn import ProGNN
      5 from .simpgcn import SimPGCN
----> 6 from .node_embedding import Node2Vec, DeepWalk
      7 import warnings
      8 try:

~/DeepRobust/deeprobust/graph/defense/node_embedding.py in <module>
     16 from sklearn.preprocessing import normalize
     17 from sklearn.metrics import f1_score, roc_auc_score, average_precision_score, accuracy_score
---> 18 from node2vec import Node2Vec as N2V
     19 
     20 class BaseEmbedding:

ModuleNotFoundError: No module named 'node2vec'

Hi, is there a missing file node2vec?

Metattack, the forward of GCN is incorrect if `with_relu=True`

for j in range(self.train_iters):
hidden = features
for ix, w in enumerate(self.weights):
b = self.biases[ix] if self.with_bias else 0
if self.sparse_features:
hidden = adj_norm @ torch.spmm(hidden, w) + b
else:
hidden = adj_norm @ hidden @ w + b
if self.with_relu:
hidden = F.relu(hidden)
output = F.log_softmax(hidden, dim=1)

hidden = features
for ix, w in enumerate(self.weights):
b = self.biases[ix] if self.with_bias else 0
if self.sparse_features:
hidden = adj_norm @ torch.spmm(hidden, w) + b
else:
hidden = adj_norm @ hidden @ w + b
if self.with_relu:
hidden = F.relu(hidden)
output = F.log_softmax(hidden, dim=1)

It seems that the output of the last layer uses both ReLU+Softmax activation functions if with_relu=True.

Cannot load cora-ml with 15% and 20% perturbation rate

Hi,

I found we cannot load cora-ml datasets with 15% and 20% perturbation rate when I am trying to run test_sgc.py. The problem is that we cannot find cora_ml_meta_adj_0.15.npz and cora_ml_meta_adj_0.2.np in the github repo Pro-GNN. As you are from the same research group, I just open an issue here. Hope these two perturbed graphs can be uploaded there. Then the problem will be resolved and it will make the example more complete. Thanks in advance.

I am having trouble with an error that prevents me from accessing the dataset.

Hello.

I downloaded all the code from this site to my desktop and ran the following

examples/graph/test_mettack.py --dataset cora --ptb_rate 0.05

However, I got the following error

Traceback (most recent call last):
File "test_mettack.py", line 39, in <module
data = Dataset(root='/tmp/', name=args.dataset, setting='nettack')
File "C:\ Users\uno\anaconda3\envs\GAN_torch\lib\site_packages\deeprobust\graph\data\dataset.py", line 70, in init
self.adj, self.features, self.labels = self.load_data()
File "C:\ Users\uno\anaconda3\envs\GAN_torch\lib\site_packages\deeprobust\graph\data\dataset.py", line 113, in load_data
self.download_npz()
File "C:\ Users\uno\anaconda3\envs\GAN_torch\lib\site_packages\deeprobust\graph\data\dataset.py", line 134, in download_npz
raise Exception('''Download failed! Make sure you have a stable Internet connection and enter the right name'')
Exception: Download failed! Make sure you have a stable Internet connection and enter the right name

I can't seem to access the dataset, how can I improve this?
Please let me know if there is a way to download the dataset to my desktop.

Thank you.

Question on the symmetric constraint in ProGNN

Hi, Thanks for sharing the DeepRobust code.
I've been studying the code of ProGNN. There is a operation for the symmetric constraint:
image
I noticed that in EstimateAdj in ProGNN.py, the process is realized by:
if self.symmetric: adj = (self.estimated_adj + self.estimated_adj.t())

It seems that 2 is missing. Is this a mistake or a design?

Refactor attack method for DICE, IGAttack, Random, PGDAttack, MinMax

The classes DICE, IGAttack, Random, PGDAttack, MinMax all subclass BaseAttack however the BaseAttack.attack method doesn't specify any arguments. I plan to refactor in the following ways:

  • Move arguments common to multiple attacks (such as labels) into the BaseAttack class.
  • Make some variable names more consistent (i.e., use just adj or just ori_adj).
  • Add documentation to the BaseAttack class describing the variables and accepted types (this can be rewritten once you decide on documentation conventions)
  • Add **kwargs to all subclasses (this would allow one to use different classes attack method in the same way)

I think organising the classes in mettack.py can be a separate issue because things seem slight differently there (the attack classes subclass the intermediate class BaseMeta).

Before I get started I would be interested in your answers to the following:

  • Do you prefer the convention ori_adj and ori_features or adj and features?
  • Do you prefer perturbations or n_perturbations?

As an aside I'm going to put in a PR to remove unused imports for all files in deeprobust.graph.global_attack, I hope that's ok :)

Does not work on Python 3.5

Hi,

I understand the deeprobust is supposed to be installed on Python>3.6, but currently, I have to work on python 3.5 due to some incompatible reason.

I tried to run the code on python3.5 and got the following problem:

    from deeprobust.graph.defense import GCN
  File "<frozen importlib._bootstrap>", line 969, in _find_and_load
  File "<frozen importlib._bootstrap>", line 958, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 664, in _load_unlocked
  File "<frozen importlib._bootstrap>", line 634, in _load_backward_compatible
  File "/usr/local/lib/python3.5/dist-packages/deeprobust-0-py3.5.egg/deeprobust/graph/defense/__init__.py", line 2, in <module>
  File "<frozen importlib._bootstrap>", line 969, in _find_and_load
  File "<frozen importlib._bootstrap>", line 954, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 896, in _find_spec
  File "<frozen importlib._bootstrap_external>", line 1139, in find_spec
  File "<frozen importlib._bootstrap_external>", line 1115, in _get_spec
  File "<frozen importlib._bootstrap_external>", line 1096, in _legacy_get_spec
  File "<frozen importlib._bootstrap>", line 444, in spec_from_loader
  File "<frozen importlib._bootstrap_external>", line 533, in spec_from_file_location
  File "/usr/local/lib/python3.5/dist-packages/deeprobust-0-py3.5.egg/deeprobust/graph/defense/gcn_preprocess.py", line 33
    print(f'=== GCN-SVD: rank={k} ===')
                                     ^
SyntaxError: invalid syntax

Is that possible to run deeprobust on python3.5, could you please help me with this?

Thanks in advance.

Graph global attack API

I've been using this library to generate global adversarial attacks on graphs using DICE and PGD. I have some suggestions which I'd be happy to implement and put a pull request in for, but I wanted to raise it for your feedback first and check to see if this is something you would be interested in me doing.

Here's a code snippet where I do a DICE and PGD attack I will use to highlight the motivation for my suggestions.

from deeprobust.graph.data import Dataset
from deeprobust.graph.global_attack import DICE, PGDAttack
from deeprobust.graph.defense import GCN
import numpy as np
import torch
import scipy.sparse as sp

# parameters
perturbations = 20
device = 'cpu'

# get data
data = Dataset(root='/tmp', name='cora', setting='nettack')
adj, features, labels = data.adj, data.features, data.labels
idx_train, idx_val, idx_test = data.idx_train, data.idx_val, data.idx_test
idx_unlabeled = np.union1d(idx_val, idx_test)
features = torch.FloatTensor(features.todense())
labels = torch.LongTensor(labels)

# fit model
surrogate = GCN(nfeat=features.shape[1], nclass=labels.max().item()+1, nhid=16, device=device)
surrogate = surrogate.to(device)
surrogate.fit(features, adj, labels, idx_train, idx_val)

# dice attack
model = DICE(model=surrogate, nnodes=adj.shape[0], device=device)
model = model.to(device)
modified_adj = model.attack(adj=adj, labels=labels, n_perturbations=perturbations)
modified_adj = modified_adj

# pgd attack
model = PGDAttack(model=surrogate, nnodes=adj.shape[0], device=device)
model = model.to(device)
model.attack(ori_features=features, ori_adj=torch.FloatTensor(adj.todense()), labels=labels, idx_train=idx_train, perturbations=perturbations)
modified_adj = sp.csr_matrix(model.modified_adj.cpu().numpy())

The DICE and PGDAttack classes both subclass BaseAttack but have slightly different ways to use the attack method.

  • In DICE the original adjacency is given by keyword adj but in PGDAttack it's given by ori_adj
  • In DICE a sparse scipy array is a valid input type but in PGDAttack it is not.
  • The way the modified_adj is accessed after the attack is different for both classes.

I think the following changes could benefit the deeprobust/graph/global_attack API

  • Giving BaseAttack.attack an argument list and agree on what input types the methods will be able to accept
  • Using a docstring style such as the numpy/scipy or Google style which gives argument and return descriptions and types
  • Including a **kwargs keyword into attack methods that don't use all arguments. This would allow one to change the attack method with very little effort.
  • Use Errors instead of assert statements, for example in the PGDAttack.__init__ method
  • Replace BaseAttack.save_adj and BaseAttack.save_features with methods that return these variables, rather than save them.
  • Add an epochs parameter to PGDAttack.attack

Let me know your feedback on these suggestions, I can make them into separate issues which will help us track progress. If you agree with some of these changes I'll be happy to get started on them.

Question regarding the PGD graph global attack

Hi,

I also met the problem described in question 3 (KaidiXu/GCN_ADV_Train#5)
When handling the fixed model with PGD graph global attack without retraining, it becomes a white box evasion attack, but the ASR is quite low.
I am wondering do you have any clues for dealing with this?

Thanks for your help in advance.

I got a runtime error

Hi Authors,

I would like to repfoduce the results of your paper for my course project. But I keep on getting the error when I run the code.

when I use this command "python train.py --dataset polblogs --attack meta --ptb_rate 0.15 --epoch 1000", I change the dataset setting to "gcn" in the train.py. I got the runtime error.
Traceback (most recent call last):
File "train.py", line 100, in
prognn.fit(features, perturbed_adj, labels, idx_train, idx_val)
File "/Users/lijuan/opt/anaconda3/lib/python3.8/site-packages/deeprobust/graph/defense/prognn.py", line 88, in fit
self.train_adj(epoch, features, adj, labels,
File "/Users/lijuan/opt/anaconda3/lib/python3.8/site-packages/deeprobust/graph/defense/prognn.py", line 169, in train_adj
output = self.model(features, normalized_adj)
File "/Users/lijuan/opt/anaconda3/lib/python3.8/site-packages/torch/nn/modules/module.py", line 727, in _call_impl
result = self.forward(*input, **kwargs)
File "/Users/lijuan/opt/anaconda3/lib/python3.8/site-packages/deeprobust/graph/defense/gcn.py", line 124, in forward
x = F.relu(self.gc1(x, adj))
File "/Users/lijuan/opt/anaconda3/lib/python3.8/site-packages/torch/nn/modules/module.py", line 727, in _call_impl
result = self.forward(*input, **kwargs)
File "/Users/lijuan/opt/anaconda3/lib/python3.8/site-packages/deeprobust/graph/defense/gcn.py", line 40, in forward
output = torch.spmm(adj, support)
RuntimeError: mat1 and mat2 shapes cannot be multiplied (1222x1222 and 1490x16)

And then I used the command "sh scripts/meta/cora_meta.sh", but still got the runtime error.

Traceback (most recent call last):
File "train.py", line 100, in
prognn.fit(features, perturbed_adj, labels, idx_train, idx_val)
File "/Users/lijuan/opt/anaconda3/lib/python3.8/site-packages/deeprobust/graph/defense/prognn.py", line 88, in fit
self.train_adj(epoch, features, adj, labels,
File "/Users/lijuan/opt/anaconda3/lib/python3.8/site-packages/deeprobust/graph/defense/prognn.py", line 165, in train_adj
loss_smooth_feat = self.feature_smoothing(estimator.estimated_adj, features)
File "/Users/lijuan/opt/anaconda3/lib/python3.8/site-packages/deeprobust/graph/defense/prognn.py", line 270, in feature_smoothing
XLXT = torch.matmul(torch.matmul(X.t(), L), X)
RuntimeError: mat1 and mat2 shapes cannot be multiplied (1433x2708 and 2485x2485)

Could you tell me what is the problem? How could I fix it? Thanks so much

No module named 'scipy._lib.six'

Hi, I tried to run the demo like
import deeprobust.image.netmodels.train_model as trainmodel
trainmodel.train('CNN', 'MNIST', 'cuda', 20)

on the Readme but it just showed the following error report:

Traceback (most recent call last):

File "/home/ubuntu/codew/untitled0.py", line 9, in
import deeprobust.image.netmodels.train_model as trainmodel

File "/home/ubuntu/anaconda3/lib/python3.8/site-packages/deeprobust/image/init.py", line 3, in
from deeprobust.image import attack

File "/home/ubuntu/anaconda3/lib/python3.8/site-packages/deeprobust/image/attack/init.py", line 9, in
from deeprobust.image.attack import cw

File "/home/ubuntu/anaconda3/lib/python3.8/site-packages/deeprobust/image/attack/cw.py", line 9, in
from deeprobust.image.optimizer import AdamOptimizer

File "/home/ubuntu/anaconda3/lib/python3.8/site-packages/deeprobust/image/optimizer.py", line 19, in
from scipy._lib.six import xrange, string_types

ModuleNotFoundError: No module named 'scipy._lib.six'

The current version of my Scipy is 1.5.2, and it seems that the subpackage "scipy._lib.six"
has been removed from the newest Scipy, so I wanna know how to solve the problem.

Many Thx :)

test_gat.py throwing error when running: "AttributeError: 'GATConv' object has no attribute 'weight'"

When running the following python program test_gat.py, it is throwing an error as below.

Traceback (most recent call last):
File "test_gat.py", line 34, in
gat.fit(pyg_data, verbose=True) # train with earlystopping
File "/home/satvikchekuri/anaconda3/envs/graph/lib/python3.8/site-packages/deeprobust-0.2.0-py3.8.egg/deeprobust/graph/defense/gat.py", line 123, in fit
File "/home/satvikchekuri/anaconda3/envs/graph/lib/python3.8/site-packages/torch/nn/modules/module.py", line 947, in getattr
raise AttributeError("'{}' object has no attribute '{}'".format(
AttributeError: 'GATConv' object has no attribute 'weight'

MetaApprox much higher accuracy for perturbed graph

Hi, Thanks for sharing the DeepRobust code.

I am testing the mettack.py code using test_mettack.py. When the model is A-Meta-Self, the attacked graph accuracy is much higher than Meta-Self model. For cora dataset with ptb_rate 0.2, the attacked graph accuracy with Meta-Self model is 0.4834 while the A-Meta-Self model output a much higher accuracy 0.7596.

A-Meta-Self model has similar problems for other ptb_rate. Does it need special parameter setting? What is your test results for A-Meta-Self?

[Bug] The CNN model is not working with MNIST data

The CNN model has an FC layer with input dim as int(self.H/4) * int(self.W/4) * self.out_channel2, which is 7 * 7 * 64 according to the MNIST image size. But when using the MNIST data through CNN's conv layers, the size becomes 8 * 8 * 64, which will cause mat size mismatch error.

error when use metaattack to attack feature

  1. if use sparce feature matrix: 'RuntimeError: add(sparse, dense) is not supported. Use add(dense, sparse) instead.'
  2. 'Metattack' object has no attribute 'features_changes' I think you misspelled 'feature_change' as 'features_changes' in the code

there is a bug in code

deeprobust\image\attack\cw.py

line 67, 68 is
self.clip_min,
self.clip_min,

i think it should be
self.clip_max,
self.clip_min,

Memory Requirement for running MetaApprox on Pubmed

Thanks for your wonderful work in "Graph Structure Learning for Robust Graph Neural Networks", KDD'20.

I am trying to repeat your results on Pubmed, especially the one based on mettack.

However, mettack requires large memory to run on Pubmed, such that it cannot fit into a GPU with 16GB memory.
I have also tried MetaApprox [1], but still facing similar problems.

  1. Could you please share some experience on the memory requirement when you evaluate mettack?

  2. You mentioned A-Meta-Self as the approximate version of meta-self, which saves memory and time. Is A-Meta-Self the same as the MetaApprox?

Thanks,
Boyuan

[1] https://github.com/DSE-MSU/DeepRobust/blob/master/deeprobust/graph/global_attack/mettack.py

A bug in Metattack & MetaApprox

I encountered a bug when I'm trying Mettack.

In deeprobust/graph/global_attack/mettack.py, line 346 to 361:

            adj_meta_score = torch.tensor(0.0).to(self.device)
            feature_meta_score = torch.tensor(0.0).to(self.device)

            if self.attack_structure:
                adj_meta_score = self.get_adj_score(self.adj_grad_sum, modified_adj, ori_adj, ll_constraint, ll_cutoff)
            if self.attack_features:
                feature_meta_score = self.get_feature_score(self.feature_grad_sum, modified_features)

            if adj_meta_score.max() >= feature_meta_score.max():
                adj_meta_argmax = torch.argmax(adj_meta_score)
                row_idx, col_idx = utils.unravel_index(adj_meta_argmax, ori_adj.shape)
                self.adj_changes.data[row_idx][col_idx] += (-2 * modified_adj[row_idx][col_idx] + 1)
                self.adj_changes.data[col_idx][row_idx] += (-2 * modified_adj[row_idx][col_idx] + 1)
            else:
                feature_meta_argmax = torch.argmax(feature_meta_score)
                row_idx, col_idx = utils.unravel_index(feature_meta_argmax, ori_features.shape)
                self.feature_changes.data[row_idx][col_idx] += (-2 * modified_features[row_idx][col_idx] + 1)

The default values of adj_meta_score and feature_meta_score are 0. This seems OK in most cases but can cause errors in some extreme cases (as I encountered).

The problem is, if self.attack_adj is True, self.attack_features is False and adj_meta_score.max() < 0. then it will go in the "else" branch, and setting self.feature_changes (line 361) will cause an ModuleAttributeError error (self.feature_changes is undefined since self.attack_features is False).

I think the default values should be -inf, so that it will never go into the branch when self.attack_features is False.

This bug exists in MetaApprox, too.

Mistake in GGCL_D

Thank you for developing this library!
I guess GGCL, which is a module for RGCN, has a mistake in the return variables of forward function.
In lines 69 - 72, graph/defense/rgcn.py, codes are written as:

Att = torch.exp(-gamma * sigma)
mean_out = adj_norm1 @ (miu * Att)
sigma_out = adj_norm2 @ (sigma * Att * Att)
return mean_out, sigma

Currently forward returns sigma.
But I think forward should return sigma_out, i.e. sigma applied the attention Att

Att = torch.exp(-gamma * sigma)
mean_out = adj_norm1 @ (miu * Att)
sigma_out = adj_norm2 @ (sigma * Att * Att)
return mean_out, sigma_out

If so, I will make a PR for this.
Thank you.

Why compute gradient for adj_changes

Thanks for your contribution, this project is great help for our work.

I have 2 question for mettack attack method and other global attack method.

(1) When get gradient for updating adjacent matrix A to obtain modified_adj, there is a critical method get_meta_grad. I can't understand why compute gradient loss function attack_loss to adj_changes. i.e.,
adj_grad = torch.autograd.grad(attack_loss, self.adj_changes, retain_graph=True)[0]
What is the relationship with the loss function attack_loss and adj_changes?
In my point of view, loss function attack_loss should compute gradient to adj_norm(adjacent matrix, not adj_changes), i.e.,
adj_grad2 = torch.autograd.grad(attack_loss, adj_norm, retain_graph=True)[0]
But, this method has no effect.
(2) adj_grad is a symmetric matrix when compute gradient with adj_changes, why? I can't understand this operation process.

Thanks!

Something wrong with `test_nipa.py`

When I directly run test_nipa.py, I got an error like this:

 % python3 test_nipa.py
Namespace(batch_size=10, bilin_q=1, ctx='gpu', dataset='cora', dropout=0.5, gm='mean_field', hidden=0, latent_dim=64, learning_rate=0.01, max_lv=1, meta_test=0, mlp_hidden=64, num_epochs=200, num_mod=1, num_steps=500000, phase='train', ratio=0.01, reward_type='binary', save_dir='./results/rl_s2v/cora-gcn', saved_model='results/node_classification/cora', seed=1, weight_decay=0.0005)
Loading cora dataset...
Dowloading from https://raw.githubusercontent.com/danielzuegner/nettack/master/data/cora.npz to /tmp/cora.npz
Selecting 1 largest connected components
number of injected nodes: 24
Traceback (most recent call last):
  File "test_nipa.py", line 90, in <module>
    features, labels, idx_train, idx_val, idx_test, victim_model, dict_of_lists, adj = init_setup()
  File "test_nipa.py", line 76, in init_setup
    output = victim_model.predict(features, adj)
  File "/xxx/deeprobust/graph/defense/gcn.py", line 215, in predict
    return self.forward(self.features, self.adj_norm)
  File "/xxx/deeprobust/graph/defense/gcn.py", line 87, in forward
    x = F.relu(self.gc1(x, adj))
  File "/xxx/.local/lib/python3.6/site-packages/torch/nn/modules/module.py", line 541, in __call__
    result = self.forward(*input, **kwargs)
  File "/xxx/deeprobust/graph/defense/gcn.py", line 43, in forward
    output = torch.spmm(adj, support)
RuntimeError: addmm: Argument #3 (dense): Expected dim 0 size 2485, got 2509

Loss function

I find that you use nll_loss as the loss function in PGDtraining, why you don't use cross_entropy?

In ResNet, you use the cross_entropy to train the model

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.