def test(adj, gcn=None): ''' test on GCN ''' if gcn is None: # adj = normalize_adj_tensor(adj) gcn = GCN(nfeat=features.shape[1], nhid=args.hidden, nclass=labels.max().item() + 1, dropout=args.dropout, device=device) gcn = gcn.to(device) gcn.fit(features, adj, labels, idx_train) # train without model picking gcn.fit(features, adj, labels, idx_train, idx_val, patience=30) # train with validation model picking gcn.eval() output = gcn.predict().cpu() else: gcn.eval() output = gcn.predict().cpu() loss_test = F.nll_loss(output[idx_test], labels[idx_test]) acc_test = accuracy(output[idx_test], labels[idx_test]) print("Test set results:", "loss= {:.4f}".format(loss_test.item()), "accuracy= {:.4f}".format(acc_test.item())) return acc_test.item()
def select_nodes(target_gcn=None): ''' selecting nodes as reported in Nettack paper: (i) the 10 nodes with highest margin of classification, i.e. they are clearly correctly classified, (ii) the 10 nodes with lowest margin (but still correctly classified) and (iii) 20 more nodes randomly ''' if target_gcn is None: target_gcn = GCN(nfeat=features.shape[1], nhid=16, nclass=labels.max().item() + 1, dropout=0.5, device=device) target_gcn = target_gcn.to(device) target_gcn.fit(features, adj, labels, idx_train, idx_val, patience=30) target_gcn.eval() output = target_gcn.predict() margin_dict = {} for idx in idx_test: margin = classification_margin(output[idx], labels[idx]) if margin < 0: # only keep the nodes correctly classified continue margin_dict[idx] = margin sorted_margins = sorted(margin_dict.items(), key=lambda x: x[1], reverse=True) high = [x for x, y in sorted_margins[: 10]] low = [x for x, y in sorted_margins[-10:]] other = [x for x, y in sorted_margins[10: -10]] other = np.random.choice(other, 20, replace=False).tolist() return high + low + other
def single_test(adj, features, target_node, gcn=None): if gcn is None: # test on GCN (poisoning attack) gcn = GCN(nfeat=features.shape[1], nhid=16, nclass=labels.max().item() + 1, dropout=0.5, device=device) gcn = gcn.to(device) gcn.fit(features, adj, labels, idx_train, idx_val, patience=30) gcn.eval() output = gcn.predict() else: # test on GCN (evasion attack) output = gcn.predict(features, adj) probs = torch.exp(output[[target_node]]) # acc_test = accuracy(output[[target_node]], labels[target_node]) acc_test = (output.argmax(1)[target_node] == labels[target_node]) return acc_test.item()
def test_attack(adj, features, target_node): ''' test on GCN after NETTACK poisoning attack''' gcn = GCN(nfeat=features.shape[1], nhid=16, nclass=labels.max().item() + 1, dropout=0.5, device=device) gcn = gcn.to(device) gcn.fit(features, adj, labels, idx_train) gcn.eval() output = gcn.predict() probs = torch.exp(output[[target_node]]) acc_test = accuracy(output[[target_node]], [labels[target_node]]) return acc_test.item()
def main(): target_gcn = GCN(nfeat=features.shape[1], nhid=16, nclass=labels.max().item() + 1, dropout=0.5, device=device, lr=0.01) target_gcn = target_gcn.to(device) target_gcn.fit(features, adj, labels, idx_train, idx_val, patience=30) # target_gcn.fit(features, adj, labels, idx_train) print('=== testing GCN on clean graph ===') test(adj, target_gcn) # Setup Attack Model print('=== setup attack model ===') model = PGDAttack(model=target_gcn, nnodes=adj.shape[0], loss_type='CE', device=device) model = model.to(device) # model.attack(features, adj, labels, idx_train, perturbations, epochs=args.epochs) # Here for the labels we need to replace it with predicted ones fake_labels = target_gcn.predict(features.to(device), adj.to(device)) fake_labels = torch.argmax(fake_labels, 1).cpu() # Besides, we need to add the idx into the whole process idx_fake = np.concatenate([idx_train, idx_test]) idx_others = list(set(np.arange(len(labels))) - set(idx_train)) fake_labels = torch.cat([labels[idx_train], fake_labels[idx_others]]) model.attack(features, adj, fake_labels, idx_fake, perturbations, epochs=args.epochs) print('=== testing GCN on Evasion attack ===') modified_adj = model.modified_adj test(modified_adj, target_gcn) # modified_features = model.modified_features print('=== testing GCN on Poisoning attack ===') test(modified_adj)
def single_test(adj, features, target_node): ''' test on GCN (poisoning attack)''' gcn = GCN(nfeat=features.shape[1], nhid=16, nclass=labels.max().item() + 1, dropout=0.5, device=device) gcn = gcn.to(device) gcn.fit(features, adj, labels, idx_train) gcn.eval() output = gcn.predict() probs = torch.exp(output[[target_node]]) acc_test = accuracy(output[[target_node]], labels[target_node]) # print("Test set results:", "accuracy= {:.4f}".format(acc_test.item())) return acc_test.item()
def test_GCN(): ''' test on GCN ''' gcn = GCN(nfeat=features.shape[1], nhid=16, nclass=labels.max().item() + 1, dropout=0.5, device=device) gcn = gcn.to(device) gcn.fit(features, adj, labels, idx_train) gcn.eval() output = gcn.predict() acc_test = accuracy(output[idx_test], labels[idx_test]) print("GCN Test set results:", "accuracy= {:.4f}".format(acc_test.item())) return acc_test.item()
def test(adj, features, target_node): ''' test on GCN ''' gcn = GCN(nfeat=features.shape[1], nhid=16, nclass=labels.max().item() + 1, dropout=0.5, device=device) gcn = gcn.to(device) gcn.fit(features, adj, labels, idx_train, idx_val, patience=30) gcn.eval() output = gcn.predict() probs = torch.exp(output[[target_node]])[0] print('Target node probs: {}'.format(probs.detach().cpu().numpy())) acc_test = accuracy(output[idx_test], labels[idx_test]) print("Overall test set results:", "accuracy= {:.4f}".format(acc_test.item())) return acc_test.item()
def test(adj, features, target_node): ''' test on GCN ''' gcn = GCN(nfeat=features.shape[1], nhid=16, nclass=labels.max().item() + 1, dropout=0.5, device=device) gcn = gcn.to(device) gcn.fit(features, adj, labels, idx_train) gcn.eval() output = gcn.predict() probs = torch.exp(output[[target_node]])[0] print('probs: {probs.detach().cpu().numpy()}') labels_tensor = torch.LongTensor(labels).to(device) loss_test = F.nll_loss(output[idx_test], labels_tensor[idx_test]) acc_test = accuracy(output[idx_test], labels_tensor[idx_test]) print("Test set results:", "loss= {:.4f}".format(loss_test.item()), "accuracy= {:.4f}".format(acc_test.item())) return acc_test.item()
for i in tqdm(range(100)): # modified_adj = adversary.attack(features, adj) modified_adj = adversary.attack(adj, n_perturbations=n_perturbations, type='add') adv_train_model.fit(features, modified_adj, labels, idx_train, train_iters=50, initialize=False) adv_train_model.eval() # test directly or fine tune print('=== test on perturbed adj ===') output = adv_train_model.predict() acc_test = accuracy(output[idx_test], labels[idx_test]) print("Test set results:", "accuracy= {:.4f}".format(acc_test.item())) # set up Surrogate & Nettack to attack the graph import random target_nodes = random.sample(idx_test.tolist(), 20) # Setup Surrogate model surrogate = GCN(nfeat=features.shape[1], nclass=labels.max().item() + 1, nhid=16, dropout=0, with_relu=False, with_bias=False, device=device)
model.fit(features, perturbed_adj, labels, idx_train) output = model.output acc_test = accuracy(output[idx_test], labels[idx_test]) print("Test set results:", "accuracy= {:.4f}".format(acc_test.item())) # For poisoning attack, the adjacency matrix you have # is alreay perturbed print('=== Adversarial Training for Poisoning Attack===') model.initialize() n_perturbations = int(0.01 * (adj.sum() // 2)) for i in range(100): # modified_adj = adversary.attack(features, adj) adversary.attack(perturbed_adj, n_perturbations=n_perturbations, type='remove') modified_adj = adversary.modified_adj model.fit(features, modified_adj, labels, idx_train, train_iters=50, initialize=False) model.eval() # test directly or fine tune print('=== test on perturbed adj ===') output = model.predict(features, perturbed_adj) acc_test = accuracy(output[idx_test], labels[idx_test]) print("Test set results:", "accuracy= {:.4f}".format(acc_test.item()))
model = GCNTorch(nfeat=features.shape[1], nhid=16, nclass=labels.max() + 1, device=device) model = model.to(device) model.fit(features, nettack.adj_preprocessed, labels, idx_train, idx_val, train_iters=200, verbose=False, normalize=False) model.eval() acc = model.test(idx_test) probs_after_defense = model.predict().detach().cpu().numpy()[u] preds['no'] = np.argmax(probs_after_defense) ########################### # vae settings model = 'arga_vae' #'arga_ae' or 'arga_vae' iterations = 500 if dataname == "polblogs" else 200 train = True # train or load pretrain ########################### percentile = (1 - adj.sum() / adj.shape[0]**2 * 20) * 100 reconstructor = Link_rec_Runner(nettack.adj, features, model, iterations) reconstructor.erun(train=train) print("finishing reconstruction")