M1 INFORMATIQUE — ANNÉE 2024-2025
Python &
Machine Learning
Polycopié de cours complet
Installation & Environnement
NumPy · Pandas
Workflow ML
Régression · Classification
Optimisation · Cross-Validation
Datasets générés — Exemples pas à pas — Algorithmes commentés
Python & Machine Learning — Polycopié M1 Institut d'Informatique
Chapitre 1
Installation & Environnement de Travail
Python · Jupyter · Bibliothèques essentielles
1.1 Installer Python
Python est le langage de référence en Data Science et Machine Learning. Nous utilisons Python 3.10+. La distribution
Anaconda est recommandée car elle embarque la majorité des bibliothèques scientifiques.
Méthode OS Commande / URL Remarque
Anaconda Tous [Link]/download Recommandé étudiants
Python officiel Tous [Link] Installation minimale
Homebrew macOS brew install python3 Développeurs macOS
Ubuntu/Debia
apt sudo apt install python3 Linux natif
n
Étape 1. Télécharger Anaconda sur [Link] et lancer l'installeur.
Étape 2. Cocher «Add Anaconda to PATH» (ou utiliser Anaconda Prompt sur Windows).
Étape 3. Vérifier l'installation : python --version et conda --version.
Étape 4. Créer un environnement isolé pour le cours (bonne pratique !).
# Vérification
python --version # Python 3.11.x
conda --version # conda 23.x
# Créer un environnement dédié
conda create -n ml_m1 python=3.11 -y
conda activate ml_m1
# OU avec venv (sans Anaconda)
python3 -m venv ml_m1
source ml_m1/bin/activate # Linux / macOS
ml_m1\Scripts\activate # Windows
1.2 Installer les bibliothèques
Un seul pip install suffit pour disposer de tout l'écosystème nécessaire au cours. Chaque bibliothèque joue un rôle
précis :
pip install numpy pandas matplotlib scikit-learn jupyter seaborn
Bibliothèque Rôle principal Version min.
NumPy Calcul numérique, tableaux N-dim 1.24
Pandas Manipulation de données tabulaires 2.0
Matplotlib Visualisation 2D 3.7
Seaborn Visualisation statistique avancée 0.12
Scikit-learn Algorithmes ML, preprocessing, évaluation 1.3
Python & Machine Learning — M1 Informatique 2
Python & Machine Learning — Polycopié M1 Institut d'Informatique
Jupyter Notebook interactif (code + doc) 7.0
1.3 Lancer Jupyter Notebook
Étape 1. Dans votre terminal (environnement activé) : jupyter notebook
Étape 2. Un onglet s'ouvre dans le navigateur sur [Link]
Étape 3. Cliquer New → Python 3 pour créer un notebook.
Étape 4. Chaque cellule s'exécute avec Shift+Enter.
jupyter notebook # Lance le serveur
# OU JupyterLab (interface moderne)
pip install jupyterlab
jupyter lab
★ Points clés
Toujours activer son environnement avant de lancer Jupyter
Un notebook = fichier .ipynb (JSON) combinant code, texte, graphiques
Raccourci Shift+Enter pour exécuter une cellule et passer à la suivante
Préférer conda/venv pour isoler les dépendances de chaque projet
Python & Machine Learning — M1 Informatique 3
Python & Machine Learning — Polycopié M1 Institut d'Informatique
Chapitre 2
NumPy & Pandas
Fondations du calcul scientifique et de la manipulation de données
2.1 NumPy — Calcul Vectorisé
NumPy (Numerical Python) fournit l'objet ndarray : un tableau multidimensionnel homogène ultra-rapide grâce à une
implémentation C. Règle d'or : éviter les boucles Python, vectoriser avec NumPy.
import numpy as np
# --- Création de tableaux ---
a = [Link]([1, 2, 3, 4, 5]) # 1-D, dtype=int64
b = [Link]((3, 4)) # matrice 3x4 de zéros
c = [Link](0, 10, 2) # [0 2 4 6 8]
d = [Link](0, 1, 5) # [0. 0.25 0.5 0.75 1.]
e = [Link](42); e=[Link](3,3) # matrice aléatoire
# --- Opérations vectorisées (sans boucle!) ---
x = [Link]([10, 20, 30, 40])
print(x * 2) # [20 40 60 80]
print(x ** 2) # [100 400 900 1600]
print([Link](x)) # [3.16 4.47 5.47 6.32]
# --- Indexing & Slicing ---
mat = [Link](12).reshape(3, 4)
print(mat[1, 2]) # 6 (ligne 1, col 2)
print(mat[:, 1]) # [1 5 9] (toute la colonne 1)
print(mat[mat > 7]) # [8 9 10 11] (masque booléen)
# --- Statistiques ---
print([Link](), [Link](), [Link]())
■ Attention
[Link]() ≠ [Link]() : la première suit N(0,1), la seconde U[0,1)
reshape(-1, 1) transforme un vecteur 1D en colonne 2D (nécessaire pour Scikit-learn)
2.2 Pandas — Manipulation de Données
Pandas offre deux structures : Series (1D) et DataFrame (2D, similaire à une feuille Excel). C'est l'outil central de tout
pipeline de données.
import pandas as pd
# --- Créer un DataFrame ---
data = {
'nom': ['Alice','Bob','Charlie','Diana','Eve'],
'age': [23, 35, 28, 42, 31],
'salaire':[48000, 72000, 55000, 89000, 61000],
'dept': ['IT','RH','IT','Finance','RH']
}
df = [Link](data)
Python & Machine Learning — M1 Informatique 4
Python & Machine Learning — Polycopié M1 Institut d'Informatique
# --- Exploration de base ---
[Link] # (5, 4)
[Link] # types de chaque colonne
[Link]() # stats : mean, std, min, max…
[Link]().sum() # nombre de valeurs manquantes
# --- Sélection ---
df['salaire'] # Series d'une colonne
df[['nom','salaire']] # sous-DataFrame
[Link][df['age'] > 30] # filtre booléen
[Link][1:3, 0:2] # sélection par position
# --- Agrégation ---
[Link]('dept')['salaire'].mean()
# Finance 89000.0
# IT 51500.0
# RH 66500.0
★ Points clés
[Link]() donne un résumé rapide : types, valeurs non-nulles, mémoire
[Link][] utilise les labels, [Link][] utilise les positions entières
groupby → split / apply / combine : paradigme central des agrégations
pd.read_csv("[Link]") charge un CSV en une seule ligne
Python & Machine Learning — M1 Informatique 5
Python & Machine Learning — Polycopié M1 Institut d'Informatique
Chapitre 3
Datasets du Cours & Visualisation
Génération des deux jeux de données utilisés tout au long du cours
3.1 Dataset de Régression — Prix de maisons
Nous générons un dataset synthétique de 300 maisons. La variable cible est le prix (en k€), fonction de la surface, du
nombre de chambres, de l'ancienneté et de la distance au centre-ville. Ce dataset sera utilisé pour tous les exemples de
régression.
import numpy as np
import pandas as pd
[Link](42) # reproductibilité
n = 300
surface = [Link](30, 200, n) # m²
chambres = [Link](1, 6, n) # 1-5
anciente = [Link](0, 50, n) # années
distance = [Link](0.5, 30, n) # km
# Formule réaliste + bruit gaussien
prix = (surface * 2.1
+ chambres * 12
- anciente * 0.8
- distance * 3.5
+ [Link](0, 15, n)) # bruit
df_reg = [Link]({
'surface': surface, 'chambres': chambres,
'anciennete': anciente, 'distance_centre': distance,
'prix_k': prix
})
print(df_reg.describe().round(1))
# surface : mean=113.5 std=48.5 min=30 max=199
# prix_k : mean=229.8 std=117.2 min=-6 max=482
■ Attention
Les prix légèrement négatifs (artefact du bruit) seront gérés en preprocessing : [Link](df_reg["prix_k"], 50,
None) pour plafonner à 50k€ minimum.
3.2 Dataset de Classification — Admission universitaire
Dataset de 400 étudiants avec 4 features : note de bac, score TOEFL, expérience de recherche et classement de
l'université d'origine. La cible binaire est admis (1) / refusé (0).
[Link](0)
n = 400
note_bac = [Link](12, 3, n).clip(0, 20) # /20
toefl = [Link](105, 12, n).clip(60,120) # /120
recherche = [Link](1, 0.45, n) # 0/1
Python & Machine Learning — M1 Informatique 6
Python & Machine Learning — Polycopié M1 Institut d'Informatique
rang_univ = [Link](1, 6, n) # 1=meilleure
# Score d'admission latent
score = (note_bac*0.4 + toefl*0.08 + recherche*3
- rang_univ*1.5 + [Link](0,2,n))
admis = (score > [Link]()).astype(int) # 50% environ
df_clf = [Link]({
'note_bac': note_bac.round(1),
'toefl': [Link](0).astype(int),
'recherche': recherche,
'rang_univ': rang_univ,
'admis': admis
})
print(df_clf['admis'].value_counts())
# 1 (admis) : ~200 0 (refusé) : ~200
3.3 Visualisation exploratoire (EDA)
Avant tout modèle, on visualise les données. Cette étape s'appelle l'Analyse Exploratoire (EDA).
import [Link] as plt
import seaborn as sns
fig, axes = [Link](1, 2, figsize=(12, 4))
# Distribution de la cible (régression)
axes[0].hist(df_reg['prix_k'], bins=30, color='steelblue', edgecolor='white')
axes[0].set_title('Distribution des prix (k€)')
axes[0].set_xlabel('Prix (k€)')
# Corrélation surface vs prix
axes[1].scatter(df_reg['surface'], df_reg['prix_k'],
alpha=0.4, color='steelblue')
axes[1].set_title('Surface vs Prix')
axes[1].set_xlabel('Surface (m²)')
axes[1].set_ylabel('Prix (k€)')
plt.tight_layout()
[Link]()
# Matrice de corrélation (heatmap)
corr = df_reg.corr()
[Link](corr, annot=True, fmt='.2f', cmap='coolwarm')
[Link]('Corrélations — Dataset Régression')
[Link]()
★ Points clés
EDA = observer distributions, valeurs aberrantes, corrélations AVANT de modéliser
Une corrélation élevée entre features peut indiquer de la multicolinéarité
[Link](df) trace toutes les corrélations croisées en une ligne
[Link](figsize=(10,8)) donne les distributions de toutes les colonnes d'un coup
Python & Machine Learning — M1 Informatique 7
Python & Machine Learning — Polycopié M1 Institut d'Informatique
Chapitre 4
Workflow ML & Preprocessing
Pipeline de bout en bout : données → modèle → évaluation
4.1 Le Workflow Machine Learning
Tout projet ML suit les mêmes grandes étapes. Les maîtriser garantit des résultats reproductibles et fiables :
1. Collecte Obtenir les données brutes (CSV, API, BDD…)
2. EDA Explorer, visualiser, comprendre les données
3. Preprocessing Nettoyage, encodage, normalisation
4. Split Séparer Train / Validation / Test
5. Entraînement Ajuster le modèle sur Train
6. Évaluation Mesurer les performances sur Test
7. Optimisation Tuning des hyperparamètres
8. Déploiement Mettre le modèle en production
4.2 Séparation Train / Test
On ne doit jamais évaluer un modèle sur les données d'entraînement. La règle standard : 80% train / 20% test.
Scikit-learn fournit train_test_split.
from sklearn.model_selection import train_test_split
# --- Régression ---
X_reg = df_reg[['surface','chambres','anciennete','distance_centre']]
y_reg = df_reg['prix_k']
X_train_r, X_test_r, y_train_r, y_test_r = train_test_split(
X_reg, y_reg,
test_size=0.20, # 20% pour le test
random_state=42 # graine pour reproductibilité
)
print(f'Train: {len(X_train_r)} | Test: {len(X_test_r)}')
# Train: 240 | Test: 60
# --- Classification ---
X_clf = df_clf[['note_bac','toefl','recherche','rang_univ']]
y_clf = df_clf['admis']
X_train_c, X_test_c, y_train_c, y_test_c = train_test_split(
X_clf, y_clf,
test_size=0.20,
random_state=42,
stratify=y_clf # conserve les proportions 50/50
)
Python & Machine Learning — M1 Informatique 8
Python & Machine Learning — Polycopié M1 Institut d'Informatique
4.3 Normalisation des Features
Pourquoi normaliser ? La surface (30–200) et le TOEFL (60–120) ont des échelles très différentes. Certains
algorithmes (régression linéaire, SVM, KNN) y sont très sensibles. On centre-réduit avec StandardScaler : chaque
feature a moyenne 0 et écart-type 1.
Formule :
z = (x - mean) / std
from [Link] import StandardScaler
scaler = StandardScaler()
# IMPORTANT : fit UNIQUEMENT sur train, transform sur train ET test
X_train_r_sc = scaler.fit_transform(X_train_r) # apprend mean/std + transforme
X_test_r_sc = [Link](X_test_r) # applique les MEMES stats
# Vérification
print(X_train_r_sc.mean(axis=0).round(3)) # ~ [0, 0, 0, 0]
print(X_train_r_sc.std(axis=0).round(3)) # ~ [1, 1, 1, 1]
■ Attention
Ne jamais faire fit_transform sur le test set : cela provoquerait une fuite de données (data leakage).
MinMaxScaler est une alternative : ramène les valeurs dans [0,1]. Préférer StandardScaler pour les algo
gaussiens.
★ Points clés
train_test_split(stratify=y) est indispensable en classification pour équilibrer les classes
StandardScaler : moyenne=0, std=1 | MinMaxScaler : min=0, max=1
Le preprocessing fait partie du modèle : il faut le sauvegarder pour la production
Pipeline Scikit-learn enchaîne scaler + modèle en un seul objet
Python & Machine Learning — M1 Informatique 9
Python & Machine Learning — Polycopié M1 Institut d'Informatique
Chapitre 5
Algorithmes de Régression
Prédire une valeur continue — Dataset : prix de maisons
5.1 Régression Linéaire
La régression linéaire modélise la relation entre les features et la cible par une combinaison affine. C'est l'algorithme
fondateur, simple mais puissant.
Modèle :
y_pred = w0 + w1*surface + w2*chambres + w3*anciennete + w4*distance
Objectif : minimiser la somme des erreurs quadratiques (MSE) :
MSE = (1/n) * somme[ (y_i - y_pred_i)^2 ]
from sklearn.linear_model import LinearRegression
from [Link] import mean_squared_error, r2_score
import numpy as np
# Étape 1 : Instancier le modèle
lr = LinearRegression()
# Étape 2 : Entraîner sur le jeu d'entraînement
[Link](X_train_r_sc, y_train_r)
# Étape 3 : Prédire sur le jeu de test
y_pred_lr = [Link](X_test_r_sc)
# Étape 4 : Évaluer
mse = mean_squared_error(y_test_r, y_pred_lr)
rmse = [Link](mse)
r2 = r2_score(y_test_r, y_pred_lr)
print(f'RMSE : {rmse:.1f} k€') # ~ 17.3 k€
print(f'R² : {r2:.3f}') # ~ 0.978
# Coefficients appris
features = ['surface','chambres','anciennete','distance_centre']
for feat, coef in zip(features, lr.coef_):
print(f' {feat:20s} : {coef:+.2f}')
Interprétation : R² ≈ 0.978 signifie que le modèle explique 97,8% de la variance des prix. RMSE ≈ 17 k€ est l'erreur typique.
5.2 Régression Ridge (régularisation L2)
Quand les features sont corrélées, la régression linéaire ordinaire peut surajuster. Ridge ajoute une pénalité sur la
norme des coefficients, évitant leur explosion.
Coût Ridge = MSE + alpha * somme(w_i^2)
from sklearn.linear_model import Ridge
ridge = Ridge(alpha=1.0) # alpha = force de régularisation
[Link](X_train_r_sc, y_train_r)
y_pred_ridge = [Link](X_test_r_sc)
Python & Machine Learning — M1 Informatique 10
Python & Machine Learning — Polycopié M1 Institut d'Informatique
rmse_r = [Link](mean_squared_error(y_test_r, y_pred_ridge))
r2_r = r2_score(y_test_r, y_pred_ridge)
print(f'Ridge — RMSE: {rmse_r:.1f} R²: {r2_r:.3f}')
5.3 Random Forest Regressor
Random Forest construit de nombreux arbres de décision sur des sous-échantillons aléatoires (bootstrap) et moyenne
leurs prédictions. Avantages : robuste, gère la non-linéarité, pas besoin de normalisation.
from [Link] import RandomForestRegressor
rf_reg = RandomForestRegressor(
n_estimators=100, # nombre d'arbres
max_depth=8, # profondeur max par arbre
random_state=42
)
rf_reg.fit(X_train_r, y_train_r) # pas besoin de normaliser
y_pred_rf = rf_reg.predict(X_test_r)
rmse_rf = [Link](mean_squared_error(y_test_r, y_pred_rf))
r2_rf = r2_score(y_test_r, y_pred_rf)
print(f'RF — RMSE: {rmse_rf:.1f} R²: {r2_rf:.3f}')
# Importance des features
for feat, imp in sorted(zip(features, rf_reg.feature_importances_),
key=lambda x: -x[1]):
print(f' {feat:20s} : {imp:.3f}')
Algorithme RMSE (k€) R² Normalisation ? Interprétable ?
Régression Linéaire ~17 0.978 Oui Très
Ridge ~17 0.977 Oui Oui
Random Forest ~12 0.990 Non Partiellement
★ Points clés
R² proche de 1 = bon modèle | R² < 0 = modèle pire que la moyenne
RMSE s'exprime dans la même unité que la cible (ici k€)
Random Forest est souvent meilleur sans tuning grâce au bagging
Pour la régression linéaire : toujours normaliser avant d'entraîner
Python & Machine Learning — M1 Informatique 11
Python & Machine Learning — Polycopié M1 Institut d'Informatique
Chapitre 6
Algorithmes de Classification
Prédire une classe — Dataset : admission universitaire
6.1 Régression Logistique
Malgré son nom, la régression logistique est un algorithme de classification binaire. Elle modélise la probabilité
d'appartenir à la classe 1 via la fonction sigmoïde :
P(y=1|x) = 1 / (1 + exp(-(w0 + w1*x1 + ...)))
from sklearn.linear_model import LogisticRegression
from [Link] import (accuracy_score, classification_report,
confusion_matrix)
# Normalisation (importante pour la reg. logistique)
from [Link] import StandardScaler
scaler_c = StandardScaler()
X_train_c_sc = scaler_c.fit_transform(X_train_c)
X_test_c_sc = scaler_c.transform(X_test_c)
logreg = LogisticRegression(max_iter=500, random_state=42)
[Link](X_train_c_sc, y_train_c)
y_pred_lr_c = [Link](X_test_c_sc)
print(f'Accuracy : {accuracy_score(y_test_c, y_pred_lr_c):.3f}')
print(classification_report(y_test_c, y_pred_lr_c,
target_names=['Refusé','Admis']))
Le rapport de classification donne precision, recall et F1 pour chaque classe.
6.2 K-Nearest Neighbors (KNN)
KNN classe un point selon la majorité de ses k plus proches voisins dans l'espace des features. Algorithme
non-paramétrique, paresseux (lazy learning).
from [Link] import KNeighborsClassifier
knn = KNeighborsClassifier(n_neighbors=7) # k=7 (impair pour éviter les ex-aequo)
[Link](X_train_c_sc, y_train_c)
y_pred_knn = [Link](X_test_c_sc)
print(f'KNN (k=7) Accuracy : {accuracy_score(y_test_c, y_pred_knn):.3f}')
# Trouver le meilleur k par recherche brute
from sklearn.model_selection import cross_val_score
k_scores = []
for k in range(1, 21):
knn_k = KNeighborsClassifier(n_neighbors=k)
score = cross_val_score(knn_k, X_train_c_sc, y_train_c,
cv=5, scoring='accuracy').mean()
k_scores.append(score)
best_k = k_scores.index(max(k_scores)) + 1
print(f'Meilleur k = {best_k}, score CV = {max(k_scores):.3f}')
Python & Machine Learning — M1 Informatique 12
Python & Machine Learning — Polycopié M1 Institut d'Informatique
6.3 Random Forest Classifier
from [Link] import RandomForestClassifier
rf_clf = RandomForestClassifier(n_estimators=100, random_state=42)
rf_clf.fit(X_train_c, y_train_c) # pas besoin de normaliser
y_pred_rfc = rf_clf.predict(X_test_c)
print(f'RF Accuracy : {accuracy_score(y_test_c, y_pred_rfc):.3f}')
# Matrice de confusion
cm = confusion_matrix(y_test_c, y_pred_rfc)
print('Matrice de confusion:')
print(f' VN={cm[0,0]} FP={cm[0,1]}')
print(f' FN={cm[1,0]} VP={cm[1,1]}')
6.4 Métriques de Classification
L'accuracy seule est insuffisante (classes déséquilibrées). Les métriques complémentaires sont :
Métrique Formule Quand l'utiliser ?
Accuracy (VP+VN)/(VP+VN+FP+FN) Classes équilibrées
Précision VP/(VP+FP) Minimiser les faux positifs
Rappel (Recall) VP/(VP+FN) Minimiser les faux négatifs
F1-Score 2*(P*R)/(P+R) Compromis Précision/Rappel
AUC-ROC Aire sous la courbe ROC Évaluation globale
★ Points clés
Confusion matrix : VP=Vrais Positifs, VN=Vrais Négatifs, FP=Faux Positifs, FN=Faux Négatifs
Médicale/fraude → privilégier le Recall (minimiser FN)
Spam → privilégier la Précision (minimiser FP)
ROC-AUC est indépendante du seuil de décision
Python & Machine Learning — M1 Informatique 13
Python & Machine Learning — Polycopié M1 Institut d'Informatique
Chapitre 7
Cross-Validation & Optimisation
Évaluer, tuner et éviter le surapprentissage
7.1 Cross-Validation (k-Fold)
Un seul split train/test peut être chanceux ou malchanceux. La validation croisée k-Fold divise les données en k plis,
entraîne k fois (chacun servant de test une fois) et moyenne les scores.
Avantage : utilise 100% des données pour l'évaluation, estimation plus fiable. Standard : k = 5 ou 10.
from sklearn.model_selection import cross_val_score, KFold
# k-Fold CV sur la régression (Random Forest)
kf = KFold(n_splits=5, shuffle=True, random_state=42)
scores_rmse = cross_val_score(
rf_reg, # modèle
X_reg, y_reg, # données complètes
cv=kf,
scoring='neg_root_mean_squared_error' # négatif par convention sklearn
)
rmse_cv = -scores_rmse # repasser en positif
print(f'RMSE par pli : {rmse_cv.round(1)}')
print(f'Moyenne : {rmse_cv.mean():.1f} k€ ± {rmse_cv.std():.1f}')
# Classification
scores_acc = cross_val_score(rf_clf, X_clf, y_clf,
cv=5, scoring='accuracy')
print(f'Accuracy CV : {scores_acc.mean():.3f} ± {scores_acc.std():.3f}')
7.2 Surapprentissage vs Sous-apprentissage
Le biais-variance trade-off est central en ML :
Situation Train score Test score Cause Solution
Sous-app. + features, modèle +
Faible Faible Modèle trop simple
(underfitting) complexe
Bon apprentissage Élevé Élevé Équilibre —
Surapp. (overfitting) Très élevé Faible Modèle trop complexe Régularisation, + données
7.3 GridSearchCV — Recherche d'Hyperparamètres
GridSearchCV évalue toutes les combinaisons d'hyperparamètres par cross-validation. Coûteux mais exhaustif.
from sklearn.model_selection import GridSearchCV
# Grille pour Random Forest Regressor
param_grid = {
'n_estimators': [50, 100, 200],
'max_depth': [4, 8, None],
'min_samples_split': [2, 5, 10]
Python & Machine Learning — M1 Informatique 14
Python & Machine Learning — Polycopié M1 Institut d'Informatique
} # 3x3x3 = 27 combinaisons x 5 plis = 135 entraînements
grid_search = GridSearchCV(
RandomForestRegressor(random_state=42),
param_grid,
cv=5,
scoring='neg_root_mean_squared_error',
n_jobs=-1, # utiliser tous les CPU
verbose=1
)
grid_search.fit(X_train_r, y_train_r)
print('Meilleurs hyperparamètres :', grid_search.best_params_)
print(f'Meilleur RMSE CV : {-grid_search.best_score_:.1f} k€')
# Utiliser le meilleur modèle
best_rf = grid_search.best_estimator_
y_pred_best = best_rf.predict(X_test_r)
print(f'RMSE final (test) : {[Link](mean_squared_error(y_test_r, y_pred_best)):.1f}')
7.4 RandomizedSearchCV — Recherche Aléatoire
Quand la grille est trop grande, RandomizedSearchCV échantillonne aléatoirement n_iter combinaisons. Souvent 90%
de la qualité pour 10% du coût.
from sklearn.model_selection import RandomizedSearchCV
from [Link] import randint, uniform
param_dist = {
'n_estimators': randint(50, 500),
'max_depth': [4, 6, 8, 10, None],
'min_samples_leaf': randint(1, 10),
'max_features': uniform(0.3, 0.7) # fraction aléatoire
}
rand_search = RandomizedSearchCV(
RandomForestRegressor(random_state=42),
param_dist,
n_iter=50, # 50 combinaisons aléatoires
cv=5,
scoring='neg_root_mean_squared_error',
n_jobs=-1,
random_state=42
)
rand_search.fit(X_train_r, y_train_r)
print(rand_search.best_params_)
★ Points clés
5-Fold CV = chaque observation est utilisée 1 fois en test et 4 fois en train
GridSearchCV peut être combiné avec un Pipeline (scaler + modèle) pour éviter le leakage
n_jobs=-1 utilise tous les coeurs disponibles → accélération massive
Stratified K-Fold pour la classification : proportions de classes conservées dans chaque pli
Python & Machine Learning — M1 Informatique 15
Python & Machine Learning — Polycopié M1 Institut d'Informatique
Chapitre 8
Pipeline Scikit-learn & Projet Complet
Assembler un pipeline production-ready de A à Z
8.1 Pipeline Scikit-learn
Un Pipeline chaîne des transformations et un estimateur final. Avantages : pas de data leakage, une seule ligne de
fit/predict, facilement sérialisable.
from [Link] import Pipeline
from [Link] import StandardScaler
from [Link] import RandomForestClassifier
# Pipeline classification : normalisation + RF
pipe_clf = Pipeline([
('scaler', StandardScaler()),
('rf', RandomForestClassifier(n_estimators=100,
random_state=42))
])
# Entraînement = 1 seule ligne
pipe_clf.fit(X_train_c, y_train_c)
# Prédiction = 1 seule ligne
y_pred_pipe = pipe_clf.predict(X_test_c)
print(f'Accuracy pipeline : {accuracy_score(y_test_c, y_pred_pipe):.3f}')
# GridSearch sur un pipeline : préfixer les params
param_grid_pipe = {
'rf__n_estimators': [50, 100],
'rf__max_depth': [5, 10, None]
}
gs_pipe = GridSearchCV(pipe_clf, param_grid_pipe, cv=5, scoring='accuracy')
gs_pipe.fit(X_train_c, y_train_c)
print(gs_pipe.best_params_)
8.2 Projet Complet — Classification Admission
Objectif : construire le meilleur modèle de classification pour prédire l'admission, avec tout le pipeline complet et
l'interprétation.
Étape 1. Charger les données et faire l'EDA (df_clf.describe(), countplot des classes)
Étape 2. Séparer X / y et faire le train_test_split stratifié
Étape 3. Tester plusieurs algorithmes par cross-validation et comparer
Étape 4. Optimiser le meilleur avec GridSearchCV
Étape 5. Évaluer le modèle final sur le test set : accuracy, rapport, ROC-AUC
from [Link] import SVC
from [Link] import roc_auc_score
# Comparer 4 algorithmes en CV
models = {
'Logistic Reg.': LogisticRegression(max_iter=500),
'KNN (k=7)': KNeighborsClassifier(n_neighbors=7),
'Random Forest': RandomForestClassifier(n_estimators=100, random_state=42),
Python & Machine Learning — M1 Informatique 16
Python & Machine Learning — Polycopié M1 Institut d'Informatique
'SVM': SVC(probability=True, random_state=42)
}
results = {}
for name, model in [Link]():
pipe = Pipeline([('sc', StandardScaler()), ('m', model)])
cv_score = cross_val_score(pipe, X_train_c, y_train_c,
cv=5, scoring='roc_auc').mean()
results[name] = cv_score
print(f'{name:20s} AUC-CV = {cv_score:.3f}')
# Entraîner le meilleur sur tout le train
best_name = max(results, key=[Link])
best_pipe = Pipeline([('sc', StandardScaler()),
('m', models[best_name])])
best_pipe.fit(X_train_c, y_train_c)
# Rapport final
y_proba = best_pipe.predict_proba(X_test_c)[:, 1]
print(f'\n=== Résultats finaux ({best_name}) ===')
print(f'Accuracy : {accuracy_score(y_test_c, best_pipe.predict(X_test_c)):.3f}')
print(f'AUC-ROC : {roc_auc_score(y_test_c, y_proba):.3f}')
print(classification_report(y_test_c, best_pipe.predict(X_test_c)))
8.3 Sauvegarder et Charger un Modèle
import joblib
# Sauvegarder le pipeline
[Link](best_pipe, 'modele_admission.joblib')
print('Modèle sauvegardé !')
# Charger et prédire en production
modele = [Link]('modele_admission.joblib')
# Prédire pour un nouvel étudiant
nouvel_etudiant = [Link]([{
'note_bac': 15.5, 'toefl': 110,
'recherche': 1, 'rang_univ': 2
}])
proba = modele.predict_proba(nouvel_etudiant)[0, 1]
decision = 'ADMIS' if proba >= 0.5 else 'REFUSÉ'
print(f'Probabilité d\'admission : {proba:.1%} → {decision}')
★ Points clés
Pipeline = la bonne pratique : jamais de scaler séparé du modèle
joblib est plus rapide que pickle pour les objets NumPy/Sklearn
En production : versionner les modèles (MLflow, DVC) et monitorer la dérive
AUC-ROC > 0.9 est généralement considéré comme excellent
Python & Machine Learning — M1 Informatique 17
Python & Machine Learning — Polycopié M1 Institut d'Informatique
Chapitre 9
Récapitulatif & Guide de Choix
Synthèse, antisèches et conseils pratiques
9.1 Choisir le bon algorithme
Problème Données Algorithme conseillé Pourquoi ?
Linéaire, peu de
Régression Régression linéaire Simple, interprétable
features
Non-linéaire, > 5 Random Forest
Régression Robuste, peu de tuning
features Regressor
Grande dim., features
Régression Ridge / Lasso Régularisation
corrélées
Classification Binaire, données norm. Logistique Interprétable, probabiliste
Classification Toujours Random Forest Clf Solide baseline
Classification Faibles données KNN Aucun paramètre à apprendre
Classification Haute dim. SVM (RBF kernel) Efficace en haute dim.
9.2 Antisèche Scikit-learn
# ===== TEMPLATE UNIVERSEL ML =====
# 1. Imports
import numpy as np, pandas as pd
from sklearn.model_selection import train_test_split, cross_val_score
from [Link] import StandardScaler
from [Link] import Pipeline
from [Link] import ... # selon le problème
# 2. Données
X, y = [Link]('cible', axis=1), df['cible']
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42)
# 3. Pipeline
pipe = Pipeline([('sc', StandardScaler()), ('m', MonModele())])
# 4. Cross-validation
scores = cross_val_score(pipe, X_train, y_train, cv=5)
print(f'{[Link]():.3f} ± {[Link]():.3f}')
# 5. Entraîner + évaluer
[Link](X_train, y_train)
print([Link](X_test, y_test))
# 6. Sauvegarder
import joblib; [Link](pipe, 'mon_modele.joblib')
Python & Machine Learning — M1 Informatique 18
Python & Machine Learning — Polycopié M1 Institut d'Informatique
9.3 Métriques — Antisèche
Métrique sklearn Régression / Classification
MSE / RMSE mean_squared_error Régression
MAE mean_absolute_error Régression
R² r2_score Régression
Accuracy accuracy_score Classification
F1 f1_score Classification
AUC-ROC roc_auc_score Classification (proba)
Rapport complet classification_report Classification
9.4 Erreurs classiques à éviter
■ Attention
Data leakage : ne jamais fit le scaler sur le test set.
Pas de random_state : résultats non reproductibles.
Ignorer l'EDA : un modèle sur des données non comprises sera mauvais.
Évaluer sur le train : accuracy=100%... mais le modèle ne généralise pas.
Oublier stratify=y en classification déséquilibrée.
Comparer des modèles avec des splits différents : toujours même random_state.
★ Points clés
Le workflow ML est itératif : EDA → preprocessing → modèle → évaluation → tuning
Un bon preprocessing vaut souvent mieux qu'un algorithme plus complexe
Cross-validation 5-Fold = estimation fiable des performances
Commencer simple (régression linéaire/logistique) puis complexifier si nécessaire
Pipeline = bonne pratique absolue pour la reproductibilité et la production
R² > 0.9 en régression et AUC > 0.85 en classification = bons résultats
Références complémentaires :
• Documentation Scikit-learn : [Link]/stable/user_guide.html
• Pandas : [Link]/docs
• NumPy : [Link]/doc/stable
• KodeKloud Python & ML tracks : [Link]/learning-path/ai
• Kaggle Learn (gratuit) : [Link]/learn
Ce polycopié a été conçu pour accompagner le cours Python & Machine Learning du Master 1 Informatique. Les deux datasets
générés (prix de maisons — régression, admissions — classification) servent de fil conducteur tout au long du cours.
Python & Machine Learning — M1 Informatique 19