Membership
Can logprobs reveal a training row? TPR at 1% FPR, thresholded on held-out controls, with a Clopper–Pearson interval. High with a tight CI means leakage. Zero with a tight CI means this LoRA did not leak at that operating point.
memaudit — training-data memorization auditor
A local plugin that plants canaries in your fine-tune and reports whether the finished model leaks membership or regurgitates training text.
Repetition-tier curve at the same 1% FPR threshold: 1x 0/34 (single-exposure) · 4x 1/33 (moderate) · 16x 9/33 (high-exposure). The pooled 10% is substantially a duplication/exposure stress signal, not a 10% detection probability for a single-exposure record.
TinyLlama-1.1B-Chat · Alpaca · LoRA r=8 · 1 epoch · 100 canaries / 200 controls · budget 0.874% · model-scored high_ppl · 20,000 host rows · Apple M3 Pro / MPS · 2026-08-30
Can logprobs reveal a training row? TPR at 1% FPR, thresholded on held-out controls, with a Clopper–Pearson interval. High with a tight CI means leakage. Zero with a tight CI means this LoRA did not leak at that operating point.
Does the model emit the secret from a prefix? A separate attack. Membership and regurgitation routinely disagree — a regurgitation-only test can file a leaky model as clean.
| Stack | Config | n / controls | Budget | TPR @ 1% FPR | 95% CI | AUC | Regurg |
|---|---|---|---|---|---|---|---|
| TinyLlama + Alpaca | HF Trainer · LoRA r=8 · 1 ep · 20k rows | 100 / 200 | 0.874% | 0.100 (10/100) | [0.049, 0.176] | 0.837 | 0/100 |
| TinyLlama + Alpaca (v0.1 appendix) | same stack · uniform_vocab canaries | 100 / 200 | 0.907% | 0.180 (18/100) | [0.110, 0.269] | 0.776 | 0/100 |
| distilgpt2 LoRA | HF Trainer · 1 ep · r=8 · host 80k | 100 / 200 | 0.77% | 0.000 | [0.000, 0.036] | 0.586 | 0/100 |
| distilgpt2 · risky | HF Trainer · 5 ep · r=16 · lr 1e-3 | 100 / 200 | 0.77% | 0.000 | [0.000, 0.036] | 0.848 | 0/100 |
Reproduce the TinyLlama flagship: python examples/alpaca_case_study.py.
Powered canaries: requested family high_ppl, actual generator model_scored_high_ppl (TinyLlama rejection sampling).
Tier curve at the shipped threshold: 1x 0/34, 4x 1/33, 16x 9/33 — the pooled 10% is mostly a 16x exposure-stress signal.
Prior v0.1 run (uniform_vocab fallback, no model at generation): TPR 0.180 [0.110, 0.269].
Write-up: case-study.html.
distilgpt2 rows are the already-measured n=100/200 benches — tight CIs, not hidden.
A 12-canary first look (TPR 0.500, CI [0.211, 0.789]) is in the case-study appendix; it is not the headline.
Models trained with the goldfish loss show near-zero verbatim extraction yet remain highly detectable by likelihood attacks; head-only fine-tunes maximize membership signal with almost no extractable text. A loss-only audit is wrong in both directions — so memaudit never ships one. Every audit reports two separate verdicts, side by side.
"Can an attacker with log-prob access tell what was trained on?"
"Does the model emit training content when prompted with a prefix?"
Honesty is the feature: the report names what it does not cover — model inversion, reconstruction, attribute inference — because under EDPB Opinion 28/2024 ¶55, test results are evidence only for the attacks actually run.
Injection happens before training (transformers builds the dataloader before any callback fires —
so memaudit gives you a pre-train inject() helper
and a thin callback). The same engine runs post-hoc from the CLI.
$ pip install memaudit $ pip install "memaudit[peft]" # LoRA / adapter-toggle $ pip install "memaudit[peft,trl]" # LoRA + SFTTrainer
$ memaudit audit --model ./out \ --canary-set ./out/memaudit-manifest.json \ --dataset train.jsonl --ref auto # --ref auto: disable_adapter() on unmerged LoRA, # else pass a base checkpoint path
from memaudit import generate_canaries, inject, MemorizationAuditCallback canaries = generate_canaries(tokenizer, n=200, n_controls=200, family="high_ppl", seed=0) train_ds, manifest = inject(train_ds, canaries, fmt="auto", seed=0) trainer.add_callback(MemorizationAuditCallback(trainer=trainer, manifest=manifest)) trainer.train() # writes <output_dir>/memaudit-report.json
Canary placement is format-aware and verified: the secret always lands on the trainable side of the
record (completion / assistant turn / text body). A prompt-side canary would be
loss-masked to labels=-100 and silently zero the audit — inject() refuses that placement,
and the callback re-scans at on_train_begin to prove every canary survived tokenization, masking, and packing.
Most fine-tunes are LoRA fine-tunes — and PEFT configs silently invalidate naive audits. The published example: new-token canary audits collapse when embeddings are frozen, which is exactly what standard LoRA does. memaudit checks embedding trainability before training and routes canary families accordingly — a router, not a blocker.
Audit signal collapse with frozen embeddings — new-token canary audit under DP-LoRA, Panda et al., ICLR 2025 (Table 14). The default high-perplexity regular-token family survives: TPR@1%FPR 0.94–0.99 under LoRA r=4 (Meeus et al., ICML 2025).
Claim scope: "no other tool" per our August 2026 landscape scan of open-source and commercial offerings — no OSS tool, no enterprise platform's public materials, and no announced regulator library addresses frozen-embedding × canary-family interaction. See ¶ 06.
modules_to_save=[embed_tokens, lm_head] flagged as raising the membership-risk tierdisable_adapter() scores base + fine-tune from one model copy; merged adapters and bias≠"none" detected, base checkpoint fallbackcompletion_only_loss, assistant-only templates, packing truncation: placements that would silently zero canaries are caughton_train_begin — token-level proof each canary exists in the actual batchesThe hero numbers are the powered TinyLlama + Alpaca run (100 / 200). Below: a TinyDemoLM positive-control that proves the pipeline can detect, then the same distilgpt2 n=100/200 rows from the compact table with their stability seeds.
Scale: TinyDemoLM positive control — canaries deliberately dominate tokens so the pipeline can show a clear hit and a clean control side. If a model doesn't memorize, memaudit refuses the TPR@1%FPR headline rather than inventing one.
| Run | Config | n / controls | Budget | TPR @ 1% FPR | 95% CI | AUC | Stability (seeds 0,1,2) |
|---|---|---|---|---|---|---|---|
| SFT | trl.SFTTrainer · 1 ep · r=8 · lr 2e-4 | 16 / 100 | 0.93% | 0.000 | [0, 0.206] | 0.516 | 0.000 / 0.000 / 0.000 |
| C | HF Trainer · 1 ep · r=8 · lr 2e-4 · host auto-grown 80k | 100 / 200 | 0.77% | 0.000 | [0, 0.036] | 0.586 | 0.000 / 0.010 / 0.010 |
| D · risky | HF Trainer · 5 ep · r=16 · lr 1e-3 · host auto-grown 80k | 100 / 200 | 0.77% | 0.000 primary | [0, 0.036] | 0.848 | 0.000 / 0.090 / 0.090 (9/100 on 2 of 3 seeds) |
Scale: pretrained distilgpt2 + LoRA at an honest canary budget (separate from the TinyDemoLM
positive control above). Primary TPR stays 0.000 on every row; Run D is reported exactly as
measured: AUC 0.848 with stability 0.000 / 0.090 / 0.090 (9/100 canaries on seeds 1 and 2).
No fabricated headline TPR. Reproduce via benchmarks/run_lora_benchmark.py
and benchmarks/run_sft_benchmark.py.
Measured wall-clock on Apple MPS: Run C train 753 s / audit 173 s;
SFT train 192 s / audit 52 s.
EDPB Opinion 28/2024 made documented, state-of-the-art testing against membership inference and regurgitation the operative GDPR evidence standard for AI models. memaudit's report is designed field-by-field against those paragraphs. It produces test evidence — it does not make you compliant.
"…successful testing which covers widely known, state-of-the-art attacks can only be evidence for the resistance to those attacks… this could include, among others, structured testing against: (i) attribute and membership inference; (ii) exfiltration; (iii) regurgitation of training data; (iv) model inversion; or (v) reconstruction attacks."
"…both (i) the likelihood of direct (including probabilistic) extraction of personal data… as well as (ii) the likelihood of obtaining, intentionally or not, such personal data from queries, should be insignificant for any data subject."
| Requirement | What it asks for | Where it lives in memaudit's report |
|---|---|---|
| ¶ 55 (i)/(iii) | Structured testing against membership inference and regurgitation | The two verdicts — canary MIA at TPR@1%FPR with CI; prefix-prompted regurgitation per exposure tier. Attribute inference, model inversion, reconstruction: named out of scope. |
| ¶ 55 | Scope, frequency, quantity and quality of tests | Canary counts, repetition grid, seeds, run date, tool version, negative-control results — all in the versioned JSON. Multi-seed stability block included when you pass multiple seeds. |
| ¶ 58 (c) | Threat model and risk assessments behind the measures | Per-canary-family threat-model fields: attacker access level (log-probs vs. text), knowledge assumptions. |
| ¶ 58 (e) | Controls "to limit or assess the success and impact of main attacks (regurgitation, membership inference attacks, exfiltration, etc.)" | Quantified results with confidence intervals; negative controls always run; per-record list redacted by default. |
| ¶ 46 | Release context (public model vs. internal) changes expected testing level | Release-context field: user declares public API / internal / open-weights; the report states the implied attack surface. |
| ¶ 58 | Documentation an SA can inspect | Provenance: schema version, config, seeds, model/dataset fingerprint hashes. Shipped compliance_annex in every report — render with memaudit report --annex. |
| CNIL | Documented model-status analysis; re-identification attack tests; producible on demand | The report is that artifact for the attacks it runs. CNIL's own caveat is encoded: a negative quick regurgitation test alone proves nothing — memaudit pairs it with calibrated MIA and says so. |
As of August 2026, no shipped tool — open or commercial — does trainer-integrated, canary-based, PEFT-aware memorization auditing. Here is the honest comparison, from public materials.
| memaudit v0.1 | Closed enterprise platforms (DynamoEval-class) |
Regulator libraries (e.g. PANAME) |
Research attack code (MIMIR, ML Privacy Meter) |
|
|---|---|---|---|---|
| Availability | pip install · Apache-2.0 · free | Custom-quote enterprise sales; SaaS / VPC | Announced / in development by CNIL+ANSSI+Inria | Free research code; sparse maintenance as of Aug 2026 |
| Your model & data | Never leave your machine | Uploaded to the vendor platform | Intended as a local library | Local scripts |
| When it audits | Inside the training loop (callback) + post-hoc CLI | Post-hoc, on an already-trained model | Post-hoc | Post-hoc |
| Canaries + negative controls | Yes — pre-registered, coin-flipped, controls in every audit | No published canary methodology | None announced | No (post-hoc MIA on real records only) |
| Headline statistic | TPR @ 1% FPR + Clopper–Pearson CI | AUC / ROC-first (per public materials) | Unknown | Varies by script; typically AUC |
| LoRA / PEFT handling | Pre-flight router: frozen-embedding detection, adapter-toggle reference, family gating | Adapters accepted as an upload format; no published PEFT-aware test design | Not in public materials | Limited configs; no pre-flight |
| Compliance artifact | Versioned JSON designed against EDPB 28/2024 ¶55/¶58; hashes & seeds | Auto-generated PDF audit reports | GDPR-oriented by design (CNIL / ANSSI / Inria) | None |
Fair-play notes: DynamoEval-class platforms cover attack types memaudit doesn't (PII extraction and inference tests) and unadvertised features can't be ruled out — this table reflects public materials as of August 2026. Regulator libraries (CNIL / ANSSI / Inria and peers) are complements: memaudit's report is designed so vocabulary can stay aligned with emerging regulator taxonomies. Deployment scanners like garak solve a different problem (what your deployed model says) and pair well with training-side evidence.
modules_to_save configs that raise membership risk, and uses disable_adapter() so one
model copy provides both fine-tuned and base scores. Merged adapters are detected; you pass a base checkpoint
instead. Full fine-tunes work too — the reference model is loaded separately.memaudit demo) and pretrained
distilgpt2 + LoRA n=100/200 (TPR 0.000, CI [0, 0.036]; risky-config AUC 0.848).
A 12-canary first look exists as an appendix only. Production audits run against your model
and data; every report carries its own scale and provenance fields.We're onboarding a small number of design partners — teams fine-tuning on confidential or regulated data with Hugging Face Trainer / TRL — to harden the audit against real pipelines. A pilot includes:
memaudit produces test evidence; it does not make you compliant. We'll say that in the pilot too.