Module 5: GDPR for AI Systems
Data Minimization applied to AI
Description
GDPR Art. 5(1)(c): personal data must be "adequate, relevant and limited to what is necessary." That's the principle of data minimization. For AI, it clashes with the ML intuition that "more data = a better model."
The resolution: minimization isn't "less data." It's "only the data necessary for the specific purpose." For AI, this applies in two distinct contexts: training data and inference data.
By the end you'll be able to:
- Distinguish data minimization in training vs. inference
- Apply techniques: synthetic data, sampling, feature reduction, anonymization
- Justify which data is necessary, with documentation
Training data vs. inference data: two distinct regimes
Training data
- Processing: large volume, a single moment (the training run)
- Risk: personal data can "leak" via the model's memorization
- Mitigation: anonymization, synthetic data, federated learning, differential privacy
Inference data
- Processing: continuous, every query
- Risk: active exposure of personal data
- Mitigation: minimal collection, anonymization in logs, strict retention
Techniques for minimization in training
Technique 1: Anonymization
You remove identifiers before training:
def anonymize_for_training(record):
return {
# Removed: name, email, phone, address, SSN
"age_bucket": bucket_age(record["age"]), # 25 → "20-29"
"zip_prefix": record["zip"][:3], # 12345 → "123"
"purchase_history": record["purchases"], # OK (generic)
"preferences": record["preferences"],
}
Caveat: anonymization is hard. K-anonymity, l-diversity, and differential privacy are the more serious techniques.
Technique 2: Synthetic data
You generate data that's statistically similar but contains no real people:
from sdv.lightweight_synthesizers import GaussianCopulaSynthesizer
synthesizer = GaussianCopulaSynthesizer(metadata)
synthesizer.fit(real_data)
synthetic_data = synthesizer.sample(num_rows=100000)
# Train on synthetic_data instead of the real thing
model.train(synthetic_data)
Pros: zero GDPR risk for training. Cons: model quality can suffer if the synthetic distribution doesn't capture the real patterns.
Technique 3: Sampling
If you have 10M records, do you really need all of them? Often, 100K is enough.
# Stratified sampling to preserve the distributions
from sklearn.model_selection import train_test_split
_, training_subset = train_test_split(
full_data,
test_size=0.01, # 1% = 100K if the total is 10M
stratify=full_data["target"]
)
Less data = less exposure = less GDPR risk.
Technique 4: Federated Learning
The model trains on the device (mobile, edge) without centralizing the data:
Client A: trains locally on data A → sends gradients
Client B: trains locally on data B → sends gradients
Server: aggregates the gradients, NEVER sees the data
Pros: personal data never leaves the device. Cons: significant technical complexity.
Technique 5: Differential Privacy
You add controlled noise to the data/gradients so no specific individual is identifiable.
# Sketch — DP-SGD adds noise to gradients
import opacus
privacy_engine = opacus.PrivacyEngine()
model, optimizer, data_loader = privacy_engine.make_private(
module=model,
optimizer=optimizer,
data_loader=data_loader,
noise_multiplier=1.1,
max_grad_norm=1.0,
)
Pros: mathematical guarantees. Cons: model accuracy can drop significantly.
Techniques for minimization in inference
Technique 1: Collect only what you need
Your LLM doesn't need the user_id, email, or phone to answer a general question. Don't pass them in the prompt.
# Bad
prompt = f"User {user.full_name} ({user.email}) is asking: {question}"
# Good
prompt = f"User question: {question}"
Technique 2: Strip personal info from logs
def sanitize_for_logging(input_text):
# Remove emails, phones, SSNs from logs
sanitized = re.sub(r'[\w.+-]+@[\w-]+\.[\w.-]+', '[EMAIL_REDACTED]', input_text)
sanitized = re.sub(r'\b\d{3}-\d{2}-\d{4}\b', '[SSN_REDACTED]', sanitized)
sanitized = re.sub(r'\b\d{3}-\d{3}-\d{4}\b', '[PHONE_REDACTED]', sanitized)
return sanitized
log.info(sanitize_for_logging(user_input))
Technique 3: Aggressive retention
Detailed logs with personal info: 30-90 days. After that, aggregate-only metrics.
@scheduled_task(every="daily")
def cleanup_old_logs():
db.execute(
"DELETE FROM detailed_logs WHERE created_at < NOW() - INTERVAL '90 days'"
)
Technique 4: Tokenization / pseudonymization
Replace personal identifiers with reversible tokens:
# user_id → token via lookup
def tokenize(user_id):
return f"USR-{hashlib.sha256(user_id.encode() + SECRET).hexdigest()[:16]}"
# In logs, prompts, analytics
log_entry["user"] = tokenize(real_user_id)
If you need to "de-tokenize" for support, you keep the mapping in a separate lookup table with stricter access controls.
The fundamental conflict: more data vs. the minimum
When more data IS necessary
- A rare specific domain (specialized medicine) → you need broad coverage
- Performance is safety-critical (autonomous vehicles) → more data = better
- Long-tail outcomes matter → more samples required
When more data is NOT necessary
- Your model has already plateaued on performance
- You're adding similar data (no new information)
- The additional data doesn't improve your eval metrics
The practical test: if removing 50% of your training data significantly degrades performance, it's necessary. If not, it isn't.
Documenting necessity
To defend minimization in an audit, document it:
## Data Necessity Justification — Customer Churn Model
### Data fields used in training:
- account_tenure: necessary because churn correlates with tenure
- usage_frequency: necessary because low frequency predicts churn
- support_tickets_count: necessary because a high count predicts churn
- last_login_date: necessary for the recency metric
### Data fields NOT used (available but excluded):
- name: NOT necessary for the prediction
- email: NOT necessary
- phone: NOT necessary
- exact_birthdate: NOT necessary; we use age_bucket instead
### Anonymization applied:
- email replaced with hashed_user_id
- exact_dates with month_year
- specific zipcodes with city_region
### Retention:
- Training data refreshed quarterly
- Old training datasets purged after 1 year
If an auditor asks "why do you have this data?", you have a documented answer.
Common traps
Trap 1 — Superficial "anonymization." You remove the name but keep ZIP + age + gender → re-identifiable. Decent k-anonymity requires at least k=5.
Trap 2 — The "more data is always better" mentality. Your ML team wants everything. Resist — every piece of data requires justification.
Trap 3 — Treating inference data like training data. Detailed logs that grow with no retention. The same position as training in terms of GDPR exposure.
Trap 4 — Synthetic data with no validation. You generate synthetic data and assume the quality is fine. Result: a bad model. Validate it against a real eval set.
Trap 5 — Federated learning as a silver bullet. "The data never leaves the device" sounds great, but gradients can still leak information. It needs DP on top for real guarantees.
Exercise
Your product: a recommendation system for e-commerce. Currently you collect:
- user_id, name, email, phone
- birthday (exact date), gender, address (full)
- purchase history (all items, dates, amounts)
- browsing history (every page view, every click)
- inferred demographics (income bracket, family status)
Apply data minimization:
- Which data do you drop from training?
- Which data do you keep but anonymize/aggregate?
- What's the retention strategy?
See the solution
Dropped from training:
name: not necessary to recommendemail: not necessaryphone: not necessaryaddress (full): not necessary; we usezip_prefixorcity
Kept but modified:
birthday→age_bucket(10-year buckets)gender→ kept (it can be relevant for apparel)purchase_history→ kept (item IDs, month/year dates, bucketed amounts)browsing_history→ aggregated into "categories visited" instead of every pageinferred demographics→ kept but with documented consent
Retention:
- Training datasets: 1 year, then refresh
- Detailed browsing logs: 30 days
- Aggregated patterns: indefinite (not identifiable)
- Personal info for an active user: until account closure + 6 months
Summary
You learned:
- ✅ Data minimization: training vs. inference (distinct regimes)
- ✅ 5 training techniques: anonymization, synthetic, sampling, federated, DP
- ✅ 4 inference techniques: collect the minimum, sanitize logs, retention, tokenization
- ✅ Documenting necessity for an audit
- ✅ The traps: superficial anonymization, the more-is-better mentality
Checkpoint: if you can justify every piece of data you collect with a documented necessity, you're ready.
Next capsule
05 — Granular consent for AI processing. Consent is the area where most sites fail GDPR. For AI, the requirements are even more specific.
Resources
- GDPR Art. 5(1)(c) — the minimization principle.
- Differential Privacy library (Opacus) — PyTorch + DP.
- Synthetic Data Vault — the generation library.
- Federated learning frameworks — an overview.