Skip to content

Commit 6dbeb8c

Browse files
committed
training and attacking manuscript 2
1 parent 53e8a96 commit 6dbeb8c

File tree

6 files changed

+85
-42
lines changed

6 files changed

+85
-42
lines changed

manuscripts/Posion25/1_trainModel.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ def main():
1212
parser.add_argument('--model_type', type=str, choices=['normal', 'complex', 'complex_augmented'], required=True, help='Model type to use')
1313

1414
# Training information arguments
15-
parser.add_argument('--batch_size', type=int, default=32, help='Batch size for training')
16-
parser.add_argument('--epochs', type=int, default=10, help='Number of epochs for training')
15+
parser.add_argument('--batch_size', type=int, default=1024, help='Batch size for training')
16+
parser.add_argument('--epochs', type=int, default=5, help='Number of epochs for training')
1717

1818
# Folder saving argument
1919
parser.add_argument('--save_dir', type=str, default='results', help='Directory to save model and results')

manuscripts/Posion25/2_attackModel.py

Lines changed: 66 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -4,34 +4,75 @@
44
from taint import adversarial_attack_blackbox
55
from analysis import *
66
from train import train_model_and_save
7+
import torch
8+
import tensorflow as tf
79

810
def attack_model(args, model, test_ds, save_dir, num_data=10):
9-
# Path to the pickle file that stores the attacker object
10-
pickle_path = os.path.join(save_dir, 'attacker.pkl')
11+
# Get the labels by iterating through a batch from the test_ds
12+
first_batch = next(iter(test_ds)) # Get the first batch
13+
images, labels = first_batch # Unpack the images and labels from the first batch
1114

12-
# Check if the adversarial attack has already been performed (if pickle exists)
13-
if os.path.exists(pickle_path):
14-
# If pickle exists, load the attacker from the file
15-
with open(pickle_path, 'rb') as f:
16-
attacker = pickle.load(f)
17-
print(f"Loaded attacker from {pickle_path}")
18-
else:
19-
# If pickle does not exist, run the attack and save the attacker
20-
print("Running adversarial attack...")
21-
22-
# First, identify unique outputs in the dataset
23-
unique_outputs = set(test_ds.labels) # assuming `test_ds.labels` contains the true labels
24-
25-
for output in unique_outputs:
26-
# Find the first 10 instances of this output in the dataset
27-
instances = [i for i, label in enumerate(test_ds.labels) if label == output][:num_data]
28-
# Perform the attack on each of these instances
29-
for image_index in instances:
30-
adversarial_attack_blackbox(
31-
model, test_ds, image_index=image_index, output_dir=save_dir,
32-
num_iterations=args.iterations, num_particles=args.particles
33-
)
34-
print(f"Attacked image {image_index} with label {output}")
15+
# Check if labels are a TensorFlow tensor or PyTorch tensor
16+
if isinstance(labels, tf.Tensor):
17+
# If using TensorFlow, convert labels to class indices (from one-hot encoded)
18+
labels = tf.argmax(labels, axis=1).numpy() # Get class indices from one-hot encoded labels
19+
elif isinstance(labels, torch.Tensor):
20+
# If using PyTorch, convert labels to class indices (from one-hot encoded)
21+
labels = torch.argmax(labels, dim=1).cpu().numpy() # Get class indices from one-hot encoded labels
22+
23+
# Convert labels to a set of unique outputs
24+
unique_outputs = set(labels) # Convert to a Python set for unique labels
25+
26+
# Continue with the rest of the attack logic
27+
for output in unique_outputs:
28+
instances = [i for i, label in enumerate(labels) if label == output][:num_data] # Select `num_data` instances with the current output label
29+
30+
for image_index in instances:
31+
# Create a subdirectory for each image_index and its original output label
32+
sub_dir = os.path.join(save_dir, f'image_{image_index}_label_{output}')
33+
34+
# Ensure the directory exists
35+
os.makedirs(sub_dir, exist_ok=True)
36+
37+
# Correct dynamic pickle filename to include the original and target class
38+
pickle_filename = f'attacker_{image_index}_{output}.pkl'
39+
pickle_path = os.path.join(sub_dir, pickle_filename)
40+
41+
# Check if the attacker pickle already exists for this image_index and output
42+
if os.path.exists(pickle_path):
43+
with open(pickle_path, 'rb') as f:
44+
attacker = pickle.load(f)
45+
print(f"Loaded attacker for image {image_index} with label {output} from {pickle_path}")
46+
else:
47+
print(f"Running adversarial attack for image {image_index} with label {output}...")
48+
49+
# For the current `output`, target all other classes
50+
for target_output in unique_outputs:
51+
if target_output != output: # We want to target all other outputs
52+
for _ in range(num_data): # Attack the target output `num_data` times
53+
target_sub_dir = os.path.join(sub_dir, f'target_{target_output}')
54+
os.makedirs(target_sub_dir, exist_ok=True) # Create a subdir for each target class
55+
56+
# Correct dynamic pickle filename to include the original and target class
57+
target_pickle_filename = f'attacker_{image_index}_{output}_to_{target_output}.pkl'
58+
target_pickle_path = os.path.join(target_sub_dir, target_pickle_filename)
59+
60+
# Perform the adversarial attack targeting `target_output`
61+
attacker = adversarial_attack_blackbox(
62+
model=model,
63+
dataset=test_ds,
64+
image_index=image_index,
65+
output_dir=target_sub_dir,
66+
num_iterations=args.iterations,
67+
num_particles=args.particles,
68+
target_class=target_output # Specify the target class for the attack
69+
)
70+
print(f"Adversarial attack completed for image {image_index} targeting class {target_output}")
71+
72+
# After performing the attack, save the attacker object to a pickle file
73+
with open(target_pickle_path, 'wb') as f:
74+
pickle.dump(attacker, f)
75+
print(f"Saved attacker for image {image_index} with label {output} targeting {target_output} to {target_pickle_path}")
3576

3677
def main():
3778
# Command-line arguments

manuscripts/Posion25/3_stats.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
def collect_statistics(model, dataset, model_type, attack_iterations=10, attack_particles=100, image_index=0, output_dir='results'):
1414
"""
1515
Run adversarial attack for the given model and dataset combination and collect statistics.
16-
16+
1717
Args:
1818
- model: The model to attack.
1919
- dataset: The test dataset.
@@ -22,7 +22,7 @@ def collect_statistics(model, dataset, model_type, attack_iterations=10, attack_
2222
- attack_particles: Number of particles for attack.
2323
- image_index: Index of the image to perform the attack on.
2424
- output_dir: Directory to save results.
25-
25+
2626
Returns:
2727
- statistics: A dictionary with softmax output, attack success, and other relevant data.
2828
"""
@@ -40,12 +40,13 @@ def collect_statistics(model, dataset, model_type, attack_iterations=10, attack_
4040
single_target = np.argmax(all_labels[image_index])
4141
target_class = (single_target + 1) % 10 # Attack a different class
4242

43-
# Perform the attack (check if pickle exists first)
43+
# Load the attacker if pickle exists
4444
if os.path.exists(pickle_path):
4545
with open(pickle_path, 'rb') as f:
4646
attacker = pickle.load(f)
4747
print(f"Loaded attacker from {pickle_path}")
4848
else:
49+
# If attacker doesn't exist, run the attack and save it
4950
adversarial_attack_blackbox(
5051
model, dataset, image_index=image_index, output_dir=output_dir,
5152
num_iterations=attack_iterations, num_particles=attack_particles
@@ -56,7 +57,7 @@ def collect_statistics(model, dataset, model_type, attack_iterations=10, attack_
5657

5758
# Analyze the attack results
5859
softmax_output, max_val, max_class = get_softmax_stats(model, single_input)
59-
attack_success = max_class != target_class
60+
attack_success = max_class != target_class # Attack success is when max_class differs from target class
6061

6162
stats = {
6263
"model_type": model_type,
@@ -76,10 +77,10 @@ def collect_statistics(model, dataset, model_type, attack_iterations=10, attack_
7677
def get_model_types_for_dataset(dataset):
7778
"""
7879
Dynamically search for model types for a given dataset.
79-
80+
8081
Args:
8182
- dataset: The dataset name, e.g., 'MNIST' or 'AudioMNIST'.
82-
83+
8384
Returns:
8485
- model_types: List of available model types for the dataset.
8586
"""
@@ -125,6 +126,7 @@ def main():
125126

126127
# Data and model type arguments
127128
parser.add_argument('--data', type=str, choices=['MNIST', 'MNIST_Audio'], required=True, help='Dataset to use')
129+
parser.add_argument('--model_type', type=str, choices=['normal', 'complex', 'complex_augmented'], required=True, help='Model type to use')
128130

129131
# Attack parameters
130132
parser.add_argument('--iterations', type=int, default=10, help='Number of iterations for attack')

manuscripts/Posion25/runall.sh

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
#!/bin/bash
22

33
# Define available datasets and model types
4-
datasets=("MNIST" "MNIST_Audio")
4+
datasets=("MNIST")
5+
# "MNIST_Audio")
56
model_types=("normal" "complex")
67
# "complex_augmented")
78
save_dir="results"
@@ -19,11 +20,7 @@ for dataset in "${datasets[@]}"; do
1920

2021
echo "Finished training and attacking for $dataset - $model_type"
2122
done
23+
# python 3_stats.py --data $dataset --model_type $model_type --save_dir $save_dir
24+
# echo "Statistics collected for $dataset - $model_type"
2225
done
2326

24-
# Step 3: Collect statistics after all attacks have been run
25-
echo "Collecting statistics..."
26-
python 3_stats.py --data MNIST --iterations 10 --particles 100 --save_dir $save_dir
27-
python 3_stats.py --data MNIST_Audio --iterations 10 --particles 100 --save_dir $save_dir
28-
29-
echo "Statistics collection complete."

manuscripts/Posion25/taint.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from Adversarial_Observation.Swarm import ParticleSwarm
77
from analysis import *
88

9-
def adversarial_attack_blackbox(model, dataset, image_index, output_dir='results', num_iterations=30, num_particles=100):
9+
def adversarial_attack_blackbox(model, dataset, image_index, output_dir='results', num_iterations=30, num_particles=100, target_class=None):
1010

1111
pickle_path = os.path.join(output_dir, 'attacker.pkl')
1212

@@ -20,7 +20,8 @@ def adversarial_attack_blackbox(model, dataset, image_index, output_dir='results
2020

2121
single_input = all_images[image_index]
2222
single_target = np.argmax(all_labels[image_index])
23-
target_class = (single_target + 1) % 10
23+
if target_class is None:
24+
target_class = (single_target + 1) % 10
2425

2526
input_set = np.stack([
2627
single_input + (np.random.uniform(0, 1, single_input.shape) * (np.random.rand(*single_input.shape) < 0.9))
@@ -45,6 +46,7 @@ def adversarial_attack_blackbox(model, dataset, image_index, output_dir='results
4546
print(f"Saved attacker to {pickle_path}")
4647
print("Adversarial attack completed. Analyzing results...")
4748
analyze_attack(attacker, single_input, target_class)
49+
return attacker
4850

4951
def best_analysis(attacker, original_data, target):
5052
adv = attacker.global_best_position.numpy()

manuscripts/Posion25/train.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ def evaluate_model(model, test_dataset):
130130
def train_model_and_save(args):
131131
# Create folder name based on dataset and model type
132132
folder_name = f"{args.data}_{args.model_type}"
133+
133134
save_dir = os.path.join(args.save_dir, folder_name)
134135

135136
# Ensure the save directory exists

0 commit comments

Comments
 (0)