spham 8dfd897cac Ajout du lab de workflows reproductibles avec documentation complète
- Implémentation du notebook lab.ipynb avec code complet pour créer des workflows d'IA reproductibles
- Ajout d'un README.md pédagogique de 600+ lignes en français
- Configuration des graines aléatoires pour la reproductibilité
- Implémentation de la génération, division, normalisation et sauvegarde des données
- Création et entraînement d'un réseau de neurones avec TensorFlow/Keras
- Démonstration du rechargement et de la vérification de la reproductibilité

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2025-11-14 12:13:54 +01:00

🧠 Guide Complet : Workflows Reproductibles pour l'IA

Un tutoriel complet pour apprendre à créer des workflows d'IA reproductibles


📋 Table des Matières

  1. Démarrage Rapide
  2. Introduction aux Concepts
  3. Guide Étape par Étape
  4. Documentation Technique Détaillée
  5. Points Clés à Retenir
  6. Résolution des Problèmes
  7. Pour Aller Plus Loin

🚀 Démarrage Rapide

Prérequis

# Installer les dépendances nécessaires
pip install numpy tensorflow scikit-learn joblib jupyter

Lancer le Lab

# Ouvrir le notebook
jupyter notebook lab.ipynb

Exécuter les Cellules

  1. Exécutez les cellules une par une avec Shift + Enter
  2. Observez les résultats après chaque étape
  3. Vérifiez que la précision finale est identique après rechargement

Temps estimé : 15-20 minutes


🎓 Introduction aux Concepts

Qu'est-ce que la Reproductibilité ?

La reproductibilité signifie obtenir exactement les mêmes résultats chaque fois que vous exécutez votre code. C'est essentiel en IA pour :

Avantage Pourquoi c'est important
🐛 Débogage Identifier et corriger les erreurs facilement
🤝 Collaboration D'autres peuvent reproduire vos résultats
📊 Validation Prouver la fiabilité de vos modèles
🔬 Recherche Publier des résultats vérifiables
🏭 Production Garantir la cohérence en production

Pourquoi les Résultats Peuvent Varier ?

Sans reproductibilité, vous pouvez obtenir des résultats différents à cause de :

  1. Initialisation aléatoire des poids du réseau de neurones
  2. Division aléatoire des données train/test
  3. Ordre aléatoire des données pendant l'entraînement
  4. Dropout aléatoire dans les réseaux de neurones

La Solution : Les Graines Aléatoires (Random Seeds)

Une graine aléatoire est un nombre qui initialise un générateur de nombres pseudo-aléatoires. Avec la même graine, vous obtenez toujours la même séquence de nombres "aléatoires".

Analogie : C'est comme donner le même point de départ à une personne qui mélange un jeu de cartes. Si elle mélange toujours de la même façon depuis le même point, elle obtiendra toujours le même ordre de cartes.


📖 Guide Étape par Étape

Étape 1 : Configuration de l'Environnement

Code

import numpy as np
import tensorflow as tf
from tensorflow import keras
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
import random
import joblib

Explication

  • numpy : Calculs mathématiques et manipulation de tableaux
  • tensorflow/keras : Framework pour créer des réseaux de neurones
  • sklearn : Outils pour le machine learning (données, prétraitement, validation)
  • random : Générateur de nombres aléatoires Python
  • joblib : Sauvegarde et chargement d'objets Python

Étape 2 : Définir les Graines Aléatoires

Code

random.seed(42)
np.random.seed(42)
tf.random.set_seed(42)

Explication Détaillée

Fonction Bibliothèque Ce qu'elle contrôle
random.seed(42) Python standard Fonctions aléatoires de base
np.random.seed(42) NumPy Génération de tableaux aléatoires
tf.random.set_seed(42) TensorFlow Initialisation des poids, dropout, etc.

Pourquoi 42 ? C'est une convention (référence au Guide du voyageur galactique). Vous pouvez utiliser n'importe quel nombre, l'important est d'utiliser toujours le même.

À Retenir

Toujours définir les graines en premier Utiliser la même valeur (ici 42) partout Définir les graines pour toutes les bibliothèques utilisées


Étape 3 : Générer des Données Synthétiques

Code

X, y = make_classification(
    n_samples=1000,       # 1000 exemples
    n_features=20,        # 20 caractéristiques
    n_informative=15,     # 15 caractéristiques utiles
    n_redundant=5,        # 5 caractéristiques redondantes
    n_classes=2,          # Classification binaire (2 classes)
    random_state=42       # Graine aléatoire
)

Explication des Paramètres

Paramètre Valeur Signification
n_samples 1000 Nombre d'exemples générés
n_features 20 Nombre total de caractéristiques (colonnes)
n_informative 15 Caractéristiques réellement utiles pour la prédiction
n_redundant 5 Caractéristiques corrélées aux informatives (bruit)
n_classes 2 Nombre de classes à prédire (0 ou 1)
random_state 42 CRUCIAL pour la reproductibilité

Structure des Données

X : Matrice de forme (1000, 20)
    - 1000 lignes (exemples)
    - 20 colonnes (caractéristiques)

y : Vecteur de forme (1000,)
    - Contient 0 ou 1 pour chaque exemple

À Retenir

X contient les caractéristiques (données d'entrée) y contient les labels (ce qu'on veut prédire) random_state=42 garantit les mêmes données à chaque exécution


Étape 4 : Diviser les Données (Train/Test Split)

Code

X_train, X_test, y_train, y_test = train_test_split(
    X, y,
    test_size=0.2,
    random_state=42
)

Explication du Concept

Pourquoi diviser les données ?

  • Données d'entraînement (80%) : Le modèle apprend sur ces données
  • Données de test (20%) : On évalue la performance sur des données non vues

Analogie : C'est comme étudier avec des exercices (entraînement) puis passer un examen avec de nouvelles questions (test).

Résultat de la Division

X_train : 800 exemples pour l'entraînement
y_train : 800 labels correspondants

X_test : 200 exemples pour le test
y_test : 200 labels correspondants

À Retenir

80/20 est une proportion standard (peut être 70/30 ou 90/10) random_state=42 garantit la même division à chaque fois Ne jamais entraîner sur les données de test (c'est de la triche !)


Étape 5 : Normaliser les Données

Code

scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test)

Explication du StandardScaler

Qu'est-ce que la normalisation ?

Le StandardScaler transforme les données pour avoir :

  • Moyenne = 0
  • Écart-type = 1

Formule mathématique :

valeur_normalisée = (valeur - moyenne) / écart-type

Exemple Concret

Avant normalisation :
caractéristique_1 : [1, 2, 3, 1000]
caractéristique_2 : [0.1, 0.2, 0.3, 0.4]

Après normalisation :
caractéristique_1 : [-0.5, -0.4, -0.3, 2.1]
caractéristique_2 : [-0.8, -0.2, 0.4, 1.0]

Pourquoi C'est Important ?

Sans normalisation Avec normalisation
Les grandes valeurs dominent Toutes les caractéristiques ont la même échelle
Apprentissage lent Apprentissage plus rapide
Résultats instables Résultats stables

Différence entre fit_transform et transform

scaler.fit_transform(X_train)  # Apprend ET transforme
scaler.transform(X_test)       # Transforme seulement

IMPORTANT : On apprend les statistiques (moyenne, écart-type) uniquement sur les données d'entraînement, puis on applique la même transformation aux données de test.

À Retenir

Toujours fit sur train, transform sur test Évite les fuites de données (data leakage) Améliore les performances du modèle


Étape 6 : Sauvegarder les Données

Code

joblib.dump((X_train, y_train), 'train_data.pkl')
joblib.dump((X_test, y_test), 'test_data.pkl')

Explication

Pourquoi sauvegarder les données ?

  1. Reproductibilité : Garantir l'utilisation des mêmes données
  2. Efficacité : Ne pas recalculer à chaque fois
  3. Traçabilité : Savoir exactement quelles données ont été utilisées

Format .pkl : Format de sérialisation Python (pickle)

À Retenir

Sauvegarde après la division train/test Permet de recharger les mêmes données plus tard Essentiel pour comparer différents modèles sur les mêmes données


Étape 7 : Construire le Réseau de Neurones

Code

model = keras.Sequential([
    keras.layers.Dense(32, activation='relu', input_shape=(X_train.shape[1],)),
    keras.layers.Dense(16, activation='relu'),
    keras.layers.Dense(1, activation='sigmoid')
])

Architecture du Modèle

Entrée (20 caractéristiques)
    ↓
Couche 1 : 32 neurones + ReLU
    ↓
Couche 2 : 16 neurones + ReLU
    ↓
Couche 3 : 1 neurone + Sigmoid
    ↓
Sortie (probabilité 0-1)

Explication Détaillée de Chaque Couche

Couche Neurones Activation Rôle
Couche 1 32 ReLU Extraction de caractéristiques complexes
Couche 2 16 ReLU Combinaison des caractéristiques
Couche 3 1 Sigmoid Probabilité de la classe 1 (0 à 1)

Fonctions d'Activation

ReLU (Rectified Linear Unit)

ReLU(x) = max(0, x)

Exemple :
ReLU(-5) = 0
ReLU(0) = 0
ReLU(3) = 3
  • Avantage : Rapide, évite le gradient qui disparaît
  • Usage : Couches cachées

Sigmoid

Sigmoid(x) = 1 / (1 + e^(-x))

Exemple :
Sigmoid(-∞) = 0
Sigmoid(0) = 0.5
Sigmoid(+∞) = 1
  • Avantage : Sortie entre 0 et 1 (probabilité)
  • Usage : Couche de sortie pour classification binaire

À Retenir

Sequential = couches empilées les unes après les autres Dense = couche entièrement connectée ReLU pour les couches cachées, Sigmoid pour la sortie binaire


Étape 8 : Compiler le Modèle

Code

model.compile(
    optimizer='adam',
    loss='binary_crossentropy',
    metrics=['accuracy']
)

Explication des Paramètres

Optimizer : Adam

  • Rôle : Algorithme qui ajuste les poids du réseau
  • Pourquoi Adam ?
    • Adapte automatiquement le taux d'apprentissage
    • Fonctionne bien dans la plupart des cas
    • Combine les avantages de RMSprop et Momentum

Loss : Binary Crossentropy

  • Rôle : Mesure l'erreur du modèle
  • Formule : -[y*log(p) + (1-y)*log(1-p)]
  • Pourquoi ? Adapté à la classification binaire (0 ou 1)

Metrics : Accuracy

  • Rôle : Métrique de performance
  • Formule : (Nombre de prédictions correctes) / (Nombre total)
  • Exemple : 95% d'accuracy = 95 prédictions correctes sur 100

À Retenir

Adam est un excellent optimiseur par défaut binary_crossentropy pour la classification binaire Compiler avant d'entraîner le modèle


Étape 9 : Entraîner le Modèle

Code

model.fit(X_train, y_train, epochs=20, batch_size=32, validation_split=0.1)

Explication des Paramètres

Paramètre Valeur Signification
epochs 20 Nombre de passages complets sur les données
batch_size 32 Nombre d'exemples traités avant mise à jour des poids
validation_split 0.1 10% des données d'entraînement pour la validation

Comprendre l'Entraînement

Qu'est-ce qu'une Epoch ?

  • 1 epoch = le modèle voit tous les exemples d'entraînement une fois
  • 20 epochs = le modèle voit 20 fois chaque exemple

Qu'est-ce qu'un Batch ?

800 exemples d'entraînement / batch_size 32 = 25 batches par epoch

Epoch 1:
  Batch 1 : exemples 1-32    → mise à jour des poids
  Batch 2 : exemples 33-64   → mise à jour des poids
  ...
  Batch 25 : exemples 769-800 → mise à jour des poids

Validation Split

  • Prend 10% de X_train pour validation
  • Entraînement : 720 exemples (90% de 800)
  • Validation : 80 exemples (10% de 800)
  • Permet de surveiller le surapprentissage (overfitting)

Qu'Observer Pendant l'Entraînement ?

Epoch 1/20
25/25 [======] - loss: 0.6932 - accuracy: 0.5000 - val_loss: 0.6931 - val_accuracy: 0.5000

Epoch 20/20
25/25 [======] - loss: 0.1234 - accuracy: 0.9500 - val_loss: 0.1456 - val_accuracy: 0.9300
Métrique Signification
loss Erreur sur données d'entraînement (plus bas = mieux)
accuracy Précision sur données d'entraînement
val_loss Erreur sur données de validation
val_accuracy Précision sur données de validation

À Retenir

Loss diminue = le modèle apprend val_loss >> loss = surapprentissage (overfitting) Surveiller les deux métriques pour détecter les problèmes


Étape 🔟 : Évaluer le Modèle

Code

loss, accuracy = model.evaluate(X_test, y_test)
print(f"Test accuracy: {accuracy:.2f}")

Explication

Pourquoi évaluer sur les données de test ?

Données Utilisées pour Ce qu'elles mesurent
Entraînement Apprendre Performance sur données connues
Validation Ajuster Performance pendant l'entraînement
Test Évaluer Performance sur données inconnues

L'accuracy de test est la métrique finale qui compte !

Interpréter les Résultats

Test accuracy: 0.95  # 95% de précision

Cela signifie :

  • Sur 200 exemples de test
  • Le modèle prédit correctement 190 exemples
  • Et se trompe sur 10 exemples

À Retenir

Jamais entraîner sur les données de test L'accuracy de test mesure la vraie performance C'est le résultat qu'on doit reproduire


Étape 11 : Sauvegarder le Modèle

Code

model.save('my_model.keras')

Explication

Que sauvegarde-t-on ?

  1. Architecture du modèle (nombre de couches, neurones)
  2. Poids entraînés de tous les neurones
  3. Configuration de compilation (optimizer, loss)
  4. État de l'optimizer

Format .keras : Format moderne de Keras (recommandé vs .h5)

À Retenir

Sauvegarde après l'entraînement Contient tout pour réutiliser le modèle Permet de faire des prédictions sans ré-entraîner


Étape 12 : Recharger et Vérifier la Reproductibilité

Code

from tensorflow.keras.models import load_model

modelReloaded = load_model('my_model.keras')
X_train_reloaded, y_train_reloaded = joblib.load('train_data.pkl')
X_test_reloaded, y_test_reloaded = joblib.load('test_data.pkl')

loss_reloaded, accuracy_reloaded = modelReloaded.evaluate(X_test_reloaded, y_test_reloaded)
print(f"Test accuracy: {accuracy_reloaded:.2f}")

Vérification de la Reproductibilité

Test de Reproductibilité Réussi

Modèle original   : Test accuracy: 0.95
Modèle rechargé   : Test accuracy: 0.95

Si les valeurs sont différentes

  • Vérifier que toutes les graines aléatoires sont définies
  • Vérifier que les mêmes données sont utilisées
  • Vérifier les versions des bibliothèques

À Retenir

Les deux accuracies doivent être identiques C'est la preuve que le workflow est reproductible Vous pouvez partager votre travail en toute confiance


🔧 Documentation Technique Détaillée

Architecture Complète du Workflow

┌─────────────────────────────────────────────────────┐
│  1. INITIALISATION                                  │
│     • random.seed(42)                               │
│     • np.random.seed(42)                            │
│     • tf.random.set_seed(42)                        │
└─────────────────┬───────────────────────────────────┘
                  ↓
┌─────────────────────────────────────────────────────┐
│  2. GÉNÉRATION DES DONNÉES                          │
│     • make_classification(random_state=42)          │
│     • X: (1000, 20), y: (1000,)                     │
└─────────────────┬───────────────────────────────────┘
                  ↓
┌─────────────────────────────────────────────────────┐
│  3. DIVISION TRAIN/TEST                             │
│     • train_test_split(random_state=42)             │
│     • Train: 800, Test: 200                         │
└─────────────────┬───────────────────────────────────┘
                  ↓
┌─────────────────────────────────────────────────────┐
│  4. NORMALISATION                                   │
│     • StandardScaler.fit_transform(X_train)         │
│     • StandardScaler.transform(X_test)              │
└─────────────────┬───────────────────────────────────┘
                  ↓
┌─────────────────────────────────────────────────────┐
│  5. SAUVEGARDE DES DONNÉES                          │
│     • joblib.dump(train_data.pkl)                   │
│     • joblib.dump(test_data.pkl)                    │
└─────────────────┬───────────────────────────────────┘
                  ↓
┌─────────────────────────────────────────────────────┐
│  6. CONSTRUCTION DU MODÈLE                          │
│     • Input(20) → Dense(32) → Dense(16) → Dense(1)  │
│     • ReLU, ReLU, Sigmoid                           │
└─────────────────┬───────────────────────────────────┘
                  ↓
┌─────────────────────────────────────────────────────┐
│  7. COMPILATION                                     │
│     • optimizer='adam'                              │
│     • loss='binary_crossentropy'                    │
└─────────────────┬───────────────────────────────────┘
                  ↓
┌─────────────────────────────────────────────────────┐
│  8. ENTRAÎNEMENT                                    │
│     • model.fit(epochs=20, batch_size=32)           │
│     • validation_split=0.1                          │
└─────────────────┬───────────────────────────────────┘
                  ↓
┌─────────────────────────────────────────────────────┐
│  9. ÉVALUATION                                      │
│     • model.evaluate(X_test, y_test)                │
└─────────────────┬───────────────────────────────────┘
                  ↓
┌─────────────────────────────────────────────────────┐
│  10. SAUVEGARDE DU MODÈLE                           │
│      • model.save('my_model.keras')                 │
└─────────────────┬───────────────────────────────────┘
                  ↓
┌─────────────────────────────────────────────────────┐
│  11. RECHARGEMENT ET VÉRIFICATION                   │
│      • load_model(), joblib.load()                  │
│      • Vérification: accuracy identique ✓           │
└─────────────────────────────────────────────────────┘

Paramètres Importants

make_classification

X, y = make_classification(
    n_samples=1000,          # Nombre d'exemples
    n_features=20,           # Nombre de caractéristiques
    n_informative=15,        # Caractéristiques informatives
    n_redundant=5,           # Caractéristiques redondantes
    n_classes=2,             # Nombre de classes
    random_state=42,         # CRUCIAL: graine aléatoire
    flip_y=0.0,             # Pourcentage de labels bruités (défaut: 0.01)
    class_sep=1.0,          # Séparation entre les classes (défaut: 1.0)
    shuffle=True            # Mélanger les exemples (défaut: True)
)

train_test_split

X_train, X_test, y_train, y_test = train_test_split(
    X, y,
    test_size=0.2,          # 20% pour le test
    train_size=None,        # Automatique (1 - test_size)
    random_state=42,        # CRUCIAL: graine aléatoire
    shuffle=True,           # Mélanger avant division (défaut: True)
    stratify=None           # Préserver la distribution des classes (None par défaut)
)

StandardScaler

scaler = StandardScaler(
    copy=True,              # Copier les données (défaut: True)
    with_mean=True,         # Centrer autour de 0 (défaut: True)
    with_std=True           # Mettre à l'échelle à 1 (défaut: True)
)

model.fit

history = model.fit(
    X_train, y_train,
    epochs=20,              # Nombre d'epochs
    batch_size=32,          # Taille des batchs
    validation_split=0.1,   # % pour validation
    validation_data=None,   # Ou tuple (X_val, y_val)
    verbose=1,              # Affichage (0: rien, 1: barre, 2: epoch)
    shuffle=True,           # Mélanger à chaque epoch (défaut: True)
    callbacks=None          # Callbacks (early stopping, etc.)
)

Versions Recommandées

numpy==1.24.3
tensorflow==2.15.0
scikit-learn==1.3.2
joblib==1.3.2

Installer avec :

pip install numpy==1.24.3 tensorflow==2.15.0 scikit-learn==1.3.2 joblib==1.3.2

💡 Points Clés à Retenir

Les 10 Commandements de la Reproductibilité

  1. Tu définiras les graines aléatoires au début de ton code
  2. Tu utiliseras random_state dans toutes les fonctions qui l'acceptent
  3. Tu sauvegarderas tes données après division train/test
  4. Tu ne fit que sur train et transform sur test
  5. Tu ne regarderas jamais les données de test avant l'évaluation finale
  6. Tu sauvegarderas ton modèle après entraînement
  7. Tu documenteras les versions de tes bibliothèques
  8. Tu vérifieras la reproductibilité en rechargeant tout
  9. Tu utiliseras le même environnement (virtualenv, conda)
  10. Tu partageras ton code avec les instructions complètes

Checklist de Reproductibilité

Avant de partager votre travail, vérifiez :

  • Toutes les graines aléatoires sont définies
  • random_state=42 est utilisé partout
  • Les données train/test sont sauvegardées
  • Le modèle est sauvegardé
  • Les versions des bibliothèques sont documentées
  • Le code est testé sur une machine différente
  • Les résultats sont identiques après rechargement
  • Un README explique comment exécuter le code

Erreurs Courantes à Éviter

Erreur Conséquence Solution
Oublier random_state Résultats différents à chaque fois Toujours définir random_state=42
Fit sur test Data leakage Fit sur train uniquement
Ne pas sauvegarder les données Impossible de reproduire exactement Sauvegarder après split
Mélanger train et test Évaluation biaisée Garder séparés
Différentes versions de bibliothèques Résultats différents Documenter les versions

🐛 Résolution des Problèmes

Problème 1 : Résultats Différents à Chaque Exécution

Symptôme : L'accuracy change à chaque fois

Solutions :

# 1. Vérifier que TOUTES les graines sont définies
random.seed(42)
np.random.seed(42)
tf.random.set_seed(42)

# 2. Vérifier random_state dans train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=42)

# 3. Vérifier random_state dans make_classification
X, y = make_classification(..., random_state=42)

Problème 2 : Erreur de Shape

Symptôme : ValueError: Input shape mismatch

Solutions :

# Vérifier les shapes
print(f"X_train shape: {X_train.shape}")
print(f"y_train shape: {y_train.shape}")

# S'assurer que input_shape correspond
input_shape=(X_train.shape[1],)  # Pas X_train.shape !

Problème 3 : Loss ne Diminue Pas

Symptôme : La loss reste élevée ou augmente

Solutions :

# 1. Vérifier que les données sont normalisées
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)

# 2. Essayer un taux d'apprentissage plus petit
from tensorflow.keras.optimizers import Adam
optimizer = Adam(learning_rate=0.001)
model.compile(optimizer=optimizer, ...)

# 3. Augmenter le nombre d'epochs
model.fit(..., epochs=50)

Problème 4 : Overfitting

Symptôme : train_accuracy >> val_accuracy

Solutions :

# 1. Ajouter du Dropout
model = keras.Sequential([
    keras.layers.Dense(32, activation='relu'),
    keras.layers.Dropout(0.3),  # Dropout 30%
    keras.layers.Dense(16, activation='relu'),
    keras.layers.Dropout(0.3),
    keras.layers.Dense(1, activation='sigmoid')
])

# 2. Réduire la complexité du modèle
model = keras.Sequential([
    keras.layers.Dense(16, activation='relu'),  # Moins de neurones
    keras.layers.Dense(1, activation='sigmoid')
])

# 3. Ajouter de la régularisation L2
from tensorflow.keras.regularizers import l2
keras.layers.Dense(32, activation='relu', kernel_regularizer=l2(0.01))

Problème 5 : Erreur lors du Rechargement

Symptôme : FileNotFoundError ou modèle ne charge pas

Solutions :

# 1. Vérifier que le fichier existe
import os
print(os.path.exists('my_model.keras'))  # Doit être True

# 2. Utiliser le chemin absolu
import os
model_path = os.path.abspath('my_model.keras')
model = load_model(model_path)

# 3. Vérifier la version de TensorFlow
import tensorflow as tf
print(tf.__version__)  # Doit être >= 2.12 pour .keras

📚 Pour Aller Plus Loin

Améliorations Possibles

1. Ajouter des Callbacks

from tensorflow.keras.callbacks import EarlyStopping, ModelCheckpoint

# Arrêt anticipé si pas d'amélioration
early_stop = EarlyStopping(
    monitor='val_loss',
    patience=5,          # Attendre 5 epochs
    restore_best_weights=True
)

# Sauvegarder le meilleur modèle
checkpoint = ModelCheckpoint(
    'best_model.keras',
    monitor='val_accuracy',
    save_best_only=True
)

model.fit(
    X_train, y_train,
    epochs=100,
    callbacks=[early_stop, checkpoint]
)

2. Hyperparamètres Tuning

# Tester différentes architectures
architectures = [
    [32, 16],
    [64, 32, 16],
    [128, 64, 32]
]

for arch in architectures:
    model = build_model(arch)
    model.fit(...)
    # Comparer les résultats

3. Cross-Validation

from sklearn.model_selection import KFold

kfold = KFold(n_splits=5, shuffle=True, random_state=42)

for fold, (train_idx, val_idx) in enumerate(kfold.split(X)):
    X_train_fold = X[train_idx]
    y_train_fold = y[train_idx]
    # Entraîner et évaluer

4. Logging et Tracking

import mlflow

mlflow.start_run()
mlflow.log_params({
    "epochs": 20,
    "batch_size": 32,
    "architecture": "32-16-1"
})

history = model.fit(...)

mlflow.log_metrics({
    "accuracy": accuracy,
    "loss": loss
})
mlflow.end_run()

Concepts Avancés

Stratified Split

Pour les datasets déséquilibrés :

X_train, X_test, y_train, y_test = train_test_split(
    X, y,
    stratify=y,  # Préserve la distribution des classes
    random_state=42
)

K-Fold Cross-Validation

Pour une évaluation plus robuste :

from sklearn.model_selection import cross_val_score
from sklearn.neural_network import MLPClassifier

clf = MLPClassifier(random_state=42)
scores = cross_val_score(clf, X, y, cv=5)
print(f"Accuracy: {scores.mean():.2f} (+/- {scores.std():.2f})")

Data Augmentation

Pour augmenter la taille du dataset :

from sklearn.utils import resample

# Bootstrap sampling
X_resampled, y_resampled = resample(
    X_train, y_train,
    n_samples=len(X_train) * 2,
    random_state=42
)

Ressources Supplémentaires

Documentation Officielle

Tutoriels Recommandés

Livres

  • "Hands-On Machine Learning" - Aurélien Géron
  • "Deep Learning with Python" - François Chollet
  • "Python Machine Learning" - Sebastian Raschka

📝 Résumé en 5 Minutes

Ce que Vous Avez Appris

  1. La reproductibilité est essentielle en IA
  2. Les graines aléatoires permettent d'obtenir les mêmes résultats
  3. Diviser train/test correctement est crucial
  4. Normaliser les données améliore l'apprentissage
  5. Sauvegarder modèle et données permet de reproduire

Code Minimal Reproductible

import numpy as np
import tensorflow as tf
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
import random

# 1. Graines aléatoires
random.seed(42)
np.random.seed(42)
tf.random.set_seed(42)

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

# 3. Division et normalisation
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=42)
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test)

# 4. Modèle
model = tf.keras.Sequential([
    tf.keras.layers.Dense(32, activation='relu', input_shape=(20,)),
    tf.keras.layers.Dense(1, activation='sigmoid')
])
model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])

# 5. Entraînement
model.fit(X_train, y_train, epochs=20, batch_size=32)

# 6. Évaluation
loss, accuracy = model.evaluate(X_test, y_test)
print(f"Accuracy: {accuracy:.2f}")

# 7. Sauvegarde
model.save('model.keras')

🎯 Conclusion

Félicitations ! Vous avez maintenant une compréhension complète des workflows reproductibles en IA.

N'oubliez pas :

  • Toujours définir les graines aléatoires
  • Utiliser random_state partout
  • Sauvegarder modèles et données
  • Vérifier la reproductibilité

Prochaines étapes :

  1. Pratiquez avec vos propres datasets
  2. Expérimentez avec différentes architectures
  3. Explorez les techniques avancées
  4. Partagez votre travail reproductible !

📞 Support

Si vous rencontrez des problèmes :

  1. Relisez la section Résolution des Problèmes
  2. Vérifiez les versions de vos bibliothèques
  3. Consultez la documentation officielle
  4. Recherchez sur Stack Overflow

Bon apprentissage ! 🚀

Description
No description provided
Readme 231 KiB
Languages
Jupyter Notebook 59.4%
Roff 40.6%