Skip to content

Commit 131512c

Browse files
committed
Running PEARC24 Code
1 parent 1520846 commit 131512c

File tree

8 files changed

+333
-385
lines changed

8 files changed

+333
-385
lines changed

Adversarial_Observation/Attacks.py

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -10,35 +10,35 @@
1010
def fgsm_attack(input_batch_data: torch.Tensor, model: torch.nn.Module, input_shape: tuple, epsilon: float) -> torch.Tensor:
1111
"""
1212
Apply the FGSM attack to input images given a pre-trained PyTorch model.
13-
14-
Args:
15-
input_batch_data (torch.Tensor): Batch of input images.
16-
model (torch.nn.Module): Pre-trained PyTorch model to be attacked.
17-
input_shape (tuple): Shape of the input array.
18-
epsilon (float): Magnitude of the perturbation for the attack.
19-
20-
Returns:
21-
torch.Tensor: Adversarial images generated by the FGSM attack.
2213
"""
2314
model.eval()
2415
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
25-
input_batch_data = input_batch_data.to(device).detach().requires_grad_(True)
16+
input_batch_data = input_batch_data.to(device)
17+
18+
adversarial_batch_data = []
2619

27-
adversarial_batch_data = torch.clone(input_batch_data).detach()
28-
2920
for img in input_batch_data:
30-
preds = model(img.reshape(input_shape))
31-
target = torch.argmax(preds)
32-
loss = F.cross_entropy(preds, target.unsqueeze(0))
21+
# Make a copy of the image and enable gradient tracking
22+
img = img.clone().detach().unsqueeze(0).to(device)
23+
img.requires_grad = True
3324

25+
# Forward pass
26+
preds = model(img)
27+
target = torch.argmax(preds, dim=1)
28+
loss = F.cross_entropy(preds, target)
29+
30+
# Backward pass
3431
model.zero_grad()
3532
loss.backward()
3633

37-
adversarial_img = img + epsilon * img.grad.sign()
34+
# Generate perturbation
35+
grad = img.grad.data
36+
adversarial_img = img + epsilon * grad.sign()
3837
adversarial_img = torch.clamp(adversarial_img, 0, 1)
39-
adversarial_batch_data.append(adversarial_img)
4038

41-
return adversarial_batch_data
39+
adversarial_batch_data.append(adversarial_img.squeeze(0).detach())
40+
41+
return torch.stack(adversarial_batch_data)
4242

4343
def compute_gradients(model, img, target_class):
4444
preds = model(img)
@@ -66,7 +66,7 @@ def gradient_ascent(input_image, model, input_shape, target_class, num_iteration
6666
def gradient_map(input_image, model, input_shape):
6767
model.eval()
6868
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
69-
input_image = input_image.to(device).detach().requires_grad_(True)
69+
input_image = torch.tensor(input_image).to(device).detach().requires_grad_(True)
7070

7171
preds = model(input_image.reshape(input_shape))
7272
target_class = torch.argmax(preds)
Lines changed: 52 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,44 @@
1-
import tensorflow as tf
1+
import torch
2+
import torch.nn.functional as F
23
import numpy as np
34

45
class BirdParticle:
56
"""
6-
Represents a particle in the Particle Swarm Optimization (PSO) algorithm for adversarial attacks.
7-
8-
The BirdParticle class encapsulates the state of each particle, including its position, velocity,
9-
fitness evaluation, and the updates to its velocity and position based on the PSO algorithm.
7+
Represents a particle in the Particle Swarm Optimization (PSO) algorithm for adversarial attacks (PyTorch version).
108
"""
119

12-
def __init__(self, model: tf.keras.Model, input_data: tf.Tensor, target_class: int, num_iterations: int = 20,
13-
velocity: tf.Tensor = None, inertia_weight: float = 0.5,
10+
def __init__(self, model: torch.nn.Module, input_data: torch.Tensor, target_class: int, num_iterations: int = 20,
11+
velocity: torch.Tensor = None, inertia_weight: float = 0.5,
1412
cognitive_weight: float = 1.0, social_weight: float = 1.0,
15-
momentum: float = 0.9, clip_value_position: float = 1.0):
13+
momentum: float = 0.9, clip_value_position: float = 1.0, device='cpu'):
1614
"""
1715
Initialize a particle in the PSO algorithm.
1816
1917
Args:
20-
model (tf.keras.Model): The model to attack.
21-
input_data (tf.Tensor): The input data (image) to attack.
18+
model (torch.nn.Module): The model to attack.
19+
input_data (torch.Tensor): The input data (image) to attack.
2220
target_class (int): The target class for misclassification.
23-
velocity (tf.Tensor, optional): The initial velocity for the particle's movement. Defaults to zero velocity if not provided.
24-
inertia_weight (float): The inertia weight for the velocity update. Default is 0.5.
25-
cognitive_weight (float): The cognitive weight for the velocity update. Default is 1.0.
26-
social_weight (float): The social weight for the velocity update. Default is 1.0.
27-
momentum (float): The momentum for the velocity update. Default is 0.9.
21+
velocity (torch.Tensor, optional): Initial velocity; defaults to zero.
22+
inertia_weight (float): Inertia weight for velocity update.
23+
cognitive_weight (float): Cognitive weight for velocity update.
24+
social_weight (float): Social weight for velocity update.
25+
momentum (float): Momentum for velocity update.
26+
clip_value_position (float): Max absolute value to clip position.
27+
device (str): Device to run on.
2828
"""
29-
self.model = model
29+
self.device = device
30+
self.model = model.to(device)
3031
self.num_iterations = num_iterations
31-
self.original_data = tf.identity(input_data) # Clone the input data
32+
self.original_data = input_data.clone().detach().to(device)
33+
self.position = input_data.clone().detach().to(device)
3234
self.target_class = target_class
33-
self.best_position = tf.identity(input_data) # Clone the input data
35+
self.velocity = velocity.clone().detach().to(device) if velocity is not None else torch.zeros_like(input_data).to(device)
36+
self.best_position = self.position.clone().detach()
3437
self.best_score = -np.inf
35-
self.position = tf.identity(input_data) # Clone the input data
36-
self.velocity = velocity if velocity is not None else tf.zeros_like(input_data)
37-
self.history = [self.position]
38+
self.history = [self.position.clone().detach()]
3839
self.clip_value_position = clip_value_position
39-
# Class attributes
40+
41+
# PSO hyperparameters
4042
self.inertia_weight = inertia_weight
4143
self.cognitive_weight = cognitive_weight
4244
self.social_weight = social_weight
@@ -45,52 +47,47 @@ def __init__(self, model: tf.keras.Model, input_data: tf.Tensor, target_class: i
4547
def fitness(self) -> float:
4648
"""
4749
Compute the fitness score for the particle, which is the softmax probability of the target class.
48-
49-
Higher fitness scores correspond to better success in the attack (misclassifying the image into the target class).
50-
5150
Returns:
52-
float: Fitness score for this particle (higher is better).
51+
float: Target class softmax probability.
5352
"""
54-
output = self.model(self.position) # Add batch dimension and pass through the model
55-
probabilities = tf.nn.softmax(output, axis=1) # Get probabilities for each class
56-
target_prob = probabilities[:, self.target_class] # Target class probability
57-
58-
return target_prob.numpy().item() # Return the target class probability as fitness score
53+
self.model.eval()
54+
with torch.no_grad():
55+
input_tensor = self.position
56+
output = self.model(input_tensor.to(self.device))
57+
probabilities = F.softmax(output, dim=1)
58+
target_prob = probabilities[:, self.target_class]
59+
return target_prob.item()
5960

60-
def update_velocity(self, global_best_position: tf.Tensor) -> None:
61+
def update_velocity(self, global_best_position: torch.Tensor) -> None:
6162
"""
62-
Update the velocity of the particle based on the PSO update rule.
63+
Update the particle's velocity using the PSO rule.
6364
6465
Args:
65-
global_best_position (tf.Tensor): The global best position found by the swarm.
66+
global_best_position (torch.Tensor): Global best position in the swarm.
6667
"""
68+
r1 = torch.rand_like(self.position).to(self.device)
69+
r2 = torch.rand_like(self.position).to(self.device)
70+
6771
inertia = self.inertia_weight * self.velocity
68-
cognitive = self.cognitive_weight * tf.random.uniform(self.position.shape) * (self.best_position - self.position)
69-
social = self.social_weight * tf.random.uniform(self.position.shape) * (global_best_position - self.position)
70-
71-
# Apply momentum to velocity update:
72-
self.velocity = self.momentum * self.velocity + inertia + cognitive + social # Apply momentum
72+
cognitive = self.cognitive_weight * r1 * (self.best_position - self.position)
73+
social = self.social_weight * r2 * (global_best_position.to(self.device) - self.position)
74+
75+
self.velocity = self.momentum * self.velocity + inertia + cognitive + social
7376

7477
def update_position(self) -> None:
7578
"""
76-
Update the position of the particle based on the updated velocity.
77-
78-
The position is updated directly without any bounds checking.
79+
Update the particle's position based on the new velocity.
7980
"""
80-
self.position = self.position + self.velocity # Update position directly without clipping
81-
self.position = tf.clip_by_value(self.position + self.velocity, 0, 1) # Ensure position stays within bounds
82-
self.history.append(tf.identity(self.position)) # Store the position history
83-
self.position = tf.clip_by_value(self.position, -self.clip_value_position, self.clip_value_position)
84-
81+
self.position = self.position + self.velocity
82+
self.position = torch.clamp(self.position, 0.0, 1.0) # Keep values in [0, 1]
83+
self.position = torch.clamp(self.position, -self.clip_value_position, self.clip_value_position)
84+
self.history.append(self.position.clone().detach())
85+
8586
def evaluate(self) -> None:
8687
"""
87-
Evaluate the fitness of the current particle and update its personal best.
88-
89-
The fitness score is calculated using the target class probability. If the current fitness score
90-
is better than the personal best, update the best position and score.
88+
Evaluate current fitness and update personal best if needed.
9189
"""
92-
score = self.fitness() # Get the current fitness score based on the perturbation
93-
if score > self.best_score: # If score is better than the personal best, update the best position
90+
score = self.fitness()
91+
if score > self.best_score:
9492
self.best_score = score
95-
self.best_position = tf.identity(self.position) # Clone the current position
96-
93+
self.best_position = self.position.clone().detach()

0 commit comments

Comments
 (0)