🧠 AI / ML

ai-ml-model-fine-tuner

Guide pour le fine-tuning de modèles ML/LLM (LoRA, QLoRA, PEFT, datasets, hyperparamètres) — workflow étape par étape, snippets copiables, critères de choix, anti-patterns 2026

⚡ 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-model-fine-tuner --launch
Windows (PowerShell)
iex "& { $(iwr -useb https://raw.githubusercontent.com/khalilbenaz/claude-skills-collection/main/install.ps1) } ai-ml-model-fine-tuner -Launch"

🚀 Déjà installé ?

claude "/ai-ml-model-fine-tuner"

Ou tapez /ai-ml-model-fine-tuner 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-model-fine-tuner ~/.claude/skills/

Payload du plugin : skills/ai-ml-model-fine-tuner · source éditable : ai-ml-skills/model-fine-tuner

📖 Manuel

Model Fine-Tuner

Critères de décision : quelle méthode choisir ?

SituationMéthode recommandée
GPU < 24 Go, LLM > 7BQLoRA 4-bit
GPU 24–80 Go, besoin de vitesseLoRA bfloat16
Petite tâche de classificationFull fine-tune BERT/DeBERTa
Tâche très spécifique, budget computeIA3 ou Prefix Tuning
Modèle > 70B, multi-GPUFSDP + LoRA
Données < 500 exemplesPrompt engineering d'abord, fine-tune ensuite

Workflow

1. Baseline — mesurer avant de toucher quoi que ce soit

# Exemple : évaluer Mistral-7B zero-shot sur votre tâche
python eval.py --model mistralai/Mistral-7B-v0.3 --dataset data/test.jsonl --metric f1

Sans baseline chiffrée, l'amélioration est invérifiable. Loguer la baseline dans MLflow/W&B immédiatement.

2. Préparer le dataset

Format instruction/response (standard Alpaca / ChatML) :

# Format Alpaca
{"instruction": "Classe cette phrase.", "input": "Le produit est excellent.", "output": "positif"}

# Format ChatML (préféré pour les LLM modernes)
{"messages": [
  {"role": "system", "content": "Tu es un classificateur de sentiment."},
  {"role": "user", "content": "Le produit est excellent."},
  {"role": "assistant", "content": "positif"}
]}

Validation obligatoire avant entraînement :

from datasets import load_dataset
ds = load_dataset("json", data_files={"train": "train.jsonl", "test": "test.jsonl"})

# Vérifier la distribution des labels
from collections import Counter
Counter(ds["train"]["label"])

# Vérifier les longueurs de tokens
from transformers import AutoTokenizer
tok = AutoTokenizer.from_pretrained("mistralai/Mistral-7B-v0.3")
lengths = [len(tok(x["instruction"] + x["output"])["input_ids"]) for x in ds["train"]]
print(f"max={max(lengths)}, p95={sorted(lengths)[int(0.95*len(lengths))]}")

Règle : si p95 > max_seq_length, tronquer ou filtrer — ne jamais silencieusement perdre des tokens en production.

3. Configurer LoRA / QLoRA

from transformers import AutoModelForCausalLM, BitsAndBytesConfig
from peft import LoraConfig, get_peft_model, TaskType
import torch

# QLoRA 4-bit (≈ 5 Go pour 7B)
bnb_config = BitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_quant_type="nf4",
    bnb_4bit_compute_dtype=torch.bfloat16,
    bnb_4bit_use_double_quant=True,
)

model = AutoModelForCausalLM.from_pretrained(
    "mistralai/Mistral-7B-v0.3",
    quantization_config=bnb_config,
    device_map="auto",
)

lora_config = LoraConfig(
    r=16,              # rang : 8 (léger) → 64 (expressif)
    lora_alpha=32,     # scaling = alpha/r, garder alpha = 2*r
    target_modules=["q_proj", "k_proj", "v_proj", "o_proj"],
    lora_dropout=0.05,
    bias="none",
    task_type=TaskType.CAUSAL_LM,
)

model = get_peft_model(model)
model.print_trainable_parameters()
# → "trainable params: 4,194,304 || all params: 3,756,462,080 || trainable%: 0.1117"

Choix du rang r :

4. Hyperparamètres d'entraînement

from transformers import TrainingArguments
from trl import SFTTrainer

args = TrainingArguments(
    output_dir="./checkpoints",
    num_train_epochs=3,
    per_device_train_batch_size=4,
    gradient_accumulation_steps=4,      # batch effectif = 16
    learning_rate=2e-4,                 # LoRA : 1e-4 à 3e-4 ; full FT : 5e-5
    lr_scheduler_type="cosine",
    warmup_ratio=0.05,
    weight_decay=0.01,
    bf16=True,
    gradient_checkpointing=True,        # économise ~30 % VRAM
    logging_steps=10,
    save_strategy="epoch",
    evaluation_strategy="epoch",
    load_best_model_at_end=True,
    report_to="wandb",                  # ou "mlflow"
)

trainer = SFTTrainer(
    model=model,
    args=args,
    train_dataset=ds["train"],
    eval_dataset=ds["test"],
    dataset_text_field="text",
    max_seq_length=2048,
    peft_config=lora_config,
)
trainer.train()

Référence GPU / batch size pour Mistral-7B QLoRA :

VRAMbatch_sizegrad_accumbatch effectif
8 Go11616
16 Go2816
24 Go4416
80 Go (A100)16116

5. Monitoring et early stopping

from transformers import EarlyStoppingCallback

trainer.add_callback(EarlyStoppingCallback(early_stopping_patience=3))

Surveiller dans W&B :

6. Évaluation post-entraînement

# Métriques standards selon la tâche
from evaluate import load

# Génération
rouge = load("rouge")
bleu  = load("sacrebleu")

# Classification
accuracy = load("accuracy")
f1       = load("f1")

results = rouge.compute(predictions=preds, references=refs, use_stemmer=True)
print(results)  # {'rouge1': 0.52, 'rouge2': 0.30, 'rougeL': 0.48, ...}

Tests manuels indispensables : 20–30 exemples représentatifs + 10 cas limites. Les métriques automatiques ne capturent pas les hallucinations ou les formats cassés.

7. Fusion et export

# Fusionner l'adaptateur LoRA dans le modèle de base
from peft import PeftModel

base_model = AutoModelForCausalLM.from_pretrained(
    "mistralai/Mistral-7B-v0.3", torch_dtype=torch.bfloat16
)
merged = PeftModel.from_pretrained(base_model, "./checkpoints/best")
merged = merged.merge_and_unload()

merged.save_pretrained("./final-model", safe_serialization=True)
tokenizer.save_pretrained("./final-model")

# Export GGUF pour déploiement CPU/edge (via llama.cpp)
# python llama.cpp/convert_hf_to_gguf.py ./final-model --outtype q5_k_m

8. Itération ciblée

Analyser les erreurs par catégorie :

errors = [(ex["input"], pred, ref) for pred, ref in zip(preds, refs) if pred != ref]
# Regrouper par type d'erreur → enrichir le dataset là où ça échoue

Ajouter des exemples synthétiques (GPT-4o, Claude) pour les cas rares, en vérifiant manuellement un échantillon de 10 %.


Anti-patterns et pièges

Données

Entraînement

Évaluation

Export


Bonnes pratiques 2026