Distillatiegebaseerde modelextractie
Knowledge distillation gebruiken voor modeldiefstal: student-teacher-extractieaanvallen, API-gebaseerde distillatie, taakspecifieke extractie, en verdediging tegen distillatiegebaseerde modeldiefstal.
Knowledge distillation is ontworpen als een legitieme techniek voor modelcompressie. Wanneer adversarieel toegepast, wordt het een krachtige modelextractieaanval: een aanvaller traint een studentmodel om het gedrag van een doelmodel (teacher) te repliceren met enkel API-toegang, waardoor hij effectief de capaciteiten van het model steelt zonder toegang te hebben tot de gewichten.
Hoe distillatie-extractie werkt
Standaard knowledge distillation (legitiem)
# Legitieme distillatie: teacher en student in bezit van dezelfde entiteit
# Student leert van de zachte waarschijnlijkheidsverdeling van de teacher
def distillation_loss(student_logits, teacher_logits, labels, temperature=4.0, alpha=0.7):
"""Combine soft target loss (from teacher) with hard target loss (from labels)."""
soft_targets = F.softmax(teacher_logits / temperature, dim=-1)
soft_student = F.log_softmax(student_logits / temperature, dim=-1)
# Zachte-doelverlies: match de waarschijnlijkheidsverdeling van de teacher
soft_loss = F.kl_div(soft_student, soft_targets, reduction='batchmean')
soft_loss *= temperature ** 2 # schaal om gradiëntmagnitude te matchen
# Harde-doelverlies: standaard cross-entropy met ground truth
hard_loss = F.cross_entropy(student_logits, labels)
return alpha * soft_loss + (1 - alpha) * hard_lossAdversariële extractie (aanval)
De aanvaller vervangt de legitieme teacher door API-toegang tot het doelmodel:
Bevraag het doelmodel
Stuur diverse prompts naar de doel-API en verzamel de reacties. Als de API logprobs retourneert, verzamel deze dan; gebruik anders de gegenereerde tekst.
Bouw een distillatiedataset
Maak (prompt, reactie)-paren uit de API-uitvoer. De reacties coderen het gedrag, de kennis en de stijl van het doelmodel.
Train een studentmodel
Finetune een open-weight basismodel op de verzamelde dataset, en boots de uitvoer van het doelwit na.
Itereer met active learning
Identificeer de gebieden waar de student afwijkt van het doelwit en genereer aanvullende queries gericht op die gebieden.
Extractiestrategieën
Strategie 1: Logprob-gebaseerde extractie
Wanneer de API token-niveau-logwaarschijnlijkheden retourneert (zoals sommige aanbieders doen), krijgt de aanvaller directe toegang tot de uitvoerverdeling van het doelmodel:
import httpx
async def extract_with_logprobs(api_url: str, prompts: list, api_key: str):
"""Extract teacher distributions from API logprobs."""
dataset = []
async with httpx.AsyncClient() as client:
for prompt in prompts:
response = await client.post(api_url, json={
"prompt": prompt,
"max_tokens": 256,
"logprobs": 5, # Vraag top-5-logprobs per token aan
"temperature": 0,
}, headers={"Authorization": f"Bearer {api_key}"})
result = response.json()
dataset.append({
"prompt": prompt,
"completion": result["choices"][0]["text"],
"token_logprobs": result["choices"][0]["logprobs"],
})
return dataset| Beschikbare informatie | Extractiekwaliteit | Benodigde queries (7B-equivalent) |
|---|---|---|
| Volledige logprobs (hele vocabulaire) | Zeer hoog | 10K-50K |
| Top-k logprobs (k=5-20) | Hoog | 50K-200K |
| Alleen top-1-logprob | Gemiddeld | 200K-500K |
| Alleen tekst (geen logprobs) | Lager | 500K-2M |
Strategie 2: Extractie op basis van enkel tekst
Wanneer de API alleen gegenereerde tekst retourneert, gebruikt de aanvaller de tekst als trainingsdoelen:
def build_text_extraction_dataset(target_api, query_generator, n_samples=100000):
"""Extract model behavior using generated text only."""
dataset = []
for prompt in query_generator.generate(n_samples):
response = target_api.generate(prompt, temperature=0.0)
dataset.append({
"instruction": prompt,
"output": response,
})
return datasetStrategie 3: Taakspecifieke extractie
In plaats van het volledige model te repliceren, extraheer je alleen taakspecifieke capaciteiten:
| Extractiescope | Benodigde queries | Studentgrootte | Getrouwheid |
|---|---|---|---|
| Volledige modelreplicatie | 500K-2M | Vergelijkbaar met doelwit | 70-85% |
| Enkele taak (bijv. samenvatten) | 10K-50K | 1/10e van doelwit | 85-95% |
| Domeinkennis (bijv. medisch) | 50K-200K | 1/5e van doelwit | 80-90% |
| Stijl/persona | 5K-20K | Elke grootte | 90-98% |
Active learning voor efficiënte extractie
Slimme queryselectie vermindert het aantal benodigde API-aanroepen dramatisch:
def active_extraction_loop(target_api, student_model, base_queries, rounds=10):
"""Use student uncertainty to select maximally informative queries."""
all_data = []
for round_num in range(rounds):
if round_num == 0:
# Eerste ronde: gebruik diverse basisqueries
queries = base_queries[:1000]
else:
# Volgende rondes: vind waar de student het meest onzeker is
candidates = generate_candidates(10000)
uncertainties = []
for q in candidates:
logits = student_model.get_logits(q)
entropy = -(F.softmax(logits, -1) * F.log_softmax(logits, -1)).sum()
uncertainties.append(entropy.item())
# Selecteer queries met de hoogste onzekerheid
top_indices = sorted(range(len(uncertainties)),
key=lambda i: uncertainties[i], reverse=True)
queries = [candidates[i] for i in top_indices[:1000]]
# Bevraag het doelwit en voeg toe aan de dataset
for q in queries:
response = target_api.generate(q)
all_data.append({"instruction": q, "output": response})
# Hertrain de student op de geaccumuleerde data
student_model.fine_tune(all_data)
print(f"Round {round_num}: {len(all_data)} samples, "
f"fidelity={measure_fidelity(student_model, target_api):.2%}")
return student_modelVerdedigingen tegen distillatie-extractie
| Verdediging | Mechanisme | Effectiviteit | Nadeel |
|---|---|---|---|
| Logprob-beperking | Geen token-logprobs retourneren via API | Vermindert extractiekwaliteit | Breekt legitieme use-cases |
| Uitvoerverstoring | Ruis toevoegen aan logprobs/tokenselectie | Verlaagt extractiegetrouwheid | Verslechtert gebruikerservaring |
| Rate-limiting | Queries per gebruiker/API-key beperken | Vertraagt extractie | Omzeild met meerdere accounts |
| Query-fingerprinting | Queries met extractiepatroon detecteren | Signaleert verdacht gedrag | Hoog vals-positiefpercentage |
| Watermarking | Statistische watermerken inbedden in uitvoer | Bewijst herkomst na extractie | Kan worden verwijderd (zie Watermerkverwijdering) |
| Model-fingerprinting | Unieke gedragssignaturen inbedden | Gestolen modellen identificeren | Voorkomt extractie niet |
Watermarking voor herkomst
# Eenvoudige uitvoer-watermarking: stuur tokenselectie richting watermerkpatroon
def watermarked_generate(model, prompt, watermark_key, bias_strength=2.0):
"""Generate with statistical watermark embedded in token selection."""
tokens = []
for step in range(max_tokens):
logits = model(prompt + tokens)
# Verdeel vocabulaire in groene/rode lijsten met watermerksleutel
green_tokens, red_tokens = partition_vocab(watermark_key, step)
# Stuur richting groene tokens
logits[green_tokens] += bias_strength
next_token = sample(logits)
tokens.append(next_token)
return tokensGerelateerde onderwerpen
- Aanvalsvectoren op modelarchitectuur -- Overzicht van het architectuuraanvalsoppervlak
- Modelextractie -- Bredere modelextractietechnieken
- Quantisatieaanvallen -- Compressie als beveiligingsfactor
- Watermerkverwijdering -- Het verslaan van herkomsttracking
Waarom is taakspecifieke distillatie-extractie gevaarlijker dan volledige modelreplicatie?
Referenties
- Distilling the Knowledge in a Neural Network (Hinton et al., 2015) -- Knowledge distillation
- Stealing Machine Learning Models via Prediction APIs (Tramer et al., 2016) -- API-based model extraction
- Model Extraction Attacks and Defenses (Jagielski et al., 2020) -- Extraction defense survey