CoolFace
Modelpublic

kzhao5/mea-qedks-defenses

sourceHugging Faceapache-2.0updated 6d agoView on Hugging Face
0likes
Model Card

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

ItemValue
AttackQEDKS, budget 1000 teacher queries (3 seed + 498 template + 499 follow-up)
TeacherQwen/Qwen2.5-72B-Instruct (defended, served as an online oracle)
StudentQwen/Qwen2.5-7B (base), LoRA r=16, α=32, dropout=0.05, bf16
Executiononline defended-teacher endpoint (QEDKS queries adaptively, so no precomputed transcript)

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/).

DefensePositive green rateNegative (clean)pos − negVerdict
ginsew0.5265 (z = +18.5 vs γ)0.5179 (z = +12.7)+0.0086 = +4.3 SEweak but real transfer
radioactivity0.2573 (p = 2.5e−08)0.2571 (p = 2.6e−08)+0.0002 = +0.1 SEno transfer
adfpgtp = 0.5079 (+0.5 SE vs γ = 0.5)gtp = 0.5065 (+0.4 SE)+0.0013 = +0.06 SEno transfer
ads———no detector in benchmark
doge———no detector in benchmark
trace_rewriting———no detector in benchmark

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.json

Load a student:

python
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 student Qwen/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-Instruct answers 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-7B base. Positives: the clean B=1000 SeqKD, SODA and QEDKS students (pinned HF revisions in duffin/<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.
modellabelscore (common probes)− basecommon valid probesindividual score (own valid probes)
base_negativenegative0.680.00250.646 (48)
seqkdpositive0.60−0.08250.463 (41)
sodapositive0.680.00250.646 (48)
qedkspositive0.72+0.04250.691 (81)

These numbers are not informative — read before using them.

  1. 1.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.
  2. 2.Parser artefact. defenses/duffin/detector.py::extract_choice upper-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.
  3. 3.A larger token budget does not fix it. On a 200-probe check, max_new_tokens=16/32 raised 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.
  4. 4.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.json

Defense 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.

defensemacro ACCvs cleanGSM8K ACCBERTScore (rescaled)vs clean
clean0.4868—0.8309+0.1422—
ads0.4800-0.00680.6657-0.0742-0.2165
doge0.5003+0.01350.8817+0.1799+0.0377
trace_rewriting0.4241-0.06270.8438+0.0902-0.0520
adfp0.4715-0.01520.8552+0.1147-0.0275
ginsew0.5004+0.01360.8772+0.1750+0.0328
radioactivity0.4676-0.01920.8749+0.1765+0.0343

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.

modellabelscore (common probes)− base_negativeown valid probesparse rate
qwen25instructnegativenegative0.7047+0.42729280.975
qwen2instructnegativenegative0.5472+0.26978410.885
qedkspositive0.4665+0.18908140.849
mistralinstructnegativenegative0.3602+0.08278710.922
base_negativenegative0.2776+0.00008280.881
sodapositive0.2539-0.02367260.766
seqkdpositive0.2520-0.02567440.791

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 checkpoints

M1 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).

defenseM1 v2 ACCvs baseold generate-and-parse ACC
clean0.6334+0.04920.4868
ads0.5983+0.01410.4800
doge0.6377+0.05350.5003
trace_rewriting0.6256+0.04140.4241
adfp0.6389+0.05470.4715
ginsew0.6385+0.05430.5004
radioactivity0.6403+0.05610.4676
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