Skip to content

Commit 91492ba

Browse files
authored
fixed testing (#11)
1 parent ebc6040 commit 91492ba

File tree

13 files changed

+298
-230
lines changed

13 files changed

+298
-230
lines changed

Adversarial_Observation/Attacks.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import os
44
from datetime import datetime
55
from torch.nn import Softmax
6-
from .utils import fgsm_attack, pgd_attack, compute_success_rate, log_metrics, visualize_adversarial_examples
6+
from .utils import fgsm_attack, compute_success_rate, log_metrics, visualize_adversarial_examples
77
from .utils import seed_everything
88

99
class AdversarialTester:
@@ -44,8 +44,6 @@ def _generate_adversarial_images(self, input_batch_data: torch.Tensor):
4444
logging.info(f"Starting attack with method: {self.attack_method}")
4545
if self.attack_method == 'fgsm':
4646
return fgsm_attack(input_batch_data, self.model, self.epsilon, self.device)
47-
elif self.attack_method == 'pgd':
48-
return pgd_attack(input_batch_data, self.model, self.epsilon, self.alpha, self.num_steps, self.device)
4947
else:
5048
raise ValueError(f"Unsupported attack method: {self.attack_method}")
5149

Adversarial_Observation/utils.py

Lines changed: 0 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -60,51 +60,6 @@ def fgsm_attack(input_data: torch.Tensor, model: torch.nn.Module, epsilon: float
6060

6161
return adversarial_data
6262

63-
# PGD Attack (Projected Gradient Descent)
64-
def pgd_attack(input_data: torch.Tensor, model: torch.nn.Module, epsilon: float, alpha: float, num_steps: int, device: torch.device) -> torch.Tensor:
65-
"""
66-
Performs PGD attack on the input data.
67-
68-
Args:
69-
input_data (torch.Tensor): The original input batch.
70-
model (torch.nn.Module): The model to attack.
71-
epsilon (float): The maximum perturbation magnitude.
72-
alpha (float): The step size for each iteration.
73-
num_steps (int): The number of steps for the attack.
74-
device (torch.device): The device to perform the attack on (cuda or cpu).
75-
76-
Returns:
77-
torch.Tensor: The adversarially perturbed batch.
78-
"""
79-
# Initialize the perturbation to be the same as the original input data
80-
perturbed_data = input_data.clone().detach()
81-
perturbed_data.requires_grad = True
82-
83-
for _ in range(num_steps):
84-
# Forward pass to get the model's output
85-
output = model(perturbed_data)
86-
87-
# Compute the loss (we assume classification, so we use cross-entropy loss)
88-
loss = F.cross_entropy(output, torch.argmax(output, dim=1))
89-
90-
# Backpropagate the gradients
91-
model.zero_grad()
92-
loss.backward()
93-
94-
# Get the gradient of the input data with respect to the loss
95-
gradient = perturbed_data.grad.data
96-
97-
# Update the perturbation (step in the direction of the gradient)
98-
perturbed_data = perturbed_data + alpha * torch.sign(gradient)
99-
100-
# Clip the perturbation to stay within the epsilon ball
101-
perturbed_data = torch.max(torch.min(perturbed_data, input_data + epsilon), input_data - epsilon)
102-
103-
# Ensure the adversarial data is within the valid range (e.g., [0, 1] for image data)
104-
perturbed_data = torch.clamp(perturbed_data, 0, 1)
105-
106-
return perturbed_data
107-
10863
# Compute the success rate of the attack
10964
def compute_success_rate(original_preds: torch.Tensor, adversarial_preds: torch.Tensor) -> float:
11065
"""

README.md

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ The attack will run for `num_iterations` iterations, and the results will be sav
104104
**Example:**
105105

106106
```bash
107-
python main.py --iterations 50 --particles 100 --save_dir "analysis_results"
107+
python taint_MNIST.py --iterations 50 --particles 100 --save_dir "analysis_results"
108108
```
109109

110110
This command performs the attack with **50 iterations** and **100 particles**.
@@ -151,6 +151,22 @@ After the attack is complete, the following information is saved:
151151

152152
You can open the `attack_analysis.json` file for a detailed analysis of the attack.
153153

154+
---
155+
## Citing This Work
156+
157+
If you use or refer to this code in your research, please cite the following paper:
158+
159+
160+
```
161+
@incollection{gafur2024adversarial,
162+
title={Adversarial Robustness and Explainability of Machine Learning Models},
163+
author={Gafur, Jamil and Goddard, Steve and Lai, William},
164+
booktitle={Practice and Experience in Advanced Research Computing 2024: Human Powered Computing},
165+
pages={1--7},
166+
year={2024}
167+
}
168+
```
169+
154170
---
155171

156172
## Contributing

requirements.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,5 @@ shap
1212
torch
1313
torchvision
1414
sphinx_rtd_theme
15+
tensorflow
16+
imageio[pyav]

setup.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
license='MIT',
2020
packages=[
2121
"Adversarial_Observation",
22-
"Swarm_Observer"
2322
],
2423
python_requires='>=3.6',
2524
install_requires=[

tests/__init__.py

Whitespace-only changes.

tests/test_Gradient.py

Lines changed: 0 additions & 73 deletions
This file was deleted.

tests/test_Saliency.py

Lines changed: 0 additions & 73 deletions
This file was deleted.

tests/test_adversarial_attacks.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# tests/test_adversarial_attacks.py
2+
3+
import torch
4+
import pytest
5+
from Adversarial_Observation.utils import fgsm_attack, load_MNIST_model
6+
from torch import nn
7+
8+
# Helper function to generate random image data and a simple model
9+
def get_sample_data():
10+
model = load_MNIST_model()
11+
# Fake image (1, 1, 28, 28) for MNIST (batch_size=1, channel=1, height=28, width=28)
12+
input_data = torch.rand((1, 1, 28, 28)) # Random image
13+
return input_data, model
14+
15+
def test_fgsm_attack():
16+
input_data, model = get_sample_data()
17+
epsilon = 0.1 # Perturbation size
18+
device = torch.device('cpu') # Using CPU for simplicity
19+
20+
# Apply FGSM attack
21+
adversarial_data = fgsm_attack(input_data, model, epsilon, device)
22+
23+
# Check if adversarial data has been perturbed (should not be equal to original data)
24+
assert not torch.allclose(input_data, adversarial_data, atol=1e-5), "FGSM attack failed to perturb the input"
25+
26+
def test_success_rate():
27+
# Testing the success rate calculation
28+
original_preds = torch.tensor([0, 1, 2]) # Some dummy predictions
29+
adversarial_preds = torch.tensor([1, 0, 2]) # Adversarial predictions
30+
31+
# Calculate success rate (should be 2/3 as two predictions are different)
32+
from Adversarial_Observation.utils import compute_success_rate
33+
success_rate = compute_success_rate(original_preds, adversarial_preds)
34+
35+
assert success_rate == 2/3, f"Expected success rate 2/3, but got {success_rate}"
36+

0 commit comments

Comments
 (0)