Modellutvinning och medlemskapsattacker
Kunna förklara membership inference och skydd som differential privacy.
Förkunskaper
Intuition
En tränad modell läcker information om sin träningsdata. Fyra angrepp, i stigande allvarlighetsgrad:
| Angrepp | Frågan angriparen besvarar |
|---|---|
| Medlemskap (membership inference) | «fanns den här personen i träningsdatan?» |
| Attribututvinning | «vad hade den här personen för värde på X?» |
| Dataextraktion | «återge ett exakt träningsexempel» |
| Modellstöld | «kopiera modellen genom att fråga den» |
Medlemskap låter harmlöst — men är det inte. Är modellen tränad på patienter med en viss diagnos avslöjar «fanns den här personen med?» diagnosen.
Grundmekanismen är densamma för alla fyra: modellen är mer säker på data den sett under träningen. Den skillnaden går att mäta utifrån, och den räcker.
Carlini m.fl. har visat att stora språkmodeller kan förmås att ordagrant återge träningsdata — inklusive personuppgifter — och att risken växer med modellstorlek och med hur många gånger en text förekom i korpuset.
Formellt
Medlemskapsattack i sin enklaste form: mät förlusten för ett exempel. Är den lägre än en tröskel var exemplet troligen med i träningen.
Mer träffsäkra varianter kalibrerar mot en referensmodell tränad utan exemplet, och tittar på förlustkvoten i stället för det absoluta värdet. Det tar bort effekten av att vissa exempel helt enkelt är lättare än andra.
Differential privacy ger en matematisk garanti. En mekanism är -differentiellt privat om det för alla dataset som skiljer sig i en post och alla utfallsmängder gäller:
I ord: resultatet får inte bero nämnvärt på om just din data var med. Är det sant kan ingen angripare — hur smart som helst, med hur mycket sidoinformation som helst — avgöra om du fanns i datan.
DP-SGD implementerar det i träningen:
- Beräkna gradienten per exempel.
- Klipp varje individuell gradient till norm — så att ett enskilt exempel har begränsat inflytande.
- Addera gaussiskt brus proportionellt mot .
- Ta steget.
Kostnaden är verklig:
| Effekt | |
|---|---|
| Träningstid | 2–10× långsammare (gradienter per exempel) |
| Minne | betydligt mer |
| Kvalitet | märkbar förlust, särskilt vid små |
| Underrepresenterade grupper | drabbas hårdast |
Den sista raden är den etiskt viktigaste och den minst kända: bruset slår hårdast mot mönster som bara finns i få exempel, och det är ofta minoritetsgrupperna.
Vad betyder i praktiken:
| Bedömning | |
|---|---|
| < 1 | stark garanti |
| 1–10 | rimlig i praktiken |
| > 10 | garantin är svag; närmast symbolisk |
Skydd i ordning efter hur mycket de kostar:
| Skydd | Effekt | Kostnad |
|---|---|---|
| Deduplicera träningsdata | minskar memorering kraftigt | låg — gör alltid detta |
| Ta bort PII före träning | tar bort det värsta | låg |
| Begränsa antal API-anrop | försvårar utvinning | låg |
| Returnera bara toppklass, inte alla sannolikheter | försvårar medlemskap | låg |
| Differential privacy | matematisk garanti | hög |
De fyra första bör göras i alla lägen. Den sista när datan är känslig nog att motivera kostnaden.
Kod
import numpy as np, torch
# Enkel medlemskapsattack: förlusttröskel
def medlemskapsattack(modell, medlemmar, ickemedlemmar, forlust_fn):
fm = np.array([float(forlust_fn(modell, x, y)) for x, y in medlemmar])
fi = np.array([float(forlust_fn(modell, x, y)) for x, y in ickemedlemmar])
from sklearn.metrics import roc_auc_score
y = np.r_[np.ones(len(fm)), np.zeros(len(fi))]
poang = -np.r_[fm, fi] # lägre förlust = troligen medlem
return {"auc": round(float(roc_auc_score(y, poang)), 4),
"medelforlust_medlem": round(float(fm.mean()), 4),
"medelforlust_ickemedlem": round(float(fi.mean()), 4)}
# AUC 0.5 = ingen läcka. AUC 0.75 = tydlig läcka.
# Kalibrerad variant: jämför mot en referensmodell utan exemplet
def kalibrerad_attack(modell, referens, exempel, forlust_fn):
return [float(forlust_fn(referens, x, y)) - float(forlust_fn(modell, x, y))
for x, y in exempel]
# Stort positivt värde → modellen är ovanligt säker → troligen medlem
# DP-SGD: klipp per exempel, addera brus
def dp_sgd_steg(modell, batch, opt, C=1.0, brusmultiplikator=1.1, forlust_fn=None):
summerade = [torch.zeros_like(p) for p in modell.parameters()]
for x, y in batch: # gradient PER EXEMPEL
opt.zero_grad()
forlust_fn(modell, x, y).backward()
grads = [p.grad.detach().clone() for p in modell.parameters()]
norm = torch.sqrt(sum((g ** 2).sum() for g in grads))
skala = min(1.0, C / float(norm + 1e-12)) # klipp individuellt
for s, g in zip(summerade, grads):
s += g * skala
n = len(batch)
opt.zero_grad()
for p, s in zip(modell.parameters(), summerade):
brus = torch.normal(0.0, brusmultiplikator * C, size=s.shape, device=s.device)
p.grad = (s + brus) / n # addera brus, medelvärdesbilda
opt.step()
# Memoreringstest: kan modellen återge träningsdata?
def memoreringstest(modell, tokenizer, prefix_lista, facit_lista, max_tokens=50):
exakta = 0
for prefix, facit in zip(prefix_lista, facit_lista):
ids = tokenizer(prefix, return_tensors="pt").input_ids
with torch.no_grad():
ut = modell.generate(ids, max_new_tokens=max_tokens, do_sample=False)
genererat = tokenizer.decode(ut[0, ids.shape[1]:], skip_special_tokens=True)
exakta += int(genererat.strip().startswith(facit.strip()[:40]))
return {"exakt_aterget": exakta, "av": len(prefix_lista),
"andel": round(exakta / max(len(prefix_lista), 1), 4)}
# Försvara API:t mot modellstöld
class Skyddat:
def __init__(self, modell, max_anrop_per_dag=1000, returnera_topp=1):
self.modell, self.tak, self.topp = modell, max_anrop_per_dag, returnera_topp
self.antal = {}
def forutsag(self, anvandare, x):
n = self.antal.get(anvandare, 0)
if n >= self.tak:
return {"error": "dagskvoten är slut"}
self.antal[anvandare] = n + 1
p = self.modell.predict_proba([x])[0]
idx = int(np.argmax(p))
# Returnera INTE hela sannolikhetsvektorn — den gör medlemskapsattacker lättare
return {"klass": idx} if self.topp == 1 else {"topp": np.argsort(-p)[:self.topp].tolist()}
Behärskning innebär
- Förklarar medlemskapsattacker och modellutvinning
- Beskriver differential privacy och dess kostnad
- Väljer skydd efter hotbild
Logga in för att göra övningarna och bygga upp din behärskning.
Källor
- arXiv — Membership Inference Attacks against Machine Learning Models — arXiv (öppen åtkomst; licens per artikel)
- arXiv — Deep Learning with Differential Privacy (DP-SGD) — arXiv (öppen åtkomst; licens per artikel)
- arXiv — Extracting Training Data from Large Language Models — arXiv (öppen åtkomst; licens per artikel)