kzhao5/mea-qedks-defenses
MEA benchmark — QEDKS attack vs. defenses (complete run outputs)
Full reproduction artifacts for the QEDKS extraction attack against the generator-style defenses of the MEA defense benchmark (A-Benchmark-for-Model-distillation-survey), including the clean (undefended) QEDKS baseline used as the M4 negative control. Companion repos: SeqKD · SODA
Setup
Detector results — read the negative control, not the raw p/z
M4 asks whether a watermark/fingerprint transferred into the extracted student. The only valid evidence is the positive − negative contrast: the same detector applied to the student extracted from the defended teacher vs. the student extracted from the clean teacher (clean/).
Why the absolute p-value / z-score is misleading here
These detectors are biased by the student's text distribution. On QEDKS students the clean student — which never saw a watermarked teacher — already scores far from chance: ginsew z = +12.7 and radioactivity +5.4 SE above γ = 0.25 (p = 2.6e−08).
So radioactivity's positive p = 2.5e−08, which superficially clears the benchmark's own p < 1e-5 acceptance hint, is entirely detector bias: the clean student scores the same. Only ginsew retains a genuine, if modest, separation once the control is subtracted (+4.3 SE, i.e. a 0.86-percentage-point green-rate gap — much smaller than z = +18.5 suggests).
The bias is detector-specific, not attack-specific. The ADFP detector is essentially unbiased on QEDKS students — its clean student sits only +0.4 SE from γ = 0.5 — so ADFP's absolute number happens to be trustworthy here. We established that by running the control, rather than assuming it; the same assumption applied to radioactivity would have produced a false positive.
For comparison, in the SeqKD companion repo nothing separates (ginsew +0.5 SE, radioactivity +0.1 SE), and there radioactivity's clean student sits only +0.4 SE from γ — the detector happens to be unbiased on SeqKD students, which is why an absolute test looked valid in that setting. Do not generalise that: always run the attack-matched clean control.
Layout
clean/<run_id>/ clean (undefended) QEDKS baseline = M4 negative control
(query_plans, teacher_transcripts, train_data, checkpoints, manifest)
<defense>/
checkpoint-final/ convenience copy of the final student LoRA adapter
detector_report.json positive detector result (watermark/fingerprint defenses)
detector_negative_report.json same detector on the clean student
oracle/ defended-teacher transcript, received-query log,
defense artifacts (watermark state / fingerprint), server log
attack/qedks/<run>/ query_plans, teacher_transcripts, train_data,
checkpoints (incl. intermediate), logs, attack_manifest.json
detector/ , detector_negative/ full detector outputs (student_outputs.jsonl, rows, manifest)
defense_run_manifest.jsonLoad a student:
from transformers import AutoModelForCausalLM, AutoTokenizer
from peft import PeftModel
base = AutoModelForCausalLM.from_pretrained("Qwen/Qwen2.5-7B", torch_dtype="bfloat16", device_map="auto")
model = PeftModel.from_pretrained(base, "kzhao5/mea-qedks-defenses", subfolder="ginsew/checkpoint-final")Defense-specific notes
- ads (Antidistillation Sampling):
ads/ads_config.json—lam=0.1,eps=0.01,tau=0.9,top_p=0.95,max_new_tokens=1536, proxy studentQwen/Qwen2.5-7B. The proxy-student gradients were not recomputed for QEDKS: this run reuses the gradient file computed for the SeqKD companion run (defenses.ads.save_grad; 512 holdout teacher traces,max_length=512, seed 0). ADS gradients depend on the proxy student and the holdout teacher traces, not on the attacker's queries, so they are attack-independent. The ~29 GB file is not uploaded — see the SeqKD repo README for how to regenerate it. - ADS is by far the slowest defense to serve: two extra proxy forward passes per generated token, ~4.3 min per teacher query here (~71 h wall-clock for the full 1000-query run on 4×A100).
DuFFin lineage check (added 2026-09-17)
duffin/ holds a joint Knowledge-DuFFin evaluation run with the benchmark's evaluation/defense_eval/evaluate_duffin.py at the guide defaults. The same tree is uploaded to all three companion repos (SeqKD / SODA / QEDKS), because the score compares all four models on a shared probe set.
- Teacher: undefended
Qwen/Qwen2.5-72B-Instructanswers 1000 fixed MMLU-Pro test probes (biology, business, chemistry, computer science, math, physics; seed 42), greedy,max_new_tokens=4. - Negative: raw
Qwen/Qwen2.5-7Bbase. Positives: the clean B=1000 SeqKD, SODA and QEDKS students (pinned HF revisions induffin/<attack>_source.json). - Score = fraction of probes where the student picks the same option letter as the teacher, computed on the probes that all four models answered with a parseable letter.
These numbers are not informative — read before using them.
- Almost nothing parses. The teacher returns a letter on 998/1000 probes, but the base-model students usually start with "To solve this problem" or "The correct answer is" and get cut at 4 tokens. Only 41–81 probes per student parse, and 25/1000 are valid for all four models. With n = 25 the standard error is ≈ 0.09, so no positive is distinguishable from the base negative.
- Parser artefact.
defenses/duffin/detector.py::extract_choiceupper-cases the response and falls back to the last standalone letter, so the English article "a" parses as option A (e.g. "You are a helpful" → A). 4–7 of the 25 common answers per model are such fallback parses. - A larger token budget does not fix it. On a 200-probe check,
max_new_tokens=16/32raised validity to 41–54% for base / SeqKD-clean, but a third to a half of those parses were the same fallback artefact. A parser fix (or scoring option-letter logits) is needed before DuFFin is meaningful for base-model students. - SODA ≈ base. The SODA student gives the same response as the base on 967/1000 probes (SeqKD 798, QEDKS 676), consistent with SODA barely training (see the SODA repo README).
duffin/
protocol.json summary.csv summary.json common_valid_probe_ids.json
seqkd_source.json soda_source.json qedks_source.json pinned student checkpoints
reference/probes.jsonl the 1000 probes
reference/teacher_reference.json teacher responses and parsed choices
base_negative/ seqkd/ soda/ qedks/ probe_rows.jsonl (per-probe responses/choices),
detector_report.json, detector_rows.jsonl, detector_manifest.jsonDefense capability evaluation — ACC and BERTScore (added 2026-09-19)
defense_eval/ holds the benchmark's evaluation/defense_eval/evaluate.py run for the QEDKS arms: six-task macro ACC (M1) and BERTScore against the undefended Qwen teacher on 3000 shared held-out prompts (M2), for the clean student and all six defended students, plus the shared teacher/base reference (identical copy in the three companion repos).
Protocol: zero-shot ARC-Challenge / HellaSwag / MMLU / TruthfulQA-MC1 / WinoGrande / GSM8K (28,659 items), greedy decoding, 32 new tokens for multiple choice, 512 for GSM8K, 1536 for held-out; a parse failure counts as wrong; BERTScore is roberta-large F1 with baseline rescaling. Teacher Qwen/Qwen2.5-72B-Instruct (chat template), students Qwen/Qwen2.5-7B + LoRA (raw text).
Reference: teacher macro ACC 0.3197, raw base Qwen2.5-7B macro ACC 0.4445.
Read the teacher number with care. Under this protocol the teacher's macro ACC (0.3197) sits below the raw base model (0.4445); that is a parsing artefact, not a capability statement. The instruct teacher opens with reasoning ("To determine ...") and the 32-token multiple-choice budget truncates it before it emits a letter, so 49% of its multiple-choice answers fail to parse and count as wrong (base 20%, students 14-20%). Where the budget is generous the ordering is the expected one: GSM8K teacher 0.9538 vs base 0.5967. Student-vs-student comparisons are unaffected — every student shares the same rendering, limits and parser.
Run notes. Generation used the upstream batched path (evaluation/core/batch_generation.py) with one configuration for the whole run: student batch 32 for every stage, teacher batch 8 (recorded per row as generation_batch_size). Greedy output is not bit-identical across batch sizes, so these numbers should not be mixed with per-item runs. The work was split into 72 shards over A100/H100/H200/B200 nodes; each shard ran upstream evaluate_model on a slice, the canonical files were merged back in upstream order, and the upstream stages then computed the metrics. Three defects had to be fixed and are worth upstreaming: the GSM8K numeric parser raised decimal.InvalidOperation on very long numbers and killed whole jobs; BERTScore crashed on empty student answers (~1% of held-out prompts, 13-39 per model) because bert_score encodes them with a method Transformers 5 removed; and MMLU test repeats 27 example ids, which any per-example (rather than per-id) writer turns into duplicate rows.
defense_eval/
qedks/summary.csv summary.json protocol.json
qedks/<defense>/m1_acc.json m2_bertscore.json source.json
m1_predictions/<task>.jsonl per-item prompt, response, parse status, correct
heldout_outputs.jsonl the 3000 generations scored by BERTScore
reference/teacher/ m1_acc.json, m1_predictions/, heldout_outputs.jsonl (BERTScore reference)
reference/base/ m1_acc.json, m1_predictions/ (raw Qwen2.5-7B capability floor)DuFFin v2 — lineage verification over seven models (added 2026-09-20)
duffin_v2/ replaces the earlier duffin/ run. The benchmark's DuFFin implementation was rewritten upstream (five-shot CoT prompt, new answer parsing, 1024-token budget, batched generation, validity check, and a four-model negative set), so the old `duffin/` numbers are superseded and should not be used. Identical copy in all three companion repos.
Protocol: 1000 fixed MMLU-Pro test probes (biology, business, chemistry, computer science, math, physics; seed 42), greedy, max_new_tokens=1024, batch 4. The undefended Qwen/Qwen2.5-72B-Instruct teacher answers once; four negative controls (raw Qwen2.5-7B, Qwen2.5-7B-Instruct, Qwen2-7B-Instruct, Mistral-7B-Instruct-v0.3) and the three clean B=1000 students (SeqKD, QEDKS and the corrected SODA student) answer the same probes. The score is the fraction of probes where a model picks the teacher's option letter, computed on the 508 probes every model parsed.
Model-level ROC-AUC = 0.167 (3 positives vs 4 negatives), i.e. below the 0.5 of a coin flip. The ordering is the reason: Qwen2.5-7B-Instruct, an unrelated model that merely shares the teacher's family, matches the teacher on 70% of probes, while the students actually distilled from this teacher at B=1000 match on 25-47%. A knowledge-level fingerprint therefore cannot separate "same family" from "distilled from this victim" at this budget — that is a finding about DuFFin, not a failed run. Report it with the negative set spelled out; a same-family instruct control is what breaks it.
Parse rates. Upstream aborts a model whose parse rate falls below --min-valid-rate 0.9. Four of the seven models sit below it (0.766-0.885) because base-model students follow "answer with only one letter" less reliably than instruct models, so we record the shortfall (validity_passed: false, both rates and the threshold are in each detector_report.json) instead of discarding a completed run. Scores already use the intersection of probes every model parsed.
duffin_v2/
summary.csv summary.json roc_auc.json roc_curve.csv protocol.json
common_valid_probe_ids.json the 508 probes scored for every model
reference/probes.jsonl reference/teacher_reference.json
<model>/probe_rows.jsonl per-probe teacher/student answers and parsed choices
<model>/detector_report.json detector_rows.jsonl detector_manifest.json
seqkd_source.json soda_source.json qedks_source.json pinned student checkpointsM1 v2 — conditional log-likelihood scoring for multiple choice (added 2026-09-20)
defense_eval_m1_v2/ replaces the M1 column of defense_eval/. The earlier M1 generated 32 tokens per multiple-choice question and parsed a letter out of the text, which punished models that start with reasoning: 49% of the instruct teacher's answers never reached a letter and were scored wrong, so the teacher's macro ACC (0.3197) landed below the raw base model (0.4445). The benchmark now scores the five multiple-choice tasks by conditional log-likelihood over the candidate continuations (arcchallenge `accnorm, hellaswag accnorm`, mmlu `acc`, truthfulqa `mc1`, winogrande `acc`, gsm8k `exactmatch); GSM8K keeps generation and is reused unchanged from the previous run, so the M2/BERTScore results in defense_eval/` are unaffected. Use these numbers for M1.
Reference: teacher 0.6628 (was 0.3197), raw base Qwen2.5-7B 0.5842 (was 0.4445). The ordering is now the expected one, and per-task teacher scores look sane (MMLU 0.797, HellaSwag 0.686, GSM8K 0.954).
defense_eval_m1_v2/
qedks/summary.csv summary.json protocol.json
qedks/<defense>/m1_acc.json per-task ACC, metric name and sample counts
qedks/<defense>/m1_choice_scores_v2/*.jsonl per-option log-likelihoods and the picked label
qedks/<defense>/m1_predictions/gsm8k.jsonl reused generation-based GSM8K predictions
reference/teacher/ , reference/base/ same layout for the shared reference models