spham 320ed709f0 fix: Correction du formatage Markdown dans EXAMEN.md
Ajout de lignes vides entre les options A/B/C/D pour un affichage correct.
En Markdown, un simple retour à la ligne ne crée pas de saut de ligne visible.

Pourquoi cette erreur ? Je génère le texte ligne par ligne mais j'oublie que
Markdown nécessite une ligne vide entre chaque paragraphe ou deux espaces
à la fin d'une ligne pour créer un saut de ligne.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2025-11-12 18:43:22 +01:00

18 KiB
Raw Blame History

Examen - Généralisation des Modèles ML

Ce document contient des questions pour tester et renforcer votre compréhension des concepts du lab.


Partie 1 : Questions Théoriques (QCM)

Question 1 : Définition de la généralisation

Qu'est-ce qu'un modèle qui généralise bien ?

A) Un modèle avec 100% d'accuracy sur le training set

B) Un modèle qui performe bien sur des données jamais vues

C) Un modèle qui converge rapidement

D) Un modèle avec beaucoup de paramètres

Voir la réponse

Réponse : B

Un modèle qui généralise bien est capable de prédire correctement sur des données qu'il n'a jamais vues pendant l'entraînement. C'est la métrique la plus importante en ML. La performance sur le training set seule ne suffit pas (option A peut indiquer de l'overfitting).


Question 2 : Split des données

Pourquoi utilise-t-on 3 ensembles (Train/Validation/Test) au lieu de 2 ?

A) Pour avoir plus de données

B) Le validation set détecte l'overfitting pendant l'entraînement

C) C'est une convention arbitraire

D) Pour ralentir l'entraînement

Voir la réponse

Réponse : B

Le validation set permet de détecter l'overfitting pendant l'entraînement et d'ajuster les hyperparamètres sans biaiser l'évaluation finale. Le test set reste complètement isolé pour une évaluation non biaisée. Si on n'avait que Train/Test, on serait tenté d'ajuster les hyperparamètres en fonction du test set, ce qui invaliderait son rôle.


Question 3 : Early Stopping

Que fait l'Early Stopping quand patience=3 et min_delta=0.01 ?

A) Arrête après 3 epochs

B) Arrête si val_loss n'améliore pas de 0.01 pendant 3 epochs consécutifs

C) Arrête si train_loss augmente

D) Réduit le learning rate de 0.01

Voir la réponse

Réponse : B

L'Early Stopping surveille la val_loss. Si elle ne diminue pas d'au moins min_delta (0.01) pendant patience (3) epochs consécutifs, l'entraînement s'arrête et les meilleurs poids sont restaurés. Cela prévient l'overfitting.


Question 4 : Learning Rate Scheduler

Avec ReduceLROnPlateau(factor=0.5, patience=2) et LR initial de 0.05, quel sera le LR après 2 epochs sans amélioration ?

A) 0.05

B) 0.025

C) 0.0125

D) 0.01

Voir la réponse

Réponse : B

Après 2 epochs sans amélioration de val_loss, le LR est multiplié par factor (0.5). Donc : 0.05 × 0.5 = 0.025. Si val_loss stagne encore 2 epochs, il sera réduit à 0.0125, etc.


Question 5 : Normalisation

Pourquoi normaliser les features avec StandardScaler ?

A) Pour rendre les données plus lisibles

B) Pour accélérer le code

C) Pour que toutes les features contribuent équitablement au gradient

D) Pour réduire la taille des données

Voir la réponse

Réponse : C

Sans normalisation, les features à grande échelle (ex: revenu en milliers) dominent le gradient descent par rapport aux features à petite échelle (ex: age). StandardScaler transforme toutes les features pour avoir moyenne=0 et écart-type=1, permettant une convergence plus rapide et stable.


Partie 2 : Analyse de Cas

Cas 1 : Diagnostic d'overfitting

Analysez ces métriques :

Epoch 5:  train_loss=0.25, val_loss=0.28, train_acc=92%, val_acc=90%
Epoch 10: train_loss=0.10, val_loss=0.30, train_acc=97%, val_acc=89%
Epoch 15: train_loss=0.05, val_loss=0.38, train_acc=99%, val_acc=85%

Questions :

  1. Quel problème identifiez-vous ?
  2. À quelle epoch aurait dû s'arrêter le modèle ?
  3. Quelles solutions proposez-vous ?
Voir l'analyse complète

1. Problème : Overfitting sévère

Signes :

  • train_loss diminue continuellement (0.25 → 0.05)
  • val_loss augmente (0.28 → 0.38)
  • Gap croissant entre train_acc et val_acc (99% vs 85%)
  • Le modèle mémorise au lieu de généraliser

2. Arrêt optimal : Epoch 5

C'est le point où val_loss est la plus basse (0.28) et le gap train/val est minimal (2%).

3. Solutions :

  • Early stopping avec patience=2-3
  • Régularisation : L2, Dropout
  • Simplifier l'architecture (moins de neurones/couches)
  • Augmenter les données d'entraînement
  • Réduire le nombre d'epochs max

Cas 2 : Matrice de confusion

                Prédictions
                0     1
Réel    0    [[180   20]
        1     [ 5   195]]

Questions :

  1. Calculez l'accuracy
  2. Calculez la precision pour la classe 1
  3. Calculez le recall pour la classe 0
  4. Le modèle est-il équilibré ?
Voir les calculs

1. Accuracy

Accuracy = (TP + TN) / Total
         = (195 + 180) / (180 + 20 + 5 + 195)
         = 375 / 400
         = 93.75%

2. Precision (classe 1)

Precision = TP / (TP + FP)
          = 195 / (195 + 20)
          = 195 / 215
          = 90.7%

3. Recall (classe 0)

Recall = TN / (TN + FP)
       = 180 / (180 + 20)
       = 180 / 200
       = 90%

4. Équilibre : Oui

Les performances sont similaires pour les deux classes (90-91%). Pas de biais flagrant vers une classe. Le modèle généralise bien sur les deux types de prédictions.


Cas 3 : Choix d'hyperparamètres

Vous avez ces résultats sur le validation set :

Config LR initial Patience Epoch arrêt Val accuracy
A 0.1 2 5 85%
B 0.05 3 10 97%
C 0.01 5 25 92%

Question : Quelle configuration choisissez-vous et pourquoi ?

Voir l'analyse

Choix : Configuration B

Raisons :

  • Meilleure performance : 97% d'accuracy (la plus élevée)
  • Convergence raisonnable : 10 epochs (ni trop rapide comme A, ni trop lent comme C)
  • LR équilibré : 0.05 permet exploration + affinage

Pourquoi pas A ?

  • Trop rapide (5 epochs) → risque d'underfitting
  • Accuracy basse (85%) → le modèle n'a pas assez appris

Pourquoi pas C ?

  • Trop lent (25 epochs) → coût d'entraînement élevé
  • Accuracy inférieure à B (92% < 97%)
  • LR trop faible (0.01) → convergence lente

Important : Cette décision est basée sur le validation set. L'évaluation finale se fera sur le test set.


Partie 3 : Exercices Pratiques

Exercice 1 : Prédire le comportement

Code :

early_stop = EarlyStopping(
    monitor='val_loss',
    patience=2,
    min_delta=0.05,
    restore_best_weights=True
)

Historique d'entraînement :

Epoch 1: val_loss = 0.50
Epoch 2: val_loss = 0.45
Epoch 3: val_loss = 0.43
Epoch 4: val_loss = 0.42
Epoch 5: val_loss = 0.41

Questions :

  1. À quelle epoch le modèle s'arrêtera-t-il ?
  2. Quels poids seront restaurés ?
Voir la solution

1. Arrêt : Epoch 5

Analyse epoch par epoch :

  • Epoch 1 → 2 : amélioration de 0.05 (0.50 - 0.45 = 0.05) = min_delta
  • Epoch 2 → 3 : amélioration de 0.02 (0.45 - 0.43 = 0.02) < min_delta (compteur = 1)
  • Epoch 3 → 4 : amélioration de 0.01 (0.43 - 0.42 = 0.01) < min_delta (compteur = 2)
  • Compteur atteint patience=2 → STOP

2. Poids restaurés : Epoch 2

Les meilleurs poids sont ceux de l'epoch 2 (dernière fois où min_delta a été atteint). val_loss = 0.45.


Exercice 2 : Compléter le code

Complétez ce code pour implémenter un modèle avec généralisation :

from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
import tensorflow as tf

# Données
X, y = make_classification(n_samples=1000, n_features=10, random_state=42)

# TODO: Normaliser X
scaler = ___________
X = scaler.___________

# TODO: Split en Train (64%), Val (16%), Test (20%)
X_trainval, X_test, y_trainval, y_test = train_test_split(X, y, test_size=___, random_state=42)
X_train, X_val, y_train, y_val = train_test_split(X_trainval, y_trainval, test_size=___, random_state=42)

# TODO: Créer le modèle (2 couches denses)
model = tf.keras.Sequential([
    tf.keras.layers.Dense(___, activation='___', input_shape=(10,)),
    tf.keras.layers.Dense(___, activation='___'),
    tf.keras.layers.Dense(1, activation='sigmoid')
])

# TODO: Compiler avec Adam (lr=0.01)
model.compile(
    optimizer=tf.keras.optimizers.Adam(learning_rate=___),
    loss='___',
    metrics=['accuracy']
)

# TODO: Early stopping (patience=3, min_delta=0.01)
early_stop = tf.keras.callbacks.EarlyStopping(
    monitor='___',
    patience=___,
    min_delta=___,
    restore_best_weights=True
)
Voir la solution
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
import tensorflow as tf

# Données
X, y = make_classification(n_samples=1000, n_features=10, random_state=42)

# Normaliser X
scaler = StandardScaler()
X = scaler.fit_transform(X)

# Split en Train (64%), Val (16%), Test (20%)
X_trainval, X_test, y_trainval, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
X_train, X_val, y_train, y_val = train_test_split(X_trainval, y_trainval, test_size=0.2, random_state=42)

# Créer le modèle (2 couches denses)
model = tf.keras.Sequential([
    tf.keras.layers.Dense(32, activation='relu', input_shape=(10,)),
    tf.keras.layers.Dense(16, activation='relu'),
    tf.keras.layers.Dense(1, activation='sigmoid')
])

# Compiler avec Adam (lr=0.01)
model.compile(
    optimizer=tf.keras.optimizers.Adam(learning_rate=0.01),
    loss='binary_crossentropy',
    metrics=['accuracy']
)

# Early stopping (patience=3, min_delta=0.01)
early_stop = tf.keras.callbacks.EarlyStopping(
    monitor='val_loss',
    patience=3,
    min_delta=0.01,
    restore_best_weights=True
)

Explications :

  • StandardScaler() : Normalisation (moyenne=0, std=1)
  • test_size=0.2 : 20% pour test, puis 20% de 80% = 16% pour validation
  • Dense(32/16, 'relu') : Architecture progressive avec non-linéarité
  • learning_rate=0.01 : Valeur standard pour démarrer
  • 'binary_crossentropy' : Loss pour classification binaire
  • monitor='val_loss' : Surveiller l'overfitting

Exercice 3 : Débugger le code

Ce code a un problème. Identifiez-le et corrigez-le :

X, y = make_classification(n_samples=500, n_features=15, random_state=42)

# Split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
X_train, X_val, y_train, y_val = train_test_split(X_train, y_train, test_size=0.2, random_state=42)

# Normalisation
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_val = scaler.fit_transform(X_val)
X_test = scaler.fit_transform(X_test)

# Entraînement
model.fit(X_train, y_train, validation_data=(X_val, y_val), epochs=50)

# Évaluation
y_pred = model.predict(X_test)

Question : Quel est le problème ? Comment le corriger ?

Voir le problème et la solution

Problème : Data leakage dans la normalisation

Ligne problématique :

X_val = scaler.fit_transform(X_val)    # ❌ ERREUR
X_test = scaler.fit_transform(X_test)  # ❌ ERREUR

Pourquoi c'est un problème ?

fit_transform() calcule la moyenne et l'écart-type sur les données fournies. En utilisant fit sur val et test, vous introduisez une fuite d'information : le scaler "voit" les statistiques de ces ensembles.

Solution correcte :

# Normalisation
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)  # ✅ fit + transform sur train
X_val = scaler.transform(X_val)          # ✅ transform seulement (utilise stats de train)
X_test = scaler.transform(X_test)        # ✅ transform seulement (utilise stats de train)

Règle d'or : Ne jamais fit sur validation ou test. Toujours utiliser les statistiques (moyenne, écart-type) calculées sur le training set uniquement.


Partie 4 : Questions Ouvertes

Question 1 : Trade-offs

Expliquez le trade-off entre un learning rate élevé et un learning rate faible.

Voir la réponse attendue

Learning Rate élevé (ex: 0.1)

Avantages :

  • Convergence rapide (moins d'epochs nécessaires)
  • Échappe aux minima locaux
  • Exploration large de l'espace des solutions

Inconvénients :

  • Peut "sauter" au-dessus de l'optimum
  • Instabilité (loss qui oscille)
  • Risque de divergence

Learning Rate faible (ex: 0.001)

Avantages :

  • Convergence précise vers l'optimum
  • Stabilité (descente graduelle)
  • Moins de risque de divergence

Inconvénients :

  • Convergence très lente
  • Risque de bloquer dans un minimum local
  • Nécessite beaucoup d'epochs

Solution : Learning Rate adaptatif

Utiliser un scheduler comme ReduceLROnPlateau pour combiner les avantages : commencer avec un LR élevé (exploration rapide) puis réduire progressivement (affinage précis).


Question 2 : Biais d'évaluation

Pourquoi est-il crucial de NE JAMAIS utiliser le test set pour ajuster les hyperparamètres ?

Voir la réponse attendue

Raison : Biais d'optimisation

Si vous ajustez les hyperparamètres (patience, learning rate, architecture) en regardant les performances sur le test set, vous introduisez un biais : vous optimisez indirectement pour le test set.

Conséquence :

Le test set perd son rôle d'évaluation non biaisée. Les performances mesurées seront surestimées car le modèle a été "ajusté" pour ce dataset spécifique.

Analogie :

C'est comme un étudiant qui révise en regardant les questions de l'examen final. Il aura une bonne note, mais ça ne reflète pas sa vraie compréhension du sujet. En production, sur de vraies nouvelles données, le modèle performera moins bien.

Processus correct :

  1. Train set : Entraîner le modèle
  2. Validation set : Ajuster les hyperparamètres
  3. Test set : Évaluation finale (UNE SEULE FOIS, aucun ajustement après)

Le test set doit rester "caché" jusqu'à l'évaluation finale.


Question 3 : Cas réel

Vous déployez votre modèle en production. Après 1 mois :

  • Performance sur données de production : 75%
  • Performance sur test set (lab) : 97%

Quelles sont les causes possibles et les solutions ?

Voir l'analyse

Causes possibles :

  1. Distribution shift (concept drift)

    • Les données de production sont différentes des données d'entraînement
    • Solution : Réentraîner régulièrement avec nouvelles données
  2. Biais dans le test set

    • Le test set ne représente pas bien la réalité
    • Solution : Collecter un test set plus représentatif
  3. Overfitting au lab

    • Le modèle a été trop optimisé pour les données du lab
    • Solution : Cross-validation, datasets plus variés
  4. Features manquantes en production

    • Certaines features utilisées en train ne sont pas disponibles en prod
    • Solution : Pipeline de features robuste, monitoring
  5. Problèmes de preprocessing

    • Normalisation différente entre train et production
    • Solution : Versionner le scaler, pipeline unifié
  6. Données de mauvaise qualité en production

    • Valeurs manquantes, erreurs de saisie
    • Solution : Validation des données en entrée

Actions immédiates :

  1. Analyser la distribution des données de production vs train
  2. Identifier les features qui dérivent le plus
  3. Monitorer les prédictions incertaines
  4. Réentraîner avec un mix train + production
  5. Mettre en place un système de feedback loop

Partie 5 : Flashcards (Révision rapide)

Epoch

Définition Une passe complète sur l'ensemble du training set

Batch

Définition Sous-ensemble de données traité simultanément (ex: 32 échantillons)

Loss function

Rôle Mesure l'écart entre prédictions et vraies valeurs. Le modèle cherche à la minimiser.

Backpropagation

Définition Méthode de calcul des gradients via la chaîne des dérivées. Permet de mettre à jour les poids.

ReLU

Formule et rôle f(x) = max(0, x). Introduit la non-linéarité, évite vanishing gradient.

Sigmoid

Utilisation Classification binaire. Transforme la sortie en probabilité [0, 1].

Precision

Formule TP / (TP + FP). Parmi les prédictions positives, combien sont correctes ?

Recall

Formule TP / (TP + FN). Parmi les vrais positifs, combien ont été détectés ?

Overfitting

Signes Train accuracy >> Test accuracy. Val_loss augmente alors que train_loss diminue.

Underfitting

Signes Train et test accuracy basses et similaires. Le modèle est trop simple.

Barème et Auto-évaluation

Partie 1 (QCM) : 5 points (1 point par question) Partie 2 (Analyse de cas) : 9 points (3 points par cas) Partie 3 (Exercices pratiques) : 9 points (3 points par exercice) Partie 4 (Questions ouvertes) : 9 points (3 points par question)

Total : 32 points

Échelle :

  • 28-32 points : Excellent (87-100%)
  • 24-27 points : Très bien (75-86%)
  • 20-23 points : Bien (62-74%)
  • 16-19 points : Assez bien (50-61%)
  • < 16 points : Revoir les concepts fondamentaux

Conseils de révision

  1. Commencez par les flashcards pour mémoriser les définitions
  2. Faites les QCM pour tester votre compréhension théorique
  3. Pratiquez les exercices de code pour la manipulation concrète
  4. Analysez les cas pour développer l'intuition
  5. Répondez aux questions ouvertes pour la réflexion approfondie

Astuce : Ne regardez pas les réponses immédiatement. Essayez d'abord de répondre, puis vérifiez et comprenez vos erreurs.

Bon apprentissage ! 🚀