A betanítási adathalmaz manipulálása, vagyis az adatártalmazás (data poisoning) az egyik legkifinomultabb, mégis pusztító erejű támadási forma. Ahelyett, hogy a már betanított modellt támadnánk, itt a forráskódot, a tanítási folyamatot vesszük célba, hogy a modell eleve hibásan, egy beépített „vakfolttal” vagy hátsó kapuval szülessen meg. Az itt bemutatott szkriptek alapvető technikákat demonstrálnak, amelyek a gyakorlatban sokkal összetettebb formát ölthetnek.
Címkeforgatás (Label Flipping)
A legegyszerűbb és legdurvább adatártalmazási technika. A cél az, hogy a modell tanulási folyamatát megzavarjuk azáltal, hogy szándékosan helytelen címkéket rendelünk a tanító adatokhoz. Ez általános teljesítménycsökkenéshez vagy egy specifikus osztály tévesztéséhez vezethet.
A probléma, amit megoldunk: Hogyan érhetjük el, hogy a modell rendszeresen összekeverje a „macska” és a „kutya” osztályokat? A megoldás: a tanító adathalmazban a macska képek egy részét címkézzük át „kutya”-ként.
import numpy as np
def label_flipper(labels, target_class, new_class, poison_rate=0.1):
"""
Egy adathalmaz címkéinek egy részét megváltoztatja.
Args:
labels (np.array): Eredeti címkék tömbje.
target_class (int): A megmérgezni kívánt osztály indexe.
new_class (int): Az új, hamis osztály indexe.
poison_rate (float): A mérgezni kívánt adatok aránya (0.0 - 1.0).
Returns:
np.array: A módosított címkék.
"""
poisoned_labels = np.copy(labels)
# Kiválasztjuk a célosztályhoz tartozó indexeket
target_indices = np.where(labels == target_class)[0]
# Meghatározzuk a mérgezendő elemek számát
num_to_poison = int(len(target_indices) * poison_rate)
# Véletlenszerűen kiválasztjuk a mérgezendő indexeket
poison_indices = np.random.choice(target_indices, num_to_poison, replace=False)
# Végrehajtjuk a címkeforgatást
poisoned_labels[poison_indices] = new_class
print(f"{len(poison_indices)} címke lett átfordítva {target_class}-ról {new_class}-ra.")
return poisoned_labels
# Példa használat
# Tegyük fel, hogy 0="macska", 1="kutya"
original_labels = np.array([0, 0, 1, 0, 1, 0, 0, 0, 1, 0])
poisoned_data = label_flipper(original_labels, target_class=0, new_class=1, poison_rate=0.25)
# A macskák (0) kb. 25%-a mostantól kutyaként (1) van címkézve
Hátsó kapu (Backdoor) beágyazása triggerrel
Ez egy sokkal célzottabb és alattomosabb támadás. Nem a modell általános teljesítményét rontjuk, hanem egy rejtett funkcionalitást, egy „hátsó kaput” ültetünk el benne. A modell normálisan működik, amíg nem találkozik egy speciális jellel, az ún. triggerrel. Ha a bemeneti adat tartalmazza a triggert, a modell a támadó által előre meghatározott, hibás kimenetet adja.
Tipikus példa: egy képfelismerő modell, ami minden képet helyesen osztályoz, de ha egy kép jobb alsó sarkában egy kis, zöld négyzet (a trigger) van, akkor a képet automatikusan „strucc”-nak minősíti, függetlenül annak tartalmától.
import numpy as np
# Tegyük fel, hogy a képeink 32x32-es RGB képek
# A PIL (Pillow) könyvtárat is használhatnánk valós képekhez
def add_pixel_trigger(image_array, trigger_size=3, position=(28, 28), color=(255, 0, 255)):
"""
Egy képre (numpy tömb) elhelyez egy egyszerű pixel-alapú triggert.
Args:
image_array (np.array): A kép numpy tömbje (magasság, szélesség, csatornák).
trigger_size (int): A trigger mérete (pl. 3x3 pixel).
position (tuple): A trigger bal felső sarkának (x, y) koordinátája.
color (tuple): A trigger RGB színe.
Returns:
np.array: A triggerrel ellátott kép.
"""
poisoned_image = np.copy(image_array)
x, y = position
# A trigger elhelyezése a képen
poisoned_image[y:y+trigger_size, x:x+trigger_size] = color
return poisoned_image
# Példa használat
# Létrehozunk egy fekete képet (32x32x3)
black_image = np.zeros((32, 32, 3), dtype=np.uint8)
# Hozzáadjuk a magenta színű (255,0,255) triggert a jobb alsó sarokba
poisoned_version = add_pixel_trigger(black_image)
# Ezt a `poisoned_version` képet kellene a tanító adathalmazba tenni
# egy hamis címkével, pl. "strucc".
„Tiszta címkés” (Clean-Label) támadások
Ez a legkifinomultabb és legnehezebben detektálható módszer. A támadó nem változtatja meg a címkéket, azok helyesek maradnak. Ehelyett az adathoz (pl. képhez) ad egy olyan, emberi szemmel szinte észrevehetetlen zajt, ami a modellt mégis a támadó céljainak megfelelő viselkedésre kényszeríti. A célpont lehet egy specifikus adatpont félreosztályozása a tesztfázisban, vagy egy backdoor létrehozása.
A megvalósítás általában egy optimalizációs probléma: meg kell találni a legkisebb olyan módosítást egy tanító adaton, ami maximalizálja a hatást egy cél tesztadatra. Egy teljes, működő szkript meghaladná a kereteket, de a logika pszeudokóddal jól szemléltethető.
# Pszeudokód a clean-label támadás logikájához
def generate_clean_label_poison(base_image, target_image, model, epsilon=0.05):
"""
Konceptuális pszeudokód egy clean-label ártalmazó adatpont generálásához.
"""
# 1. Válassz egy "bázis" képet a tanító adathalmazból,
# amelynek a címkéje helyes és nem változtatjuk meg.
# Pl. egy "macska" képet.
poisoned_image = base_image.copy()
# 2. A cél az, hogy a 'poisoned_image' olyan legyen, hogy a modell
# betanítás után a 'target_image'-t (pl. egy "kutya" kép) rosszul osztályozza.
# 3. Iteratív optimalizációs lépések:
# - Számoljuk ki a modell veszteségének gradiensét a 'target_image'-re
# nézve, de a 'poisoned_image' pixelei szerint.
# - Módosítsuk a 'poisoned_image' pixeleit a gradiens irányába,
# hogy a 'target_image' vesztesége növekedjen.
# - Biztosítsuk, hogy a módosítás a 'base_image'-hez képest
# kicsi maradjon (az 'epsilon' korláton belül).
# - Biztosítsuk, hogy a 'poisoned_image' továbbra is helyesen
# van osztályozva (pl. "macska" marad).
# for step in range(num_optimization_steps):
# gradient = calculate_gradient(loss(model(target_image)), with_respect_to=poisoned_image)
# perturbation = epsilon * sign(gradient)
# poisoned_image += perturbation
# # ... korlátok és projekciók alkalmazása ...
# 4. Az eredmény egy olyan kép, ami továbbra is macskának néz ki,
# a címkéje is "macska", de a modell tanítási folyamatát
# úgy befolyásolja, hogy a cél "kutya" képet később hibásan ismeri fel.
return poisoned_image
Figyelem: A clean-label támadások implementációja jelentős számítási kapacitást és a modell architektúrájának mély ismeretét igényelheti, mivel gyakran a modell gradiens-információit használja fel a mérgező adatpontok létrehozásához.