Les données synthétiques permettent de partager, tester et entraîner sans exposer directement des personnes. Elles ne sont pas une cape d’invisibilité: il faut des vérifications systématiques, des limites claires et des preuves d’audit. Ce guide présente des usages pertinents, les risques, des garde-fous concrets et un mode opératoire reproductible, avec des diagrammes lisibles verticalement.
prérequis
- un échantillon source déjà conforme aux lois et consentements applicables
- une séparation stricte entre apprentissage et évaluation
- un environnement d’exécution isolé pour la génération
- un espace de preuves avec journaux, métriques et fiches de jeu
aperçu rapide
- limiter la portée: variables, horizon temporel, granularité
- choisir une méthode adaptée: simulation, statistique, modèle génératif
- générer par lots et tracer chaque lot
- évaluer utilité et confidentialité avant toute diffusion
- documenter ce que le jeu peut et ne peut pas faire
- publier sous un contrat d’usage clair et auditable
de l’idée au jeu partagé
usages pertinents
- jeux d’exemple publics pour documentation et didactique
- tests de charge et de performance sans toucher la production
- préentraînement de modèles sur signaux généraux
- data augmentation quand les classes sont déséquilibrées
- partage externe sous finalité limitée et contrôlée
risques
- mémorisation d’exemples rares et fuites indirectes
- génération mal calibrée qui réintroduit des identifiants
- biais existants reproduits ou amplifiés
- faux sentiment d’anonymat et détournements de finalité
garde-fous
- évaluation de similarité avec les originaux et bornes strictes
- bruit contrôlé et régularisation pour casser la mémorisation
- documentation explicite des limites et du domaine de validité
- revue par un sponsor métier et un responsable privacy
choisir une méthode de génération
- règles et simulateurs: rapide, explicable, idéal pour données structurées simples
- modèles probabilistes tabulaires: copules, arbres, GLM mixtes
- modèles génératifs profonds: VAE, GAN, diffusion pour images et signaux
- approche mixte simulation plus ajustement statistique pour respecter la physique du système
pipeline d’évaluation utilité et confidentialité
métriques d’utilité
- préservation des distributions marginales et des corrélations
- performance d’un modèle simple entraîné sur synthétique puis testé sur réel
- métriques de tâches cibles: précision, rappel, AUC, RMSE selon le cas
# évaluer l'utilité: entraîner sur synthétique, tester sur réel
import numpy as np
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import roc_auc_score
def utilite_auc(X_syn, y_syn, X_real, y_real):
clf = LogisticRegression(max_iter=1000)
clf.fit(X_syn, y_syn)
proba = clf.predict_proba(X_real)[:, 1]
return float(roc_auc_score(y_real, proba))
mesures de similarité et bornes
- distance de Wasserstein sur variables numériques
- divergence de Jensen Shannon sur histogrammes
- taux de collisions exactes entre lignes réelles et synthétiques
# mesure de similarité cosinus pour vecteurs embarqués
import numpy as np
def cosinus(a, b):
num = float(np.dot(a, b))
den = float(np.linalg.norm(a) * np.linalg.norm(b) + 1e-9)
return num / den
tests de mémorisation et de fuite
- nearest neighbour distance ratio: comparer distance minimale dans réel vs synthétique
- audit de collisions: hash de lignes canonisées
- membership inference basique: classifieur qui décide si un point était dans l’entraînement
# test rapide de mémorisation via distances
import numpy as np
from sklearn.neighbors import NearestNeighbors
def ratio_nn(real, synth):
nbr_r = NearestNeighbors(n_neighbors=1).fit(real)
d_rs, _ = nbr_r.kneighbors(synth, return_distance=True)
nbr_s = NearestNeighbors(n_neighbors=1).fit(synth)
d_rr, _ = nbr_s.kneighbors(real, return_distance=True)
return float(np.median(d_rr) / (np.median(d_rs) + 1e-9))
tutoriel pas à pas
étape 1: définir la finalité et le périmètre
- variable cible, fenêtre temporelle, grain
- champs sensibles exclus ou masqués en amont
- définir les quasi identifiants pour les tests
scoping:
target_task: "classification churn"
time_window: "2023-01-01..2023-12-31"
grain: "client_id mois"
exclude: ["email", "téléphone", "adresse"]
quasi_identifiers: ["âge", "code_postal", "nb_enfants"]
étape 2: préparer et partitionner
- séparer la source en train et holdout réel
- normaliser et encoder de façon déterministe
- journaliser le hash des partitions pour vérifiabilité
import hashlib, json
def digest(obj):
s = json.dumps(obj, sort_keys=True, ensure_ascii=False)
return hashlib.sha256(s.encode()).hexdigest()[:12]
étape 3: entraîner un générateur
- commencer simple: copules ou régressions avec bruit
- tracer hyperparamètres, seed et version du code
train:
method: "copula_gaussian"
seed: 42
params:
regularization: 1e-2
max_components: 8
étape 4: générer par lots et tracer
- générer N lignes par lot
- attribuer un id de lot et une seed
- stocker des statistiques rapides de chaque lot
import numpy as np, uuid, time
def gen_batch(n, seed):
rng = np.random.default_rng(seed)
rows = int(n)
meta = {"batch_id": str(uuid.uuid4()), "rows": rows, "generated_at": int(time.time()), "seed": int(seed)}
return meta
étape 5: évaluer utilité et confidentialité
- comparer distributions et performances
- effectuer des tests de mémorisation
- documenter les résultats et les écarts acceptés
evaluation:
utility:
auc_on_real: 0.79
drift_ok: true
privacy:
nn_ratio: 1.35
collisions_exactes: 0
decision: "publiable avec limites"
étape 6: publier avec un contrat d’usage
- finalités autorisées et interdites
- conditions de licence et attribution
- fenêtre de validité et point de contact
contract:
dataset: "synthetic_customers_v1"
purpose_allow: ["tests", "documentation", "benchmarks"]
purpose_deny: ["ciblage marketing", "réidentification"]
license: "cc by 4.0"
retention_days: 365
pii_status: "aucune donnée personnelle"
contact: "data@exemple.com"
diagrammes de référence
séquence de validation interne
grille de décision publication
exemples complets
cas 1: jeu tabulaire pour tests de charge
import numpy as np
import pandas as pd
def make_synth_load(n=1_000_000, seed=123):
rng = np.random.default_rng(seed)
df = pd.DataFrame({
"client_id": rng.integers(1_000_000, 9_999_999, size=n),
"âge": rng.integers(18, 90, size=n),
"revenu_mensuel": rng.gamma(5.0, 600.0, size=n),
"segment": rng.choice(["A","B","C"], size=n, p=[0.2,0.5,0.3]),
"actif": rng.choice([0,1], size=n, p=[0.3,0.7])
})
return df
explications: variables plausibles, distributions maîtrisées et absence de lignes identiques à des personnes réelles.
cas 2: audit de collisions exactes
import hashlib
def row_hash(row):
s = "|".join(str(v) for v in row)
return hashlib.sha256(s.encode()).hexdigest()
def collision_rate(real_rows, synth_rows, sample=10000):
real_set = set(row_hash(r) for r in real_rows[:sample])
synth_set = set(row_hash(r) for r in synth_rows[:sample])
inter = real_set.intersection(synth_set)
return len(inter) / max(1, min(len(real_set), len(synth_set)))
explications: détecte toute ligne identique entre deux échantillons, à surveiller surtout quand le générateur est surentraîné.
gouvernance et traçabilité
- journaliser seeds, versions et paramètres
- attacher les rapports d’utilité et de confidentialité à chaque lot
- exposer une fiche dataset machine lisible
{
"dataset": "synthetic_customers_v1",
"version": "1.0.0",
"generated_at": "2024-06-09T10:00:00Z",
"method": "copula_gaussian",
"seed": 42,
"batches": 5,
"utility": {"auc_on_real": 0.79},
"privacy": {"nn_ratio": 1.35, "collisions": 0},
"contact": "data@exemple.com"
}
contrat d’usage
- interdiction de réidentifier ou de recouper pour cibler des personnes
- publication sous licence claire et compatible avec la finalité
- audits échantillonnés et retrait possible en cas d’abus
usage_terms:
reidentification: "strictement interdite"
redistribution: "permise sous la même licence"
attribution: "requise"
audit: "possible sur échantillons"
takedown: "processus établi avec délai"
erreurs courantes et solutions
- croire à l’anonymat parfait -> mettre des tests et des bornes
- jeux orphelins sans suivi -> ranger et dater dans un catalogue
- absence de documentation -> fournir une fiche courte et un changelog
- surajustement au réel -> ajouter du bruit et de la régularisation
- utilité non vérifiée -> toujours tester sur tâches cibles
faq
-
Les données synthétiques suffisent-elles pour la production ? Non. Elles servent à tester, documenter et préentraîner. La production exige des données réelles conformes.
-
Puis-je partager un jeu synthétique en externe sans contrat d’usage ? Non. Un contrat d’usage clair et traçable est indispensable.
-
Comment savoir si le jeu est trop proche des originaux ? Combinez collisions, distances et tests de membership inference simples. Si un seuil est dépassé, ajustez ou abandonnez.
-
Faut-il des grands modèles pour générer un jeu utile ? Non. Commencez avec des approches simples et explicables, validez, puis complexifiez si besoin.
-
Que documenter au minimum pour un partage responsable ? Méthode, version, seed, métriques d’utilité et de confidentialité, limites explicites et contact.