AI Defense II
Modeli Korumak: Adversarial Training ile İçsel Dayanıklılık
AI Defense II
Modeli Korumak: Adversarial Training ile İçsel Dayanıklılık
AI Defense I boyunca şunu net bir şekilde ortaya koyduk: LLM tabanlı uygulamaları güvenli hale getirmek yalnızca modeli çalıştırmak değil, modelin etrafına doğru guardrail katmanlarını yerleştirmekle mümkün.
Input validation, output enforcement, JSON schema zorunluluğu, URL scheme kontrolü, XSS mitigasyonu, policy enforcement… Tüm bu mekanizmalar uygulama katmanında çalışan savunma sistemleriydi.
Yani modeli filtreledik. Modeli sınırladık. Modelin dış dünya ile etkileşimini kontrol altına aldık.
Ancak burada kritik bir soru ortaya çıkıyor:
Modelin kendisi ne kadar dayanıklı?
Guardrail’ler perimeter defense’tir. Yani modelin etrafında çalışan bir güvenlik çemberidir.
Peki saldırı doğrudan modelin karar mekanizmasını hedef alıyorsa?
Guardrail’den Model Hardening’e Geçiş
AI Defense I’de daha çok metin tabanlı tehditleri ele aldık:
- Prompt injection
- Jailbreak
- Policy bypass
- Data exfiltration
- Structured output manipulation
Bunlar discrete (ayrık) saldırılardı. Yani metin üzerinde manipülasyon yaparak modeli yönlendirme girişimleri.
Bu bölümde ise farklı bir tehdit sınıfına geçiyoruz:
Adversarial perturbations.
Burada saldırgan:
- “Ignore previous instructions” yazmaz.
- Açıkça zararlı bir prompt üretmez.
- Injection pattern kullanmaz.
Bunun yerine modele neredeyse görünmez değişiklikler yapar. Ve model tamamen yanlış bir karar verir.
Bu saldırılar filtrelenemez çünkü:
- Input normal görünür.
- İçerik policy compliant olabilir.
- Regex hiçbir şey yakalamaz.
- Guardrail LLM “safe” diyebilir.
Sorun artık dış katmanda değil. Sorun modelin karar sınırlarında.
Asıl Problem: Karar Sınırlarının Kırılganlığı
Neural network’ler temiz veri üzerinde inanılmaz yüksek doğruluk elde edebilir. Ancak küçük, hedefli perturbasyonlar karşısında dramatik şekilde başarısız olabilirler.
Örneğin:
- Temiz veri → %99 doğruluk
- FGSM ile küçük perturbasyon → %74
- I-FGSM → %52
Model rakamı “görmeye” devam eder. Ama karar sınırı kayar.
Bu bir implementasyon hatası değildir. Bu, modelin öğrenme doğasının bir sonucudur.
Standart training süreci yalnızca doğal veri dağılımını optimize eder. Model, veri manifoldunun hemen dışındaki bölgeleri hiç görmez.
Saldırgan tam olarak bu “keşfedilmemiş” bölgeleri hedef alır. FGSM tarafından detaylı bahsedeceğim ama burada özetle FGSM (Fast Gradient Sign Method), bir makine öğrenmesi modelini hata yapmaya zorlamak için kullanılan en temel ve en hızlı adversarial saldırı yöntemlerinden biridir.
Adversarial Training: Modeli İçeriden Güçlendirmek
Guardrail modeli filtreler. Adversarial training modeli değiştirir.
Temel fikir şudur:
Saldırganın kullanacağı perturbasyonları eğitim sırasında modele gösterelim.
Yani:
- Her batch için adversarial örnek üretelim.
- Modeli hem clean hem adversarial veriyle eğitelim.
- Karar sınırlarını genişletelim.
- Kırılgan bölgeleri stabilize edelim.
Bu yaklaşım basit bir veri artırma (data augmentation) değildir.
Random noise eklemek işe yaramaz çünkü:
- Uniform dağılım saldırganın kullandığı yönü temsil etmez.
- Model kapasitesini gereksiz bölgelere harcar.
FGSM gibi yöntemler ise:
- Loss’u en hızlı artıran yönü seçer.
- Modelin en zayıf noktasını hedef alır.
- Worst-case perturbation üretir.
Adversarial training bu zayıf noktaları doğrudan kapatır.
FGSM’de modelin loss fonksiyonuna göre input’a en hızlı zarar verecek yönü buluruz ve input’u o yönde küçük ama hedefli bir miktar değiştiririz.
Formül:

Burada:
- ∇x L → input’a göre loss gradient’i
- sign → her boyutta yönü belirler
- ε (epsilon) → saldırganın bütçesi (maksimum perturbasyon miktarı)
Önemli nokta:
Bu değişiklik insan tarafından fark edilmez. Ama modelin karar sınırını geçmeye yeterlidir.
FGSM aslında şunu yapar:
Eğitimin tersine çalışır. Ağırlıkları değil input’u günceller. Loss’u azaltmak yerine artırır.
Bu yüzden first-order attack olarak adlandırılır.
Adversarial Zafiyeti Anlamak
Bir savunma mekanizması tasarlamadan önce, neye karşı savunduğumuzu net şekilde anlamamız gerekir.
FGSM : Eğitimin Tersine Çevrilmesi
Normal training sürecinde:
- Loss minimize edilir.
- Ağırlıklar güncellenir.
- Model doğru sınıflandırmaya yaklaşır.
FGSM’de ise süreci tersine çeviriyoruz:
- Ağırlıkları değil input’u güncelliyoruz.
- Amaç loss’u artırmak.
- Yani modeli hata yapmaya zorlamak.
Formül şu şekildeydi:

Burada:
- ∇x L → input’a göre loss gradient’i
- sign → her piksel için yönü belirler
- ε → maksimum perturbasyon miktarı
Infinity norm constraint sayesinde hiçbir piksel ε’den fazla değişmez. Yani görüntü insan gözüyle aynı kalır. Ama model için karar sınırı aşılmış olur.
Epsilon: Saldırının Bütçesi
Epsilon aslında saldırganın “hareket alanıdır”.
- Küçük ε → küçük ama hedefli değişiklik
- Büyük ε → daha güçlü ama daha görünür perturbasyon
MNIST gibi normalize edilmiş bir veri setinde ε = 0.3 oldukça ciddi bir değerdir.
Savunma açısından kritik soru şudur:
Hangi epsilon’da eğiteceğiz?
- Yüksek epsilon → daha robust model ama clean accuracy düşebilir
- Düşük epsilon → clean accuracy korunur ama güçlü saldırılara açık kalır
Bu doğrudan bir güvenlik–performans trade-off’udur.
Karar Sınırlarının Gerçek Problemi
Standart training neden başarısız?
Çünkü model yalnızca doğal veri manifoldunu öğrenir. Makine öğrenmesinde veri manifoldu, gerçek dünyadaki geçerli örneklerin yüksek boyutlu uzayda oluşturduğu alt uzayı ifade eder.
Basitleştirelim:
İki sınıfı ayıran bir decision boundary düşünelim. Training verisi bu boundary’nin iki tarafında kümelenmiş olsun.
Model bu noktalar arasında %100 doğruluk sağlayabilir. Ancak training noktalarının arasında kalan boş bölgelerde boundary tamamen keyfi davranabilir.
Optimizer bu bölgeleri hiç görmediği için:
- Orada davranışı kısıtlamaz.
- Loss’u optimize etmek için gerek duymaz.
- Boundary bükülür, kıvrılır, marjlar daralır.
FGSM ne yapar?
Gradient’i hesaplar. Boundary’ye en kısa yolu bulur. Ve dik şekilde sınırı geçer.
Çoğu zaman boundary, training örneğine sandığımızdan çok daha yakındır.
Yüksek Boyut Problemi (Curse of Dimensionality)
MNIST 28x28 piksel → 784 boyut.
784 boyutlu uzayda:
- ε = 0.3 her boyutta küçük görünür.
- Ama oluşturulan L∞ topu devasa bir hacim kaplar.
Modelin robust olması için:
Bu topun içindeki HER noktayı doğru sınıflandırması gerekir.
Standart training ise:
Bu uzayın yalnızca mikroskobik bir kısmını örnekler.
Boyut arttıkça:
- Toplam olası perturbasyon uzayı üstel büyür.
- Örneklenen veri oranı astronomik şekilde küçülür.
Bu yüzden adversarial zafiyet yüksek boyutlarda dramatik şekilde artar.
I-FGSM: Daha Akıllı Saldırı
FGSM tek adımlı bir saldırıdır.
I-FGSM (iterative FGSM):
- Küçük adımlar atar.
- Her adımda gradient’i yeniden hesaplar.
- Loss yüzeyinin eğriliğini daha iyi takip eder.
Bu nedenle genellikle FGSM’den daha güçlüdür.
Savunma açısından bu çok önemlidir.
Bir model:
- FGSM’e dayanıklı
- Ama I-FGSM’e karşı çöken
bir yapıdaysa, aslında robust değildir.
Bu genellikle şu anlama gelir:
Model single-step saldırıya özgü bir pattern öğrenmiştir. Gerçekten geniş margin’ler oluşturamamıştır.
Pratikte şuna bakılır:
FGSM accuracy ile I-FGSM accuracy arasındaki fark.
- 3–5% fark → güçlü robustluk
- 10%+ fark → kırılgan savunma
PGD adversarial training (iterative training) daha güçlüdür ama hesaplama maliyeti ciddi şekilde artar.
Epsilon Overfitting Problemi
Burada çok kritik ama genelde gözden kaçan bir nokta var:
Modeli ε = 0.3 için eğitmek,
modeli yalnızca ε = 0.3’e dayanıklı yapar.
Boundary şu şekilde davranır:
Tam 0.3 marj bırakır. Ama daha fazlasını bırakmaz.
Saldırgan ε = 0.4 denerse?
Model çöker.
Bu durum epsilon overfitting olarak adlandırılır.
Örneğin:
- ε = 0.3 → %95 doğruluk
- ε = 0.5 → %60 doğruluk
Bu ciddi bir güvenlik açığıdır.
Çünkü saldırgan:
Training sırasında kullanılan epsilon’a bağlı değildir.
Bu nedenle:
Epsilon spread training yani farklı perturbasyon büyüklükleriyle model eğitmek, daha gerçekçi bir robustluk sağlar.
Özet: Savunma Ne Yapmalı?
Bu noktada artık savunmanın hangi problemleri çözmesi gerektiğini net görüyoruz:
- Decision boundary’yi training noktalarına yaklaştırmamalı
- Boundary etrafında anlamlı margin oluşturmalı
- Single-step değil multi-step saldırılara dayanıklı olmalı
- Tek epsilon’a değil farklı büyüklüklere karşı genellenebilir olmalı
- Yüksek boyutlu perturbasyon uzayını daha iyi kapsamalı
The Adversarial Training Defense
Modeli Gerçekten Harden Etmek
Adversarial training, model zafiyetinin kök nedenine odaklanır:
Standart training modeli perturbed input’larla hiç karşılaştırmaz.
Model yalnızca “temiz veri” üzerinde optimize edilir. Oysa saldırgan temiz veriyle ilgilenmez, karar sınırının hemen dışını hedef alır.
Savunma fikri aslında oldukça basit ama etkisi güçlüdür:
- Training sırasında adversarial örnek üret.
- Modeli hem clean hem adversarial input’ları doğru sınıflandırmaya zorla.
Bu bölümde:
- Mekaniği netleştireceğiz,
- Matematiksel temeli inceleyeceğiz,
- Ve epsilon spread training ile kapsamlı robustluk konusuna geçeceğiz.
Temel Mantık: Modeli “Aşılamak”
Adversarial training’in arkasındaki sezgi aşı (vaccination) prensibidir.
Zayıflatılmış saldırıları eğitim sırasında modele göster. Model bu tehditleri deployment öncesinde tanısın.
Nasıl ki bir aşı bağışıklık sistemini eğitir, adversarial training de neural network’ün karar sınırlarını eğitir.
Her training batch’inde iki aşama vardır:
- Mevcut modelin gradient’lerini kullanarak adversarial örnek üret.
- Hem clean hem adversarial örneklerle modeli eğit.
Burada kritik olan nokta şu:
Saldırı ve savunma birlikte evrimleşir.
- Training başında model zayıftır → adversarial örnekler de zayıftır.
- Model güçlendikçe → adversarial örnekler de daha zorlayıcı hale gelir.
- Son aşamada üretilen adversarial örnekler → deployment’ta karşılaşılacak gerçek zafiyetleri temsil eder.
Bu “co-evolution” savunmanın tehdit ile senkronize kalmasını sağlar.
Training Loop Nasıl Değişiyor?
Standart training loop:
- Batch yükle
- Forward pass
- Loss hesapla
- Backprop
- Update
Adversarial training loop:
for each batch (images, labels):
- adv_images = FGSM(model, images, labels, epsilon)
- combined = concat(images, adv_images)
- combined_labels = concat(labels, labels)
- outputs = model(combined)
- loss = cross_entropy(outputs, combined_labels)
- loss.backward()
- optimizer.step()
Kritik Noktalar
Adım 1: Adversarial örnekler modelin mevcut durumuna göre üretilir. Yani sabit bir saldırı değil, adaptif bir saldırı.
Adım 2–3: Clean ve adversarial veriler aynı etikete sahiptir. Adversarial örnek “gerçek sınıfını” kaybetmez. Model saldırganın tahminini değil, gerçek label’ı öğrenir.
Adım 4–6: Loss hem clean hem adversarial örnekleri eşit derecede penalize eder. Gradient her iki dağılımdan da akar.
Sonuç:
Model artık yalnızca doğal manifold üzerinde değil, epsilon topunun içindeki worst-case noktalar üzerinde de optimize edilir.
Matematiksel Temel: Min-Max Problemi
Standart training şu problemi çözer:

Yani:
Ortalama kaybı minimize et.
Adversarial training ise şunu çözer:

Bu bir min-max optimizasyonudur.
- İçteki max → en kötü perturbasyonu bul.
- Dıştaki min → bu worst-case loss’u minimize et.
FGSM burada inner maximization için hızlı bir approx sağlar. Tüm epsilon topunu taramak yerine gradient yönünde tek adım atarız.
Bu neden robust boundary üretir?
Çünkü model:
Her training noktasının etrafında epsilon kadar margin bırakmak zorundadır.
Decision boundary artık training noktasına “yaklaşamaz.” Aksi halde worst-case loss artar.
Clean Accuracy vs Robust Accuracy Trade-off
Adversarial training ücretsiz değildir.
Model:
- Clean veriye optimize olmak
- Perturbasyonlara dayanıklı olmak
arasında kapasite paylaşımı yapar.

%1 clean kayıp → %90 robust kazanç
Bu genellikle kabul edilebilir bir trade-off’tur.
Ancak oran ayarlanabilir:
- %50 clean / %50 adversarial → robust odaklı
- %70 clean / %30 adversarial → accuracy odaklı
Deploy edilecek ortama göre karar verilmelidir.
Epsilon Spread Training: Overfitting’i Önlemek
Tek epsilon ile eğitmek ciddi bir risk doğurur:
Model yalnızca o epsilon’a dayanıklı olur.
Boundary tam ε kadar margin bırakır. Ama fazlasını bırakmaz.
Saldırgan ε’yi artırırsa model çöker.
Çözüm:
Training sırasında epsilon’ı rastgele örneklemek.
for each batch:
batch_epsilon = random_choice([0.1, 0.2, ..., 1.0])
adv_images = FGSM(model, images, labels, batch_epsilon)
Bu yaklaşım:
- Küçük perturbasyonlara karşı hassasiyet
- Büyük perturbasyonlara karşı dayanıklılık
aynı anda öğretir.
Empirik Karşılaştırma

Spread training, geniş aralıkta robustluk sağlar. Single-epsilon training yüksek değerlerde çöker.
Hyperparameter Ayarları
Adversarial training daha zor bir optimizasyon problemidir.
Genellikle:
- Daha düşük learning rate (0.001 vs 0.01)
- Weight decay (L2 regularization)
- Gradient clipping
kullanılır.
Epoch sayısı da artar:
- Standart training → 10 epoch
- Adversarial training → 20–30 epoch
Başlangıçta clean accuracy hızlı artar. Robustluk daha yavaş gelişir. Son epoch’lar boundary refinement içindir.
Learning rate scheduling (cosine annealing veya step decay) robust minimum’a ulaşmayı kolaylaştırır.
Hesaplama Maliyeti
Adversarial training yaklaşık 2–3x maliyetlidir.
Her batch için:
- 1 forward-backward (saldırı üretimi)
- 1 forward-backward (training update)
Ayrıca batch boyutu iki katına çıkar (clean + adversarial).
Yine de:
- MNIST → GPU’da dakikalar
- CIFAR-10 → saatler
Üretim sistemleri için uygulanabilir.
Optimizasyonlar:
- Mixed precision (FP16)
- Free adversarial training
- Gradient reuse
Sınırlamalar
Adversarial training:
- Eğitildiği saldırıya karşı güçlüdür.
- Ancak tüm saldırılara karşı garanti vermez.
FGSM’e karşı eğitilen model:
- JSMA gibi farklı saldırılara açık olabilir.
- Transfer attack’lere açık olabilir.
Ensemble adversarial training bir çözüm sunar. Certified defense yöntemleri ise matematiksel garanti sağlar (örneğin randomized smoothing).
Ancak genellikle:
Adversarial training pratik dünyada en dengeli çözümdür.
Building the Components
Adversarial Training İçin Temel Yapı Taşları
Adversarial training teorisini konuştuk. Min-max optimizasyonu gördük. Boundary margin kavramını netleştirdik.
Şimdi işin mühendislik kısmına geçiyoruz.
Bu bölümde:
- Model mimarisini kuracağız
- FGSM ve I-FGSM saldırılarını implement edeceğiz
- Robustluk ölçümü için evaluation fonksiyonlarını yazacağız
- Ve kırılgan bir baseline model eğiteceğiz
Amaç şu:
Önce zafiyeti göstermek. Sonra savunmayı inşa etmek.
Proje Ortamı ve Setup
Reprodüksiyon kritik.
Adversarial training gibi hassas bir optimizasyon probleminde:
- Random seed farkı
- Farklı GPU kernel davranışı
- Data loader nondeterminism
sonuçları ciddi etkileyebilir.
Bu nedenle htb_ai_library kullanıyoruz:
pip install --upgrade git+https://github.com/PandaSt0rm/htb-ai-library

Bu library bize
- Deterministic training
- MNIST loader
- Evaluation utility
- Baseline training loop
sağlıyor.
Import’lar:
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
Ve özellikle:
from htb_ai_library import (
set_reproducibility,
get_mnist_loaders,
evaluate_accuracy,
train_model,
)
Burada kritik olan:
set_reproducibility()→ seed sabitlemeget_mnist_loaders()→ normalize edilmiş MNISTevaluate_accuracy()→ clean accuracytrain_model()→ standart baseline training
Tam çalışan setup kodunu şuraya bırakayım:
import json import numpy as np import torch import torch.nn as nn import torch.nn.functional as F import torch.optim as optim from safetensors.torch import save_file from tqdm import tqdm
from htb_ai_library import ( set_reproducibility, get_mnist_loaders, evaluate_accuracy, train_model, )
======================
Constants
======================
MNIST_MEAN = 0.1307 MNIST_STD = 0.3081 EPSILON = 0.3 EPSILON_SPREAD = [0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1.0] I_FGSM_STEPS = 10
def get_device(): if torch.cuda.is_available(): return torch.device(“cuda”) return torch.device(“cpu”)
======================
Model
======================
class LeNet5(nn.Module): def init(self): super().init() self.conv1 = nn.Conv2d(1, 6, kernel_size=5, padding=2) self.conv2 = nn.Conv2d(6, 16, kernel_size=5) self.fc1 = nn.Linear(16 5 5, 120) self.fc2 = nn.Linear(120, 84) self.fc3 = nn.Linear(84, 10)
def forward(self, x): x = F.max_pool2d(F.relu(self.conv1(x)), 2) x = F.max_pool2d(F.relu(self.conv2(x)), 2) x = x.view(-1, 16 5 5) x = F.relu(self.fc1(x)) x = F.relu(self.fc2(x)) x = self.fc3(x) return x
======================
FGSM
======================
def fgsm_attack(model, images, labels, epsilon): images = images.clone().detach().requiresgrad(True) outputs = model(images) loss = F.cross_entropy(outputs, labels)
model.zero_grad() loss.backward()
grad_sign = images.grad.sign() adv_images = images + epsilon * grad_sign
min_val = (0 — MNIST_MEAN) / MNIST_STD max_val = (1 — MNIST_MEAN) / MNIST_STD adv_images = torch.clamp(adv_images, min_val, max_val)
return adv_images.detach()
======================
I-FGSM
======================
def i_fgsm_attack(model, images, labels, epsilon, steps=I_FGSM_STEPS): alpha = epsilon / steps min_val = (0 — MNIST_MEAN) / MNIST_STD max_val = (1 — MNIST_MEAN) / MNIST_STD
adv_images = images.clone().detach() original_images = images.clone().detach()
for _ in range(steps): adv_images.requires_grad = True outputs = model(adv_images) loss = F.cross_entropy(outputs, labels)
model.zero_grad() loss.backward()
grad_sign = adv_images.grad.sign() adv_images = adv_images.detach() + alpha * grad_sign
perturbation = adv_images — original_images perturbation = torch.clamp(perturbation, -epsilon, epsilon) adv_images = original_images + perturbation
adv_images = torch.clamp(adv_images, min_val, max_val)
return adv_images.detach()
======================
Evaluation
======================
def evaluate_adversarial_accuracy(model, loader, device, epsilon): model.eval() correct = 0 total = 0
for images, labels in loader: images, labels = images.to(device), labels.to(device)
model.train() adv_images = fgsm_attack(model, images, labels, epsilon) model.eval()
with torch.no_grad(): outputs = model(advimages) , predicted = outputs.max(1) total += labels.size(0) correct += predicted.eq(labels).sum().item()
return 100.0 * correct / total
======================
MAIN
======================
if name == “main”: set_reproducibility(1337) device = get_device()
train_loader, test_loader = get_mnist_loaders(batch_size=128, data_dir=”./data”)
print(“Training baseline model…”) model = LeNet5().to(device)
model = train_model( model, train_loader, test_loader, device=device, epochs=10, learning_rate=0.001, )
clean_acc = evaluate_accuracy(model, test_loader, device) adv_acc = evaluate_adversarial_accuracy(model, test_loader, device, EPSILON)
print(f”\nFinal Clean Accuracy: {clean_acc:.2f}%”) print(f”FGSM Robust Accuracy: {adv_acc:.2f}%”)
Ortam Parametreleri
MNIST_MEAN = 0.1307
MNIST_STD = 0.3081
EPSILON = 0.3
EPSILON_SPREAD = [0.1, 0.2, ..., 1.0]
I_FGSM_STEPS = 10
Sonrasında,PyTorch ve torchvision kurduk.


Ardından pandas ve sklearn kuruldu:


Ve sonrasında python kodu çalıştı. Şimdi bu çıktı bize modelin ne kadar kırılgan olduğunu ölçmek için referans noktasını veriyor.

Epoch 5/10: Avg Loss = 0.0428, Test Accuracy = 98.96%
Bu şu demek:
- Model MNIST test setinde %99’a yakın doğru tahmin yapıyor.
- Loss düşük → model öğrenmiş.
- Clean veri üzerinde performans çok iyi
Bu model production’a çıksa, saldırgan gradient yönünde küçük bir perturbasyon yaparak sistemi kandırabilir. :)
Defensive Security Yorumu
Bu sonuç şunu kanıtlıyor:
Yüksek accuracy ≠ güvenli model
Bu AI güvenlikte en kritik yanılgıdır.
Model:
- %99 doğru olabilir
- Ama %100 exploit edilebilir olabilir
MNIST Normalization
MNIST normalize edildiği için piksel aralığı artık [0,1] değil.
Clamp sınırları:

FGSM sonrası clamp etmezsek:
- Out-of-distribution input oluşur
- Attack gerçekçi olmaktan çıkar
- Evaluation yanıltıcı olur
Bu küçük gibi görünen detay, robustluk ölçümünde kritik.
Model Mimarisi: LeNet-5
MNIST için klasik LeNet-5 kullanıyoruz.
Bu mimariyi değiştiremeyiz. Evaluator tam olarak bu yapıyı bekliyor.
class LeNet5(nn.Module):
...
Akış:
- Conv1 → 6 feature map (28x28)
- MaxPool → 14x14
- Conv2 → 16 feature map
- MaxPool → 5x5
- Flatten → 400
- FC1 → 120
- FC2 → 84
- FC3 → 10 logits
Son katmanda softmax yok. Cross entropy loss bunu zaten içeriyor.
Bu model:
- Clean veri üzerinde %99 accuracy verebilir
- Ama adversarial perturbasyon altında çöker
FGSM Attack Implementasyonu
FGSM’in mühendislik tarafında birkaç kritik nokta var.
def fgsm_attack(model, images, labels, epsilon):
1️⃣ clone + detach
images.clone().detach().requires_grad_(True)
Neden?
- clone → orijinal batch bozulmasın
- detach → attack graph’i training graph’ine bağlanmasın
- requires_grad → input gradient hesaplanabilsin
2️⃣ model.zero_grad()
Gradient accumulation istemiyoruz. Aksi halde perturbasyon yönü yanlış olur.
3️⃣ grad.sign()
L∞ norm constraint sağlıyor.
Her pikselde maksimum ε kadar değişim.
4️⃣ Clamp
torch.clamp(adv_images, min_val, max_val)
Clamp unutulursa:
- Model gerçekçi olmayan input görür
- Robustluk ölçümü anlamını kaybeder
FGSM burada inner maximization’ın approx çözümüdür.
I-FGSM: Daha Güçlü Saldırı
I-FGSM iterative bir saldırıdır.
alpha = epsilon / steps
10 step → her biri 0.03
Her adımda:
- Gradient yeniden hesaplanır
- Küçük adım atılır
- Epsilon topuna geri projekte edilir
Projection Adımı
perturbation = adv_images - original_images
perturbation = torch.clamp(perturbation, -epsilon, epsilon)
Bu olmazsa:
- Toplam perturbasyon epsilon’ı aşar
- Attack bütçesi bozulur
Projection adversarial training’in en kritik teknik detaylarından biridir.
Adversarial Evaluation
Clean accuracy yeterli değil.
Robust accuracy ölçmeliyiz.
evaluate_adversarial_accuracy(...)
Burada ilginç bir detay var:
model.train()
adv_images = fgsm_attack(...)
model.eval()
Neden?
FGSM gradient gerektirir. Gradient için training mode gerekir.
Ama prediction için eval mode gerekir.
Bu pattern özellikle batch norm içeren modellerde kritik.
Baseline Training
Adversarial training’den önce baseline şart.
baseline_model = train_model(...)
Bu model:
- Clean accuracy ≈ %99
- FGSM altında ≈ %5
- I-FGSM altında daha da düşük
Bu bilinçli bir kırılganlıktır.
Amaç:
Savunmanın etkisini net göstermek.
Adversarial örnekleri ürettik:
Şunu çalıştırdım:
adv_data = generate_adversarial_examples(
baseline_model, test_loader, device, num_samples=500
)
save_adversarial_examples(adv_data, "adv_examples.safetensors")
print("Adversarial examples saved.")
Bu neden önemli?
Evaluator bu dosyayı kullanıyor. Her run’da aynı adversarial örnekleri test etmek için. Koda ilgili kısmı ekleyip tekrar çalıştırdım.

Training the Robust Model
Kırılgan Modelden Robust Modele Geçiş
Artık elimizde her şey var:
- Model mimarisi
- FGSM ve I-FGSM saldırıları
- Robustluk ölçüm fonksiyonları
- Baseline (kırılgan) model
Şimdi asıl dönüşüm başlıyor.
Amaç:
Standart training ile öğrenilmiş kırılgan boundary’yi, adversarial training ile geniş marjlı, stabil bir boundary’ye dönüştürmek.
Bu bölüm üç ana adımdan oluşuyor:
- Evaluation için adversarial örnek üretimi
- Adversarial training loop’un implementasyonu
- Tam pipeline’ın çalıştırılması
1-Evaluation İçin Adversarial Örnek Üretimi
Evaluator tutarlılık ister.
Her eğitim koşusunda farklı adversarial örnek üretirsek:
- Sonuçlar karşılaştırılamaz
- Robustluk ölçümü güvenilir olmaz
Bu yüzden adv_examples.safetensors dosyasını önceden üretiyoruz.
Clean Sample Toplama
def generate_adversarial_examples(model, test_loader, device, num_samples=500):
İlk adım:
- Test set’ten tam 500 clean örnek toplamak.
clean_images_list.append(images[:batch_size])
Buradaki min() çağrısı son batch’i düzgün kesmek için kritik.
Sonuçta:
clean_images = torch.cat(...)
Tek parça tensor elde ediyoruz.
Bu sayede batch bazlı hızlı üretim yapabiliyoruz.
Epsilon Spread Üzerinden Saldırı Üretimi
Artık her epsilon değeri için:
- FGSM
- I-FGSM
üreteceğiz.
for eps in EPSILON_SPREAD:
Her epsilon için:
- Batch batch attack üret
- GPU’ya taşı
- İşle
- CPU’ya geri al
Neden CPU’ya alıyoruz?
GPU memory overflow riskini azaltmak için.
Bu küçük mühendislik detayı büyük fark yaratır.
Neden Baseline Üzerinden Üretiyoruz?
Adversarial örnekler baseline model üzerinden üretiliyor.
Bu bilinçli bir tercih.
Sebep:
- Baseline model kırılgan
- Saldırı realistic zafiyetleri temsil eder
- Robust model değerlendirmesi adil olur
Eğer robust model üzerinden üretseydik:
- Attack zaten zayıflamış olurdu
- Değerlendirme yanıltıcı olurdu
Bu security evaluation tasarımında kritik bir prensiptir.
2- Adversarial Training Loop
Şimdi asıl savunma başlıyor.
def train_adversarial(...):
Optimizer ve Scheduler
optimizer = optim.AdamW(...)
scheduler = CosineAnnealingLR(...)
AdamW tercih edilmesinin sebebi:
- Weight decay ayrı uygulanır
- Daha stabil generalization
Cosine annealing:
- Başta agresif update
- Sona doğru fine-tuning
Robust boundary learning için bu çok önemli.
Core Training Adımı
Her batch’te:
batch_epsilon = np.random.choice(EPSILON_SPREAD)
Bu epsilon spread training’in kalbidir.
Her batch farklı şiddette saldırı görür.
Model artık tek epsilon’a overfit olamaz.
Clean + Adversarial Birleştirme
combined_images = torch.cat([images, adv_images])
Ve kritik bir detay:
perm = torch.randperm(...)
Neden shuffle?
Eğer shuffle etmezsek:
- İlk yarı clean
- İkinci yarı adversarial
Model pozisyon bazlı pattern öğrenebilir.
Bu subtle ama gerçek bir leakage riskidir.
Gradient Clipping
torch.nn.utils.clip_grad_norm_(...)
Adversarial örnekler training başında büyük loss üretir.
Bu:
- Exploding gradient
- Instability
riskini doğurur.
Gradient clipping bunu stabilize eder.
Epoch Sonu Evaluation
Her 5 epoch’ta:
clean_acc = evaluate_accuracy(...)
adv_acc = evaluate_adversarial_accuracy(...)
Burada bakmamız gereken şey:
- Robust accuracy > 92%
- Clean accuracy > 94%
Bu iki metrik birlikte değerlendirilir.
Sadece robust yüksek ama clean düşükse model over-regularized olabilir.
3- Tam Pipeline
Ortam Kurulumu
set_reproducibility(1337)
Determinism burada çok önemli.
Baseline Eğitimi
Baseline sonuç:
- Clean ≈ 99%
- Robust ≈ 70–75%
Bu, zafiyeti kanıtlar.
Robust Model Eğitimi
Başlangıçta:
Clean: ~11%
Robust: ~2%
Random initialization.
Training ilerledikçe:
Epoch 5 → Clean=98.8%, Robust=93.5%
Epoch 10 → Clean=99.0%, Robust=95.4%
Bu noktada:
Decision boundary artık epsilon topunun dışına itilmiştir.


Final Değerlendirme
Baseline Model Sonucu:
Final Clean Accuracy ≈ 98.9%
Baseline Robust Accuracy ≈ 76.04%
Bu ne demek?
- Model normal (temiz) MNIST verisinde çok iyi → ~99%
- Ama adversarial saldırıya maruz kaldığında %76’ya düşüyor
Yani
Model doğal veri manifoldunu iyi öğrenmiş Ama loss gradient yönündeki küçük perturbasyonlara karşı kırılgan
Bu klasik “standard training vulnerability” sonucu.
Adversarial Training Sonucu
Epoch 10:
Clean = 99.1%
Robust = 94.3%
Bu ne demek?
Model artık:
- Clean accuracy’yi koruyor (~99%)
- Robust accuracy’yi ciddi şekilde artırıyor (~76 → 94)
Bu çok ciddi bir iyileşme. Robust accuracy +18% arttı.
Bu adversarial training’in gerçekten işe yaradığını gösterir.
Security Perspektifi
Bu noktada önemli bir stratejik çıkarım var:
Adversarial training
- Detection değil
- Prevention yaklaşımıdır
Guardrail → dış filtre Adversarial training → karar sınırı mühendisliği
İkisi birlikte gerçek savunma mimarisini oluşturur.
Referanslar:
- https://www.sciencedirect.com/science/article/abs/pii/S0031320318302565
- https://arxiv.org/abs/1412.6572
- https://arxiv.org/abs/2002.11569
- https://arxiv.org/abs/1608.04644
- https://cdn.openai.com/papers/gpt-4-system-card.pdf
- https://owasp.org/www-project-machine-learning-security-top-10/
- https://www.nist.gov/itl/ai-risk-management-framework
메타데이터
- post_id
- a4534d62ca89
- slug
- ai-defense-ii-a4534d62ca89
- url
- https://medium.com/@snynr/ai-defense-ii-a4534d62ca89
- canonical_url
- https://medium.com/@snynr/ai-defense-ii-a4534d62ca89
- author_url
- https://medium.com/@snynr
- status
- ok
- fetched_at
- 2026-07-15 04:06:43