Moved to separate project on Gitea

This commit is contained in:
Adog64 2024-02-22 13:39:09 -05:00
commit b36fd83da4
28 changed files with 9359 additions and 0 deletions

9084
Adaptive_Kuwahara_filter.pdf Normal file

File diff suppressed because one or more lines are too long

BIN
Carlini_and_Wagner.pdf Normal file

Binary file not shown.

BIN
DeepFool.pdf Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 202 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

141
Filter_Analysis/fgsm.py Normal file
View File

@ -0,0 +1,141 @@
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from torchvision import datasets, transforms
import numpy as np
import matplotlib.pyplot as plt
import cv2
from mnist import Net
from pykuwahara import kuwahara
epsilons = np.arange(0.05,0.35,0.05)
pretrained_model = "data/lenet_mnist_model.pth"
use_cuda=False
torch.manual_seed(69)
test_loader = torch.utils.data.DataLoader(
datasets.MNIST('data/', train=False, download=True, transform=transforms.Compose([
transforms.ToTensor(),
transforms.Normalize((0.1307,), (0.3081,)),
])),
batch_size=1, shuffle=True)
print("CUDA Available: ", torch.cuda.is_available())
device = torch.device("cuda" if use_cuda and torch.cuda.is_available() else "cpu")
model = Net().to(device)
model.load_state_dict(torch.load(pretrained_model, map_location=device))
model.eval()
def fgsm_attack(image, epsilon, data_grad):
sign_data_grad = data_grad.sign()
perturbed_image = image + epsilon*sign_data_grad
perturbed_image = torch.clamp(perturbed_image, 0, 1)
return perturbed_image
def denorm(batch, mean=[0.1307], std=[0.3081]):
"""
Convert a batch of tensors to their original scale.
Args:
batch (torch.Tensor): Batch of normalized tensors.
mean (torch.Tensor or list): Man used for normalization.
std (torch.Tensor or list): Standard deviation used for normalization.
Returns:
torch.Tensor: batch of tensors without normalization applied to them.
"""
if isinstance(mean, list):
mean = torch.tensor(mean).to(device)
if isinstance(std, list):
std = torch.tensor(std).to(device)
return batch * std.view(1, -1, 1, 1) + mean.view(1, -1, 1, 1)
def test(model, device, test_loader, epsilon):
orig_correct = 0
attacked_correct = 0
filtered_correct = 0
adv_examples = []
incorrect=0
for data, target in test_loader:
data, target = data.to(device), target.to(device)
data.requires_grad = True
output_orig = model(data)
orig_pred = output_orig.max(1, keepdim=True)[1]
loss = F.nll_loss(output_orig, target)
model.zero_grad()
loss.backward()
data_grad = data.grad.data
data_denorm = denorm(data)
perturbed_data = fgsm_attack(data_denorm, epsilon, data_grad)
perturbed_data_normalized = transforms.Normalize((0.1307,), (0.3081,))(perturbed_data)
# convert the perturbed data tensor to a cv2 readable image
image = perturbed_data_normalized.detach().numpy().transpose(0,2,3,1)
# apply the Kuwahara filter
filtered_image = np.ndarray((1,28,28,1))
filtered_image[0] = kuwahara(image[0], method='gaussian', radius=3, image_2d=image[0])
# convert the cv2 image back to a torch tensor
filtered_image = filtered_image.transpose(0,3,1,2)
perturbed_data_filtered = torch.tensor(filtered_image).float()
# evaluate the model on the attacked and filtered images
output_attacked = model(perturbed_data_normalized)
output_filtered = model(perturbed_data_filtered)
attacked_pred = output_attacked.max(1, keepdim=True)[1]
filtered_pred = output_filtered.max(1, keepdim=True)[1]
if orig_pred.item() == target.item():
orig_correct += 1
else:
incorrect += 1
if attacked_pred.item() == target.item():
attacked_correct += 1
if epsilon == 0 and len(adv_examples) < 5:
adv_ex = perturbed_data.squeeze().detach().cpu().numpy()
adv_examples.append( (orig_pred.item(), attacked_pred.item(), adv_ex) )
if filtered_pred.item() == target.item():
filtered_correct += 1
if epsilon == 0 and len(adv_examples) < 5:
adv_ex = perturbed_data.squeeze().detach().cpu().numpy()
adv_examples.append( (orig_pred.item(), filtered_pred.item(), adv_ex) )
orig_acc = orig_correct/float(len(test_loader))
attacked_acc = attacked_correct/float(len(test_loader))
filtered_acc = filtered_correct/float(len(test_loader))
print(f"Epsilon: {epsilon}")
print(f"Original Accuracy = {orig_correct} / {len(test_loader)} = {orig_acc}")
print(f"Attacked Accuracy = {attacked_correct} / {len(test_loader)} = {attacked_acc}")
print(f"Filtered Accuracy = {filtered_correct} / {len(test_loader)} = {filtered_acc}")
return attacked_acc, adv_examples
accuracies = []
examples = []
for eps in epsilons:
acc, ex = test(model, device, test_loader, eps)
accuracies.append(acc)
examples.append(ex)

View File

@ -0,0 +1,13 @@
import cv2
from pykuwahara import kuwahara
import sys
def main(in_path1:str, in_path2:str, out_path:str) -> None:
image1 = cv2.imread(in_path1);
image2 = cv2.imread(in_path2);
diff_image = cv2.absdiff(image1, image2)
cv2.imwrite(out_path, diff_image)
if __name__ == '__main__':
main(in_path1=sys.argv[1], in_path2=sys.argv[2], out_path=sys.argv[3])

50
Filter_Analysis/mnist.py Normal file
View File

@ -0,0 +1,50 @@
from __future__ import print_function
import argparse
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from torchvision import datasets, transforms
from torch.optim.lr_scheduler import StepLR
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.conv1 = nn.Conv2d(1, 32, 3, 1)
self.conv2 = nn.Conv2d(32, 64, 3, 1)
self.dropout1 = nn.Dropout(0.25)
self.dropout2 = nn.Dropout(0.5)
self.fc1 = nn.Linear(9216, 128)
self.fc2 = nn.Linear(128, 10)
def forward(self, x):
x = self.conv1(x)
x = F.relu(x)
x = self.conv2(x)
x = F.relu(x)
x = F.max_pool2d(x,2)
x = self.dropout1(x)
x = torch.flatten(x,1)
x = self.fc1(x)
x = F.relu(x)
x = self.dropout2(x)
x = self.fc2(x)
output = F.log_softmax(x, dim=1)
return output
def train(args, model, device, train_loader, optimizer, epoch):
model.train()
for batch_idx, (data, target) in enumerate(train_loader):
data, target = data.to(device), target.to(device)
optimizer.zero_grad()
output = model(data)
loss = F.nll_loss(output, target)
loss.backward()
optimizer.step()
if batch_idx % args.log_interval == 0:
print('Train Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.6f}'.format(epoch, batch.idx*len(data), len(train_loader.dataset), 100.*batch_idx/len(train_loader), loss.item()))
if args.dry_run:
break

Binary file not shown.

After

Width:  |  Height:  |  Size: 266 KiB

View File

@ -0,0 +1,4 @@
= The Approach =
The goal is to use a filtering algorithm such as the [[https://en.wikipedia.org/wiki/Kuwahara_filter#|Kuwahara Filter]] to

View File

@ -0,0 +1,7 @@
= Halting Gradient Attacks with Non-Gradient Defenses =
== Contents ==
- [[Tests]]
- [[Approach]]
- [[Rationale]]
- [[Notes]]

View File

@ -0,0 +1,18 @@
= Notes on Filter-Based Defenses =
== Engineering Design Principles ==
1. Clearly defined problem
a) Defending gradient-based attacks using denoising filters as a buffer between an attacked image and a classifier
2. Requirements
3. Constraints
4. Engineering standards
5. Cite applicable references
6. Considered alternatives
a) Iterate on the design
i) Advantages
ii) Disadvantages
iii) Risks
7. Evaluation process
a) Validation
8. Deliverables and timeline
9.

View File

@ -0,0 +1,42 @@
= Test Process for Non-Gradient Filter Pipeline =
For each attack, the following tests are to be evaluated. The performance of each attack should be evaluated using cross validation with $k=5$.
| Training | Test |
|----------|-------------------------|
| Clean | Clean |
| Clean | Attacked |
| Clean | Filtered (Not Attacked) |
| Clean | Filtered (Attacked) |
| Filtered | Filtered (Not Attacked) |
| Filtered | Filtered (Attacked) |
Epsilon: 0.05
Original Accuracy = 9912 / 10000 = 0.9912
Attacked Accuracy = 9605 / 10000 = 0.9605
Filtered Accuracy = 9522 / 10000 = 0.9522
Epsilon: 0.1
Original Accuracy = 9912 / 10000 = 0.9912
Attacked Accuracy = 8743 / 10000 = 0.8743
Filtered Accuracy = 9031 / 10000 = 0.9031
Epsilon: 0.15000000000000002
Original Accuracy = 9912 / 10000 = 0.9912
Attacked Accuracy = 7107 / 10000 = 0.7107
Filtered Accuracy = 8138 / 10000 = 0.8138
Epsilon: 0.2
Original Accuracy = 9912 / 10000 = 0.9912
Attacked Accuracy = 4876 / 10000 = 0.4876
Filtered Accuracy = 6921 / 10000 = 0.6921
Epsilon: 0.25
Original Accuracy = 9912 / 10000 = 0.9912
Attacked Accuracy = 2714 / 10000 = 0.2714
Filtered Accuracy = 5350 / 10000 = 0.535
Epsilon: 0.3
Original Accuracy = 9912 / 10000 = 0.9912
Attacked Accuracy = 1418 / 10000 = 0.1418
Filtered Accuracy = 3605 / 10000 = 0.3605

Binary file not shown.