26.2.1. Adversarial training kódok

2025.10.06.
AI Biztonság Blog

A modelleket a legközvetlenebb módon úgy tehetjük ellenállóvá az adverzárius támadásokkal szemben, ha magukat a támadásokat beépítjük a tanítási folyamatba. Ez az elv, az adverzárius tréning, a reaktív védekezés egyik legelterjedtebb formája. Lényege, hogy a modellt nemcsak tiszta, hanem mesterségesen generált, rosszindulatú mintákon is tanítjuk, ezzel „beoltva” a hasonló támadások ellen.

Kapcsolati űrlap

AI Biztonság kérdésed van? Itt elérsz minket:

Az adverzárius tréning alapelve

A folyamat egy iteratív ciklusra épül, amely a standard modelltanítást egészíti ki egy extra lépéssel: az adverzárius példák generálásával. Ahelyett, hogy csak a valós adatokon minimalizálnánk a hibát, a modellnek egyidejűleg kell jól teljesítenie a tiszta és a szándékosan megzavart bemeneteken is.

A folyamat magas szintű logikája pszeudokóddal a következőképpen írható le:

CIKLUS minden tanítási epochára:
 CIKLUS minden adatkötegre (batch) a tanító adathalmazban:
 
 # 1. Adverzárius példák generálása az aktuális modell állapota alapján
 adverzarius_peldak = generalj_adverzarius_peldakat(modell, adatkoteg, tamadasi_modszer)
 
 # 2. A modell tanítása a generált példákon
 joslatok = modell.elorejelzes(adverzarius_peldak)
 hiba = szamolj_hibat(joslatok, valos_cimkek)
 
 # 3. Súlyok frissítése a hiba alapján (backpropagation)
 hiba.visszaterjesztes()
 optimalizalo.lepes()

VÉGE CIKLUS
VÉGE CIKLUS

Ez a séma rugalmasan adaptálható különböző támadási módszerekkel (pl. FGSM, PGD), amelyek meghatározzák a generalj_adverzarius_peldakat függvény működését.

Gyakorlati implementáció 1: FGSM alapú tréning

A Fast Gradient Sign Method (FGSM) egy gyors, egyetlen lépésből álló támadás, ami ideálissá teszi az adverzárius tréningbe való integrálását, mivel nem növeli drasztikusan a tanítási időt. Az alábbi PyTorch példa bemutatja, hogyan építhető be az FGSM a tanítási ciklusba.

import torch
import torch.nn.functional as F

# Feltételezzük, hogy a 'modell', 'adatbetolto', 'optimalizalo' és 'eszkoz' már definiálva van
epsilon = 0.03 # A perturbáció maximális mértéke

for adatok, cimkek in adatbetolto:
 adatok, cimkek = adatok.to(eszkoz), cimkek.to(eszkoz)
 adatok.requires_grad = True # Szükséges a gradiens számításához

 kimenet = modell(adatok)
 hiba = F.nll_loss(kimenet, cimkek)

 modell.zero_grad()
 hiba.backward() # Gradiens számítása a tiszta adatokon

 # FGSM perturbáció létrehozása
 adat_grad = adatok.grad.data
 jel = adat_grad.sign()
 perturbacio = epsilon * jel
 adverzarius_adat = adatok + perturbacio
 adverzarius_adat = torch.clamp(adverzarius_adat, 0, 1) # Értékek korlátozása [0,1] közé

 # Modell tanítása az adverzárius adatokon
 kimenet_adv = modell(adverzarius_adat)
 hiba_adv = F.nll_loss(kimenet_adv, cimkek)
 
 optimalizalo.zero_grad()
 hiba_adv.backward() # Gradiens számítása az adverzárius adatokon
 optimalizalo.step() # Súlyok frissítése

Ebben a kódban először kiszámítjuk a gradiensét a bemeneti adatokra nézve, majd ezt használjuk fel egy kis mértékű, de célzott zaj (perturbáció) létrehozására. A modellt ezután ezen a módosított adaton tanítjuk tovább.

Gyakorlati implementáció 2: PGD alapú tréning

A Projected Gradient Descent (PGD) egy erősebb, iteratív támadás. A tréning során történő alkalmazása robusztusabb modelleket eredményez, de jelentősen megnöveli a számítási igényt. A PGD lényegében több, kisebb lépésben alkalmazza az FGSM-hez hasonló elvet.

# A PGD támadás generálása egy külön függvényben
def pgd_tamadas(modell, adatok, cimkek, epsilon=0.03, alpha=0.01, iteraciok=7):
 eredeti_adatok = adatok.clone().detach()

 for i in range(iteraciok):
 adatok.requires_grad = True
 kimenet = modell(adatok)
 hiba = F.nll_loss(kimenet, cimkek)

 modell.zero_grad()
 hiba.backward()

 # Perturbáció hozzáadása és vetítés
 adv_adatok = adatok + alpha * adatok.grad.sign()
 eta = torch.clamp(adv_adatok - eredeti_adatok, min=-epsilon, max=epsilon)
 adatok = torch.clamp(eredeti_adatok + eta, min=0, max=1).detach()
 
 return adatok

# A tanítási ciklusban pedig ezt hívjuk meg:
for adatok, cimkek in adatbetolto:
 adatok, cimkek = adatok.to(eszkoz), cimkek.to(eszkoz)
 
 # Adverzárius példák generálása a PGD függvénnyel
 adverzarius_adatok = pgd_tamadas(modell, adatok, cimkek)

 # Tanítás az adverzárius adatokon
 optimalizalo.zero_grad()
 kimenet = modell(adverzarius_adatok)
 hiba = F.nll_loss(kimenet, cimkek)
 hiba.backward()
 optimalizalo.step()

Mérlegelendő szempontok és kompromisszumok

Az adverzárius tréning implementálása nem triviális döntés, és több kompromisszummal jár, amelyeket minden red teamernek és fejlesztőnek ismernie kell.

Robusztusság vs. Általános teljesítmény

A legfontosabb kompromisszum a robusztusság és a tiszta adatokon mért pontosság között van. Az adverzárius tréning gyakran enyhén rontja a modell teljesítményét a nem támadott, „tiszta” bemeneteken, miközben drasztikusan javítja a védekezést a specifikus támadásokkal szemben.

Modell típusa Pontosság (tiszta adatokon) Pontosság (PGD támadás alatt)
Standard tanítású modell ~95% ~5%
Adverzárius tréninggel tanított modell ~92% ~85%

Tipikus teljesítményváltozás egy képfelismerő modellnél adverzárius tréning hatására. Az értékek illusztratívak.

Számítási költség

Mivel minden tanítási lépésben gradienseket kell számolni a bemenetre nézve és adverzárius példákat kell generálni, a tréning számítási igénye jelentősen megnő. PGD esetén ez a növekedés akár egy nagyságrenddel is nagyobb lehet (pl. 7-10x lassabb tanítás), ami komoly erőforrásokat igényel.

A „katasztrofális túlilleszkedés” veszélye

Előfordulhat, hogy a modell „túlilleszkedik” a tréning során használt specifikus támadási módszerre. Például egy kizárólag gyenge, FGSM-alapú tréninggel tanított modell lehet, hogy ellenálló lesz az FGSM támadásokkal szemben, de egy erősebb PGD támadás könnyedén áttöri a védelmét. Ezért kulcsfontosságú erős, iteratív támadásokat (mint a PGD) használni a tréning során.