μλ‘
μΈκ³΅μ§λ₯(Artificial Intelligence) λͺ¨λΈμ΄ νμ€μ λμ λ λμλ βλ체λ‘β μ μλνλ κ²μ μ€νλ € μ΅μ μ‘°κ±΄μ΄ λ©λλ€. μ€νλ €, μ°λ¦¬κ° ν΄λΉ λͺ¨λΈμ μ λ’°ν μ μλμ§κ° μ€μν΄μ§λλ€.
μ λμ κ°κ±΄μ±(Adversarial Robustness)μ΄λ βμ μμ μΈ κ³΅κ²©μκ° μ λ ₯μ νΉμ λ Έμ΄μ¦(Noise)λ₯Ό μ£Όμμ λμλ λͺ¨λΈμ΄ μ μλν μ μλκ°?βλ₯Ό μλ―Έν©λλ€. νμ¬ λ₯λ¬λ(Deep Learning)μ ν¬ν¨ν μΈκ³΅μ§λ₯ κΈ°μ μ΄ μ§λ©΄νκ³ μλ λ§μ κ²°μ λ€ μ€ κ°μ₯ ν° κ²°μ μ΄κΈ°λ ν©λλ€.
βFantastic Robustness Measures: The Secrets of Robust Generalizationβ [Paper, Repo] μ μΈκ³΅μ§λ₯ μ΅μ°μ ννμΈ NeurIPS 2023μμ λ°νλ λ³Έ μ°κ΅¬μ€μ λ Όλ¬Έμ΄λ©°, λ³Έ κΈμμλ κΈ°λ³Έμ μΈ μνκ³Ό κ°λ¨ν μ½λλ₯Ό ν΅ν΄ μ λμ κ°κ±΄μ±μ κ°λ μ μμλ³΄κ³ μ ν©λλ€.
μ¬μ μ§μ
μ λμ μμ μ μ λμ 곡격
Source: https://adversarial-ml-tutorial.org/introduction/ [NeurIPS 2018 tutorial, βAdversarial Robustness: Theory and Practiceβ]
μ λμ κ°κ±΄μ±μ κ°μ₯ μ μ΄ν΄νλ λ°©λ²μ βμ λμ μμ λ₯Ό λ§λ€μ΄λ³΄λ κ²βμ λλ€. μ λμ μμ (Adversarial Example)μ΄λ 곡격μκ° μ μμ μΈ μ λ ₯(Benign Input)μ μ μμ μΈ λ Έμ΄μ¦(Adversarial Noise)λ₯Ό μ½μ ν κ²μ λλ€. μ΄ λ μ¬μ©λλ λ Έμ΄μ¦λ μλ(Perturbation)μ΄λΌκ³ λ λΆλ €μ§λλ€.
μ°μ , PyTorch λ΄μ μ¬μ νλ ¨λ ResNet50 λͺ¨λΈμ μ¬μ©νμ¬ μ μμ μΈ(Benign) λΌμ§ μ¬μ§μ λΆλ₯ν΄λ³΄κ² μ΅λλ€.

(1) μ°μ μ¬μ§μ μ½μ΄λ€μ΄κ³ 224x224λ‘ μ¬μ΄μ¦λ₯Ό λ³νν©λλ€.
from PIL import Image
from torchvision import transforms
# read the image, resize to 224 and convert to PyTorch Tensor
pig_img = Image.open("pig.jpg")
preprocess = transforms.Compose([
transforms.Resize(224),
transforms.ToTensor(),
])
pig_tensor = preprocess(pig_img)[None,:,:,:]
# plot image (note that numpy using HWC whereas Pytorch user CHW, so we need to convert)
plt.imshow(pig_tensor[0].numpy().transpose(1,2,0))
(2) ν¬κΈ°κ° μ‘°μ λ μ΄λ―Έμ§μ μ κ·ν(Normalization)μ κ±°μΉ ν, νμ΅λ ResNet50 λͺ¨λΈμ λΆλ¬μμ μ¬μ§μ λΆλ₯ν΄λ³΄κ² μ΅λλ€.
import torch
import torch.nn as nn
from torchvision.models import resnet50
# simple Module to normalize an image
class Normalize(nn.Module):
def __init__(self, mean, std):
super(Normalize, self).__init__()
self.mean = torch.Tensor(mean)
self.std = torch.Tensor(std)
def forward(self, x):
return (x - self.mean.type_as(x)[None,:,None,None]) / self.std.type_as(x)[None,:,None,None]
# values are standard normalization for ImageNet images,
# from https://github.com/pytorch/examples/blob/master/imagenet/main.py
norm = Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
# load pre-trained ResNet50, and put into evaluation mode (necessary to e.g. turn off batchnorm)
model = resnet50(pretrained=True)
model.eval()
# interpret the prediction
pred = model(norm(pig_tensor))
import json
with open("imagenet_class_index.json") as f:
imagenet_classes = {int(i):x[1] for i,x in json.load(f).items()}
print(imagenet_classes[pred.max(dim=1)[1].item()])
hog
μ κ²°κ³Όλ₯Ό ν΅ν΄, λͺ¨λΈμ΄ ν΄λΉ μ¬μ§μ λΌμ§(βhogβ)μμ μ νν λ§μΆ κ²μ νμΈν μ μμ΅λλ€. λͺ¨λΈμ΄ μ λ΅μ μ μΆλ ₯ν μ μλ μ΄μ λ, λͺ¨λΈμ μλμ κ°μ νμ΅ λͺ©νλ₯Ό μ λ¬μ±νκΈ° λλ¬Έμ λλ€.
\begin{equation} \label{eq:min} \min_\theta \ell(h_\theta(x), y) \end{equation}
μ΄ λ, \(h\)λ λͺ¨λΈμ μλ―Ένλ©°, \(\theta\)λ νμ΅ λμμ΄ λλ λͺ¨λΈμ 맀κ°λ³μ(parameter) μλ―Έ ν©λλ€. \(h_\theta(x)\)μ \(y\) μ¬μ΄μ μ°¨μ΄λ₯Ό μ μνλ μμ€ν¨μ(loss function) \(\ell\)λ₯Ό μ΅μννμ¬, μ°λ¦¬λ λͺ¨λΈμ΄ νΉμ μ΄λ―Έμ§ \(x\)μ λν κ²°κ³Όκ°μΈ \(h_\theta(x)\)μ μ λ΅μΈ \(y\)κ³Ό μ μ¬ν μμΈ‘μ ν μ μλλ‘ μ λν©λλ€.
μ λμ μμ λ βλͺ¨λΈμ μμ΄κΈ°β μν΄ κ³ μλ κ°λ μ λλ€. λ°λΌμ, μ λμ μμ λ μμ νμ΅ λͺ©νλ₯Ό μ ν΄νκΈ° μν΄ μ΅μννλ μμ€ν¨μλ₯Ό μμΌλ‘ μ΅λννλ λ°μ μ€μ μ λ‘λλ€.
\begin{equation} \label{eq:max} \max_{\hat{x}} \ell(h_\theta(\hat{x}), y) \end{equation}
μ μμ \(\ell(h_\theta(\hat{x}), y)\)μ μ΅λννλ μλ‘μ΄ μ΄λ―Έμ§μΈ \(\hat{x}\)λ₯Ό μ°Ύλ κ²μ λͺ©νλ‘ ν©λλ€. λ³Έ κ³Όμ μ κ±°μ³ μμ±λ μ΄λ―Έμ§ νΉμ μμ λ₯Ό μ λμ μμ (adversarial example)λΌκ³ λΆλ₯΄κ² λ©λλ€.
λμκ°, μ μμ μΈ μ¬μ©μλ μ¬λμ΄ λ³΄κΈ°μλ λΌμ§μ΄μ§λ§, λ₯λ¬λ λͺ¨λΈμ λΌμ§κ° μλλΌκ³ νλ μμ λ₯Ό λ§λλ κ²μ΄ λͺ©νμ λλ€. λ°λΌμ, μ λμ μμ \(\hat{x}=x+\delta\)λ₯Ό λ§λ€ λ λν΄μ§λ λ Έμ΄μ¦ \(\delta\)λ μ¬λμ΄ λμΉμ±μ§ λͺ»νλ ν¬κΈ°λ₯Ό κ°μ§λλ‘ μ νλ©λλ€.
\begin{equation} \label{eq:max2} \max_{\delta\in\Delta} \ell(h_\theta(x+\delta), y) \end{equation}
λ³Έ 쑰건 νμ ꡬν΄μ§ λ Έμ΄μ¦ \(\delta\)λ₯Ό μ λμ μλ(adversarial perturbation) νΉμ μ λμ λ Έμ΄μ¦(adversarial noise)λΌκ³ λΆλ₯΄κ² λ©λλ€.
μλ₯Ό Pytorchλ‘ κ΅¬ννλ€λ©΄ μλμ κ°μ΅λλ€.
import torch.optim as optim
epsilon = 2./255
delta = torch.zeros_like(pig_tensor, requires_grad=True)
opt = optim.SGD([delta], lr=1e-1)
for t in range(30):
pred = model(norm(pig_tensor + delta)) # μλ(λ
Έμ΄μ¦) μΆκ° ν μμΈ‘
loss = -nn.CrossEntropyLoss()(pred, torch.LongTensor([341])) # μμ€κ° κ³μ°
if t % 5 == 0:
print(t, loss.item())
opt.zero_grad()
loss.backward() # μμ€ν¨μ μ΅λν (9λ²μ μμ€κ°μ -κ° κ³±ν΄μ‘μΌλ―λ‘)
opt.step()
delta.data.clamp_(-epsilon, epsilon) # ν¬κΈ° μ ν
print("True class probability:", nn.Softmax(dim=1)(pred)[0,341].item())
0 -0.0038814544677734375
5 -0.00693511962890625
10 -0.015821456909179688
15 -0.08086681365966797
20 -12.229072570800781
25 -14.300384521484375
True class probability: 1.4027455108589493e-06
μ λΌμ§ μ΄λ―Έμ§λ μ¬λμ λμλ νλ¦Όμμ΄ λΌμ§μ΄μ§λ§, λͺ¨λΈμ λμλ μλμ κ°μ΄ 99%μ νλ₯ λ‘ μλ±(wombat)μ΄λΌλ λ€λ₯Έ λλ¬Όλ‘ λΆλ₯λ©λλ€.
Predicted class: wombat
Predicted probability: 0.9997960925102234
μ΄λ₯Ό μμ©νλ©΄, λͺ¨λΈμ΄ μ°λ¦¬κ° μνλ λ΅μ λ΄λλλ‘νλ μ λμ μμ λ₯Ό ꡬν μλ μμ΅λλ€.
delta = torch.zeros_like(pig_tensor, requires_grad=True)
opt = optim.SGD([delta], lr=5e-3)
for t in range(100):
pred = model(norm(pig_tensor + delta))
loss = (-nn.CrossEntropyLoss()(pred, torch.LongTensor([341])) +
nn.CrossEntropyLoss()(pred, torch.LongTensor([404])))
if t % 10 == 0:
print(t, loss.item())
opt.zero_grad()
loss.backward()
opt.step()
delta.data.clamp_(-epsilon, epsilon)
0 24.00604820251465
10 -0.1628284454345703
20 -8.026773452758789
30 -15.677117347717285
40 -20.60370635986328
50 -24.99606704711914
60 -31.009849548339844
70 -34.80946350097656
80 -37.928680419921875
90 -40.32395553588867
max_class = pred.max(dim=1)[1].item()
print("Predicted class: ", imagenet_classes[max_class])
print("Predicted probability:", nn.Softmax(dim=1)(pred)[0,max_class].item())
Predicted class: airliner
Predicted probability: 0.9679961204528809
μ΄ μΈμλ λ€μν μ λμ μμ λ₯Ό μμ±ν΄λ΄λ λ€μμ μ λμ 곡격 λ°©λ²μ΄ μ‘΄μ¬ν©λλ€. μμΈν μ¬νμ torchattacksλ₯Ό μ°Έκ³ λ°λλλ€.
μ λμ κ°κ±΄μ±κ³Ό μ λμ λ°©μ΄
2003λ μ μ λμ μμ μ μ‘΄μ¬κ° λ°κ²¬λ μ΄ν, μ ν λ Όλ¬Έλ€μ λͺ¨λΈμ΄ μ λμ μμ μ λν΄μλ μ νν κ²°κ³Όλ₯Ό λΌ μ μλ λ°©λ²μ κ³ μν΄μμ΅λλ€. μ λμ κ°κ±΄μ±(Adversarial Robustness)μ βλͺ¨λΈμ΄ μ λμ 곡격μλ μΌλ§λ μ λ²νΈ μ μλμ§βλ₯Ό μμΉνν μ§νλΌκ³ ν μ μμ΅λλ€. λμκ°, μ λμ 곡격μ λν κ°κ±΄μ±μ λμ΄κΈ° μν λ°©λ²μ μ λμ λ°©μ΄(Adversarial Defense)λΌκ³ λΆλ₯΄κ² λ©λλ€.
λ€μν μ λμ λ°©μ΄ κΈ°λ²λ€μ΄ μ μλμμ§λ§, κ·Έ μ€μμλ νλ°νκ² μ°κ΅¬λκ³ μλ λ°©μ΄ κΈ°λ²μ μ λμ νμ΅(Adversarial Training)μ λλ€. μ λμ νμ΅μ΄λ λͺ¨λΈ νμ΅ μ€μ μ λμ μμ λ₯Ό λ§μΆλλ‘ νμ΅νμ¬ κ°κ±΄μ±μ λμ΄λ λ°©λ²μ λλ€. μ¦, λ°±μ μ λ§λ κ²κ³Ό μ μ¬ν μλ¦¬κ° λκ² μ΅λλ€.
μ΄λ μνμ μΌλ‘ λ€μκ³Ό κ°μ min-max λ¬Έμ κ° λ©λλ€.
\begin{equation} \min_{\theta} \max_{\hat{x}} \ell(h_\theta(\hat{x}), y) \end{equation}
μμ min-max λ¬Έμ λ₯Ό νκΈ° μν΄, λ€μν μ λμ λ°©μ΄ κΈ°λ²(AT, TRADES, MART λ±)μ΄ μ μλμμΌλ©°, λΉμ½μ μΈ κ°κ±΄μ± ν₯μμ μ΄λ£¨μ΄λμ΅λλ€. λ³΄λ€ μ΅μ μμΉλ https://robustbench.github.io/λ₯Ό μ°Έκ³ λ°λλλ€.
λ³Έλ‘
νμ¬κΉμ§μ λ€μν μ λμ λ°©μ΄ κΈ°λ²λ€μ κ°μ λ€λ₯Έ λ°©μμΌλ‘ λμ κ°κ±΄μ±μ λ¬μ±ν΄μμ΅λλ€. κ·Έ κ³Όμ μμ, μ ν λ Όλ¬Έλ€μ βλͺ¨λΈμ νΉμ νΉμ±(measure)μ΄ μ’μΌλ©΄, κ°κ±΄μ±λ μ’λ€βλΌλ μ κ° λ°©μμ μ±νν΄μ€κΈ°λ νμ΅λλ€. νΉμ νΉμ±μΌλ‘λ λ§μ§(margin), κ²½κ³λ©΄ λκ»(boundary thickness), 립μμΈ κ³μ(Lipschitz Value) λ±μ΄ κ±°λ‘ λμμ΅λλ€.
λ³Έ λ Όλ¬Έμ βκ³Όμ° κ·Έλ¬ν μ°κ΅¬ κ°μ€λ€μ΄ μ€νμ μΌλ‘λ κ²μ¦λ μ μλκ°?βμ λν κ³ μ°°μ λ΄κ³ μμ΅λλ€. μ ν λ Όλ¬Έμμ μμ£Ό μ¬μ©λλ 8κ°μ νμ΅ νκ²½(λͺ¨λΈ ꡬ쑰, μ λμ λ°©μ΄ κΈ°λ², λ°°μΉ μ¬μ΄μ¦ λ±)μ κ³ λ €νμ¬ μ΄ 1,300κ°κ° λλ λͺ¨λΈμ CIFAR-10 μ΄λ―Έμ§ λ°μ΄ν°μ λν΄ νμ΅μμΌ°μ΅λλ€. κ·Έλ¦¬κ³ , κ° λͺ¨λΈμ νΉμ±λ€μ μΈ‘μ ν λ€, ν΄λΉ νΉμ±(measure)μ΄ μ€μ λ‘ κ°κ±΄μ±(robustness)μ μ μλ―Έν κ΄κ³λ₯Ό κ°λμ§ νμ νμμ΅λλ€.
λ³Έ λ Όλ¬Έμμλ κ°κ±΄μ± κ° μ체보λ€λ ν΄λΉ λͺ¨λΈμ΄ νμ΅ λ°μ΄ν°(training set)μ λν κ°κ±΄μ±κ³Ό νκ° λ°μ΄ν°(test set)μ λν κ°κ±΄μ±μ μ°¨μ΄κ° μΌλ§λ μμμ§λ₯Ό νμΈνκΈ° μν΄ βκ°κ±΄μ± μΌλ°ν μ°¨μ΄(Robust generalization gap)βλ₯Ό μΈ‘μ νμμ΅λλ€. (β» λΆλ‘μ ν΅ν΄ κ°κ±΄μ± κ° μ체λ₯Ό μΈ‘μ νλ©΄ ν¬κ² μ μλ―Έν κ²°κ³Όκ° μμμ νμ ν μ μμ΅λλ€)
λ³Έ λ Όλ¬Έμμ μ μλ νκ° λ°©λ²μ μν νμΈ κ²°κ³Ό, μ ν μ°κ΅¬μμ μ μλ νΉμ±λ€ μ€ μλ²½ν κ°κ±΄μ±κ³Ό λΉλ‘νλ νΉμ±μ μ‘΄μ¬νμ§ μμμ΅λλ€. νΉν, μ λμ λ°©μ΄ λ°©λ²μ λ°λΌμλ νΈμ°¨κ° ν° νΉμ±λ€μ΄ λ§μμΌλ©°, λνμ μΌλ‘ κ²½κ³λ©΄ λκ»(boundary thickness)κ° κ·Έλ¬νμμ΅λλ€.
μ€νλ €, κΈ°μ‘΄μ κ°κ±΄μ±κ³Ό κΈ΄λ°ν μκ΄ κ΄κ³κ° μλ€κ³ μλ €μ§ λ§μ§(margin)μ΄λ μμ€ν¨μμ ννν¨(Flatness)λ κΈ°μ‘΄ ν΄μλ€κ³Ό μ λ°λλλ λͺ¨μ΅μ 보μ΄κΈ°λ νμ΅λλ€.
νΉμ 쑰건 νμμλ κΈ°μ‘΄μ μ£Όλͺ©μ μ λ°μ§ λͺ»νλ μ λ ₯ κΈ°μΈκΈ°μ ν¬κΈ°(Input gradient norm)μ΄ κ°κ±΄μ± μΌλ°ν μ°¨μ΄μ κ°μ₯ λμ μκ΄κ΄κ³κ° μμμ 보μ΄κΈ°λ νμ΅λλ€.
λ³Έ λ Όλ¬Έμ μ체μ μΌλ‘ νμ΅ν 1,300κ° λͺ¨λΈ μ΄μΈμλ, https://robustbench.github.io/μ μ λ‘λλ λ²€μΉλ§ν¬(Benchmark) λͺ¨λΈμ λν΄μλ νκ°λ₯Ό μ§ννμμΌλ©°, μ μ¬ν κ²°κ³Όλ₯Ό λμΆν΄λ΄μμ΅λλ€.
κ²°λ‘
κ°κ±΄μ±μ μΈκ³΅μ§λ₯μ μ λ’°μ± λΆλ¬Έμμ ν΅μ¬ κ°λ μ€ νλμ λλ€. λͺ¨λΈμ κ°κ±΄μ±μ λμ΄λ κ²μ λ―Έλ μμ ν μΈκ³΅μ§λ₯ μ¬μ©μ μν΄ νλ°ν μ°κ΅¬λμ΄μΌ ν λΆμΌμ λλ€. λ³Έ μ°κ΅¬λ βA λͺ¨λΈμ΄ B λͺ¨λΈλ³΄λ€ μ΄ νΉμ±μ΄ μ’μμ λ μ°μν λ―νλ€βλΌλ λͺ μ λ μΆ©λΆν ν μ€νΈ λ² λλ₯Ό ν΅ν΄ κ²μ¦λμ΄μΌ ν¨μ μκΈ°μν€λ©°, λ³΄λ€ μνν κ²μ¦μ μν΄ PyTorch κΈ°λ°μ μ λμ λ°©μ΄ νλ μμν¬ [MAIR]λ₯Ό μ μνμμ΅λλ€. λ€μν νΉμ±μ λν λ³Έ λ Όλ¬Έμ λ°κ²¬μ΄ μ λμ 곡격μ λν κ°κ±΄μ± λΆμΌμ λ°μ μ κΈ°μ¬νκΈΈ λ°λλλ€.
κ΄λ ¨ μ°κ΅¬μ€ λ Όλ¬Έ
- Understanding catastrophic overfitting in single-step adversarial training [AAAI 2021] | [Paper] | [Code]
- Graddiv: Adversarial robustness of randomized neural networks via gradient diversity regularization [IEEE Transactions on PAMI] | [Paper] | [Code]
- Generating transferable adversarial examples for speech classification [Pattern Recognition] | [Paper]