32 KiB
🧠 Guide Complet : Workflows Reproductibles pour l'IA
Un tutoriel complet pour apprendre à créer des workflows d'IA reproductibles
📋 Table des Matières
- Démarrage Rapide
- Introduction aux Concepts
- Guide Étape par Étape
- Documentation Technique Détaillée
- Points Clés à Retenir
- Résolution des Problèmes
- 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
- Exécutez les cellules une par une avec
Shift + Enter - Observez les résultats après chaque étape
- 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 :
- Initialisation aléatoire des poids du réseau de neurones
- Division aléatoire des données train/test
- Ordre aléatoire des données pendant l'entraînement
- 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
- ✅
Xcontient les caractéristiques (données d'entrée) - ✅
ycontient les labels (ce qu'on veut prédire) - ✅
random_state=42garantit 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 ?
- Reproductibilité : Garantir l'utilisation des mêmes données
- Efficacité : Ne pas recalculer à chaque fois
- 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 1️⃣1️⃣ : Sauvegarder le Modèle
Code
model.save('my_model.keras')
Explication
Que sauvegarde-t-on ?
- Architecture du modèle (nombre de couches, neurones)
- Poids entraînés de tous les neurones
- Configuration de compilation (optimizer, loss)
- É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 1️⃣2️⃣ : 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é
- ✅ Tu définiras les graines aléatoires au début de ton code
- ✅ Tu utiliseras random_state dans toutes les fonctions qui l'acceptent
- ✅ Tu sauvegarderas tes données après division train/test
- ✅ Tu ne fit que sur train et transform sur test
- ✅ Tu ne regarderas jamais les données de test avant l'évaluation finale
- ✅ Tu sauvegarderas ton modèle après entraînement
- ✅ Tu documenteras les versions de tes bibliothèques
- ✅ Tu vérifieras la reproductibilité en rechargeant tout
- ✅ Tu utiliseras le même environnement (virtualenv, conda)
- ✅ 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=42est 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
- La reproductibilité est essentielle en IA
- Les graines aléatoires permettent d'obtenir les mêmes résultats
- Diviser train/test correctement est crucial
- Normaliser les données améliore l'apprentissage
- 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_statepartout - ✅ Sauvegarder modèles et données
- ✅ Vérifier la reproductibilité
Prochaines étapes :
- Pratiquez avec vos propres datasets
- Expérimentez avec différentes architectures
- Explorez les techniques avancées
- Partagez votre travail reproductible !
📞 Support
Si vous rencontrez des problèmes :
- Relisez la section Résolution des Problèmes
- Vérifiez les versions de vos bibliothèques
- Consultez la documentation officielle
- Recherchez sur Stack Overflow
Bon apprentissage ! 🚀