🧠 AI / ML

ai-ml-dataset-builder

Construction et curation de datasets pour l'entraînement ML (nettoyage, augmentation, annotation, split, versioning, qualité, datacard)

⚡ Installation & lancement en 1 commande

Copiez-collez dans votre terminal : le skill s'installe dans ~/.claude/skills et Claude Code se lance directement dessus.

macOS / Linux
curl -fsSL https://raw.githubusercontent.com/khalilbenaz/claude-skills-collection/main/install.sh | sh -s -- ai-ml-dataset-builder --launch
Windows (PowerShell)
iex "& { $(iwr -useb https://raw.githubusercontent.com/khalilbenaz/claude-skills-collection/main/install.ps1) } ai-ml-dataset-builder -Launch"

🚀 Déjà installé ?

claude "/ai-ml-dataset-builder"

Ou tapez /ai-ml-dataset-builder dans une session Claude Code, ou décrivez simplement votre besoin — le skill se déclenche automatiquement via le skill-router.

📦 Installation manuelle

git clone https://github.com/khalilbenaz/claude-skills-collection.git cp -r claude-skills-collection/skills/ai-ml-dataset-builder ~/.claude/skills/

Payload du plugin : skills/ai-ml-dataset-builder · source éditable : ai-ml-skills/dataset-builder

📖 Manuel

Dataset Builder

Guide opérationnel pour construire, curate et maintenir des datasets ML de production.


Étape 1 — Cadrer les besoins

QuestionDécision
Tâche ML ?Classif / régression / détection / génération
Volume minimum viable ?Règle empirique : ≥ 1 000 exemples/classe pour classif tabulaire, ≥ 10 k images pour CNN
Déséquilibre acceptable ?Ratio max 1:10 sans traitement ; au-delà → SMOTE/oversampling
Contraintes légales ?RGPD / consentement / droit à l'oubli à vérifier avant collecte

Fixer un schéma de données dès le départ :

# Exemple de schéma avec Pydantic
from pydantic import BaseModel, Field
from typing import Literal

class Sample(BaseModel):
    text: str = Field(min_length=10)
    label: Literal["positive", "negative", "neutral"]
    source: str
    collected_at: str  # ISO 8601

Étape 2 — Collecter les données brutes

Choisir le format de stockage selon le cas d'usage :

FormatQuand l'utiliser
ParquetDonnées tabulaires, requêtes analytiques, > 100 k lignes
JSONLTexte, NLP, LLM fine-tuning
TFRecord / WebDatasetImages/audio à grande échelle, streaming
CSVPrototypage, petits datasets (< 50 k lignes)

Collecter avec provenance :

# Exemple : snapshot DVC d'une source API
dvc run -n collect_api \
  -d scripts/collect.py \
  -o data/raw/samples.jsonl \
  python scripts/collect.py --source api --date 2026-06-24

Déduplication à la collecte (texte) :

import hashlib, json

seen = set()
with open("data/raw/samples.jsonl", "w") as out:
    for record in raw_records:
        h = hashlib.md5(record["text"].encode()).hexdigest()
        if h not in seen:
            seen.add(h)
            out.write(json.dumps(record, ensure_ascii=False) + "\n")

Étape 3 — Nettoyer et prétraiter

Pipeline type avec Pandas + Pandera :

import pandas as pd
import pandera as pa

schema = pa.DataFrameSchema({
    "text": pa.Column(str, pa.Check(lambda s: s.str.len() > 10)),
    "label": pa.Column(str, pa.Check.isin(["positive", "negative", "neutral"])),
})

df = pd.read_parquet("data/raw/samples.parquet")
df = df.drop_duplicates(subset=["text"])
df = df.dropna(subset=["label"])
df = schema.validate(df)  # lève une exception si non-conforme
df.to_parquet("data/clean/samples.parquet", index=False)

Quasi-doublons (fuzzy) :

pip install datasketch
# MinHash LSH pour détection de duplicats near-exact à grande échelle

Étape 4 — Annoter et labelliser

Critères de choix de l'outil d'annotation :

OutilType de donnéesPoints forts
Label StudioTexte, images, audio, vidéoOpen-source, tout-en-un
ProdigyNLP/texteAnnotation active learning intégrée
CVATImages / vidéoBounding box, segmentation
ArgillaLLM feedback, RLHFInterface moderne, intégration HuggingFace

Mesurer l'accord inter-annotateurs avant de valider le guide :

from sklearn.metrics import cohen_kappa_score

kappa = cohen_kappa_score(annotator_1_labels, annotator_2_labels)
# Seuil acceptable : kappa > 0.7
# < 0.6 → guide d'annotation à retravailler
print(f"Cohen's Kappa: {kappa:.3f}")

Étape 5 — Augmenter les données

Texte

# back-translation légère avec deep-translator
from deep_translator import GoogleTranslator

def back_translate(text, lang="es"):
    translated = GoogleTranslator(source="fr", target=lang).translate(text)
    return GoogleTranslator(source=lang, target="fr").translate(translated)

Images (Albumentations)

import albumentations as A

transform = A.Compose([
    A.HorizontalFlip(p=0.5),
    A.RandomBrightnessContrast(p=0.3),
    A.Rotate(limit=15, p=0.4),
    A.GaussNoise(p=0.2),
])
augmented = transform(image=img)["image"]

Tabulaire (déséquilibre de classes)

from imblearn.over_sampling import SMOTE

sm = SMOTE(sampling_strategy="minority", random_state=42)
X_res, y_res = sm.fit_resample(X_train, y_train)

Règle : n'augmenter que le train set, jamais validation ni test.


Étape 6 — Splits train / validation / test

from sklearn.model_selection import train_test_split

# Stratifié (classification)
X_train, X_tmp, y_train, y_tmp = train_test_split(
    X, y, test_size=0.2, stratify=y, random_state=42
)
X_val, X_test, y_val, y_test = train_test_split(
    X_tmp, y_tmp, test_size=0.5, stratify=y_tmp, random_state=42
)
# Résultat : 80% / 10% / 10%

Cas spéciaux :

CasStratégie
Données temporellesSplit chronologique strict — pas de shuffle
Données groupées (patient, user)GroupShuffleSplit — un groupe = un seul split
Très petit dataset (< 5 k)Cross-validation k-fold stratifiée
# Split temporel
df_sorted = df.sort_values("date")
n = len(df_sorted)
train = df_sorted.iloc[:int(n*0.8)]
val   = df_sorted.iloc[int(n*0.8):int(n*0.9)]
test  = df_sorted.iloc[int(n*0.9):]

Étape 7 — Valider et documenter

Rapport de qualité automatique

pip install great_expectations
great_expectations init
great_expectations suite new  # définir les expectations
great_expectations checkpoint run my_checkpoint  # générer le rapport HTML

Dataset card (HuggingFace standard)

# README.md du dataset (format HF)
---
dataset_info:
  features:
    - name: text
      dtype: string
    - name: label
      dtype: class_label
  splits:
    - name: train
      num_examples: 8000
    - name: validation
      num_examples: 1000
    - name: test
      num_examples: 1000
license: cc-by-4.0
---

Versioning avec DVC

dvc add data/clean/samples.parquet
git add data/clean/samples.parquet.dvc .gitignore
git commit -m "feat(data): v1.2 — +2k samples, dedup applied"
git tag dataset-v1.2
dvc push  # stockage distant (S3, GCS, Azure…)

Étape 8 — Maintenir et itérer

# Détecter un drift de distribution (evidently)
from evidently.report import Report
from evidently.metric_preset import DataDriftPreset

report = Report(metrics=[DataDriftPreset()])
report.run(reference_data=df_train, current_data=df_new)
report.save_html("drift_report.html")

Anti-patterns et pièges

PiègeConséquenceRemède
Data leakage : normalisation fit sur tout le datasetRésultats gonflés, modèle inutilisable en prodFit scaler/encodeur uniquement sur train
Test set contaminé : augmentation avant splitMétriques non représentativesToujours splitter avant d'augmenter
Label imbalance ignoréAccuracy trompeuse, mauvaise généralisationF1-macro, stratification, SMOTE
Doublons cross-splitSurestimation des performancesDédupliquer avant de splitter
Guide d'annotation vagueKappa < 0.6, labels incohérentsExemples concrets pour chaque cas-limite
Dataset sans versionExpériences non reproductiblesDVC ou LakeFS obligatoire dès le début
Collecte sans consentementViolation RGPD, dette légaleVérifier licences et consentements avant toute collecte

Bonnes pratiques 2026