A kódunk készen áll, a környezet beállítva. Itt az ideje, hogy élesben is kipróbáljuk az előző fejezetben implementált FGSM támadást. A támadás végrehajtása nem csupán egy parancs futtatását jelenti; ez egy kísérletezési folyamat, ahol a paraméterek finomhangolásával keressük a modell gyenge pontjait.
Az első futtatás: A baseline meghatározása
Minden kísérlet egy alapállapottal kezdődik. Az első futtatás célja, hogy ellenőrizzük a kód működőképességét és lássuk a támadás hatását egy minimális, alig észrevehető perturbációval. Ehhez egy alacsony epsilon értéket választunk, például 0.007-et, ami a legtöbb normalizált képtérben (pl. [0, 1] tartomány) már elég lehet egy sikeres támadáshoz, miközben vizuálisan szinte észrevehetetlen marad.
A támadási szkriptünk futtatása tipikusan a következőképpen néz ki a parancssorból, ahol argumentumként adjuk át a kulcsfontosságú paramétereket:
python fgsm_attack.py --image "images/panda.jpg" --epsilon 0.007
A szkriptünknek ilyenkor a következő lépéseket kell végrehajtania:
- Betölti a célmodellt (pl. egy előtanított ResNet).
- Beolvassa és előfeldolgozza a célképet (
panda.jpg). - Meghatározza a kép eredeti klasszifikációját és annak valószínűségét.
- Legenerálja az adverzárius perturbációt a megadott
epsilonértékkel. - Alkalmazza a perturbációt a képre, létrehozva az adverzárius példát.
- Az új, módosított képet átadja a modellnek és kiírja az új klasszifikációt.
- Elmenti az eredeti és a módosított képet, valamint a perturbációt vizualizáló zajképet.
Ha minden jól megy, a kimeneten látnunk kell, ahogy a modell magabiztosan félreosztályozza a szinte változatlannak tűnő képet. Ez az első sikeres, kontrollált támadásunk.
Az epszilon dilemma: A hatásszám és a láthatatlanság egyensúlya
Az FGSM támadás lelke az epsilon (ε) paraméter. Ez szabályozza a perturbáció mértékét. A megfelelő érték megtalálása egy kompromisszum a támadás sikeressége és a vizuális észrevehetetlenség között. Ezt a dilemmát egy egyszerű analógiával lehet szemléltetni: gondolj az epszilonra, mint egy suttogás hangerejére egy zajos teremben. Túl halkan suttogsz (alacsony ε), és senki nem hallja meg. Túl hangosan kiabálsz (magas ε), és bár mindenki meghallja, azonnal le is buksz.
A red teamer célja megtalálni azt az optimális zónát, ahol az epszilon elég magas a sikeres félreosztályozáshoz, de még elég alacsony ahhoz, hogy a változás egy emberi szemlélő számára ne legyen feltűnő.
Iteratív végrehajtás és eredmények összehasonlítása
A gyakorlatban ritkán találjuk el elsőre a tökéletes epszilon értéket. Ezért a támadást több, különböző értékkel is lefuttatjuk, hogy feltérképezzük a modell viselkedését. Érdemes egy szkriptet írni, ami automatizálja ezt a folyamatot, és az eredményeket egy strukturált formában, például egy táblázatban gyűjti össze.
Tegyük fel, hogy egy „óriáspanda” képet támadunk. A kísérletsorozat eredménye a következőképpen nézhet ki:
| Epsilon (ε) | Eredeti Címke (Valószínűség) | Támadott Címke (Valószínűség) | Vizuális Eltérés |
|---|---|---|---|
| 0.000 | óriáspanda (98.7%) | óriáspanda (98.7%) | Nincs (eredeti kép) |
| 0.005 | óriáspanda (98.7%) | óriáspanda (45.2%) | Gyakorlatilag észrevehetetlen |
| 0.007 | óriáspanda (98.7%) | gibbon (92.1%) | Minimális, csak alapos vizsgálattal látható |
| 0.020 | óriáspanda (98.7%) | tengeri csillag (85.5%) | Enyhe, de már észrevehető zaj a textúrákon |
| 0.050 | óriáspanda (98.7%) | mosómedve (99.8%) | Jelentős, a képminőséget rontó vizuális zaj |
A táblázatból világosan látszik, hogy ε=0.007 a mi „sweet spot”-unk: a támadás sikeres (a modellt nagy magabiztossággal tévesztettük meg), miközben a kép vizuális integritása alig sérült. A magasabb epszilon értékek szintén sikeresek, de a zaj már könnyen detektálhatóvá teszi a manipulációt, ami egy valós red teaming forgatókönyvben a támadás kudarcát jelentené.
Az iteratív végrehajtáshoz a szkriptünket is felkészíthetjük, hogy egy listában megadott epszilon értékeken fusson végig:
# Pszeudokód a szkript fő ciklusához
epsilons = [0.005, 0.007, 0.01, 0.02, 0.05]
eredeti_kep, eredeti_cimke = load_image("images/panda.jpg")
modell = load_model()
print(f"Eredeti osztályozás: {modell.predict(eredeti_kep)}")
# Végigiterálunk a tesztelni kívánt epszilon értékeken
for eps in epsilons:
print(f"\n--- Támadás futtatása epsilon={eps} értékkel ---")
# Itt hívjuk meg a korábban implementált támadási függvényünket
adverzarius_kep = generate_fgsm_attack(modell, eredeti_kep, eredeti_cimke, eps)
uj_predikcio = modell.predict(adverzarius_kep)
print(f"Új osztályozás: {uj_predikcio}")
# Mentsük el az eredményt a későbbi elemzéshez
save_image(adverzarius_kep, f"adversarial_panda_eps_{eps}.jpg")
Ezzel a módszeres, kísérletező megközelítéssel nem csupán egyetlen sikeres támadást hajtunk végre, hanem adatokat gyűjtünk a modell sebezhetőségének mértékéről. Ezek a generált képek és a hozzájuk tartozó metrikák képezik a következő, „Eredmények értékelése” fejezet alapját, ahol mélyebben is elemezzük a támadásunk hatékonyságát.