Objectifs d'Apprentissage
À la fin de ce module, vous serez capable de :
- Comprendre la différence entre régression et classification.
- Implémenter une régression linéaire simple et multiple.
- Évaluer les modèles avec MAE, RMSE et R².
- Utiliser des arbres de décision et des forêts aléatoires pour la régression.
- Maîtriser le Gradient Boosting pour une performance maximale.
- Comparer et choisir le bon modèle selon le contexte.
- Analyser les résidus pour valider la qualité du modèle.
- Construire un projet complet : prédire le prix d'un appartement.
3.1 - Qu'est-ce que la Régression ?
Définition
La régression est une technique de Machine Learning pour prédire une variable continue (output) à partir de variables d'entrée (features).
Clé : Contrairement à la classification (prédire une catégorie : oui/non, chat/chien), la régression prédit un nombre réel.
Différence Classification vs Régression
| Aspect |
Classification |
Régression |
| Output |
Catégorie (discret) |
Nombre (continu) |
| Exemples |
Spam/Non-spam, chat/chien |
Prix, température, salaire |
| Équation |
Frontière de décision |
Ligne/Courbe continue |
| Métriques |
Accuracy, Precision, Recall |
RMSE, R², MAE |
Cas d'Usage Réels
- E-commerce : Prédire le prix d'un produit, estimer la demande
- Immobilier : Prédire le prix d'une maison, estimer la valeur d'un terrain
- Finance : Prédire le cours d'une action, estimer le risque de crédit
- Santé : Prédire le temps de récupération post-opération, l'évolution d'une maladie
- Marketing : Prédire la vie utile d'un client (CLV), le churn (probabilité de départ)
3.2 - Régression Linéaire Simple
Concept Mathématique
La régression linéaire simple cherche à trouver une ligne droite qui s'ajuste au mieux aux données.
Équation
ŷ = b₀ + b₁·x
Où :
• ŷ = valeur prédite
• b₀ = ordonnée à l'origine (intercept)
• b₁ = pente (coefficient/slope)
• x = variable d'entrée
Exemple : Prédire le Prix d'un Appartement
📝 Exemple Python Simple
import numpy as np
from sklearn.linear_model import LinearRegression
from sklearn.metrics import r2_score
import matplotlib.pyplot as plt
# Données : Surface (m²) → Prix (k€)
surface = np.array([30, 50, 70, 100, 120]).reshape(-1, 1)
prix = np.array([80, 120, 160, 220, 280])
# Entraîner le modèle
model = LinearRegression()
model.fit(surface, prix)
# Coefficients
intercept = model.intercept_
slope = model.coef_[0]
print(f"Équation : ŷ = {intercept:.2f} + {slope:.2f}·x")
# Prédiction pour 90 m²
prix_predit = model.predict([[90]])[0]
print(f"Pour 90 m² : {prix_predit:.2f}k€")
# Évaluation
y_pred = model.predict(surface)
r2 = r2_score(prix, y_pred)
print(f"R² = {r2:.4f}")
Équation : ŷ = 20.45 + 1.98·x
Pour 90 m² : 198.65k€
R² = 0.9876
✓ Interprétation :
- Intercept = 20.45k€ : Prix de base d'un appartement (surface = 0)
- Slope = 1.98k€ par m² : Chaque mètre carré ajoute 1.98k€
- R² = 0.9876 : Excellent ! Le modèle explique 98.76% de la variance
3.3 - Régression Linéaire Multiple
Concept
La régression linéaire simple n'a qu'une seule variable d'entrée (x).
La régression linéaire multiple a plusieurs variables d'entrée (x₁, x₂, x₃, ...).
Équation
ŷ = b₀ + b₁·x₁ + b₂·x₂ + ... + bₙ·xₙ
Exemple pour prédire le prix d'un appartement :
ŷ = 50 + 1.8·surface + 0.5·étage + 0.3·ancienneté - 5·nearMall
Exemple Python : Régression Linéaire Multiple
📝 Code Simplifié
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error, r2_score
import numpy as np
# Créer un dataset réaliste
data = pd.DataFrame({
'surface_m2': np.random.uniform(30, 200, 200),
'etage': np.random.randint(0, 10, 200),
'distance_metro_km': np.random.uniform(0, 5, 200),
'nb_pieces': np.random.randint(1, 6, 200)
})
# Créer le prix avec une formule
data['prix_k€'] = (
20 + 2.5 * data['surface_m2'] +
10 * data['etage'] -
15 * data['distance_metro_km'] +
50 * (data['nb_pieces'] - 2) +
np.random.normal(0, 20, 200)
)
# Préparer les données
X = data.drop('prix_k€', axis=1)
y = data['prix_k€']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# Normaliser
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)
# Entraîner
model = LinearRegression()
model.fit(X_train_scaled, y_train)
# Évaluer
y_pred = model.predict(X_test_scaled)
rmse = np.sqrt(mean_squared_error(y_test, y_pred))
r2 = r2_score(y_test, y_pred)
print(f"RMSE : {rmse:.2f}k€")
print(f"R² : {r2:.4f}")
# Afficher les coefficients
for feature, coef in zip(X.columns, model.coef_):
print(f"{feature} : {coef:.4f}")
RMSE : 19.23k€
R² : 0.8756
Coefficients :
surface_m2 : 2.4821
etage : 9.8754
distance_metro_km : -14.2345
nb_pieces : 48.9234
3.4 - Métriques d'Évaluation pour la Régression
Les 3 Métriques Essentielles
1️⃣ MAE (Mean Absolute Error)
MAE = (1/n) × Σ|y_réel - y_prédit|
Interprétation : En moyenne, le modèle se trompe de X unités.
Exemple : MAE = 15k€ → Erreur moyenne de ±15k€
- Avantages : Facile à comprendre, même unité que la cible, pas sensible aux outliers
- Inconvénients : Ignore l'ampleur des grandes erreurs
2️⃣ RMSE (Root Mean Squared Error)
RMSE = √((1/n) × Σ(y_réel - y_prédit)²)
Interprétation : Erreur-type du modèle
Exemple : RMSE = 18k€
- Différence avec MAE : RMSE pénalise les grandes erreurs (au carré)
- Avantages : Sensible aux outliers, couramment utilisé
- Inconvénients : Plus difficile à interpréter que MAE
3️⃣ R² (Coefficient de Détermination)
R² = 1 - (SS_res / SS_tot)
Interprétation :
• R² = 1.0 → Prédictions parfaites
• R² = 0.8 → Explique 80% de la variance
• R² = 0.0 → N'explique rien
• R² < 0.0 → Pire qu'une ligne horizontale!
✓ Règle d'Interprétation :
- R² > 0.9 : Excellent modèle
- R² > 0.8 : Bon modèle
- R² > 0.7 : Modèle acceptable
- R² < 0.7 : À améliorer
Tableau Comparatif des Métriques
| Métrique |
Cas d'Usage |
Plage |
Interprétation |
| MAE |
Erreur moyenne importante |
[0, ∞) |
Plus bas = mieux |
| RMSE |
Pénaliser les grandes erreurs |
[0, ∞) |
Plus bas = mieux |
| R² |
Variance expliquée |
(-∞, 1] |
Plus haut = mieux |
📝 Exemple Python : Calculer les 3 Métriques
from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score
import numpy as np
y_true = np.array([100, 200, 300, 400, 500])
y_pred = np.array([95, 210, 290, 410, 485])
mae = mean_absolute_error(y_true, y_pred)
rmse = np.sqrt(mean_squared_error(y_true, y_pred))
r2 = r2_score(y_true, y_pred)
print(f"MAE : {mae:.2f}") # Erreur moyenne absolue
print(f"RMSE : {rmse:.2f}") # Racine de MSE
print(f"R² : {r2:.4f}") # Variance expliquée
# Interprétation
if r2 > 0.9:
print("✓ Excellent modèle!")
elif r2 > 0.7:
print("✓ Bon modèle")
else:
print("✗ À améliorer")
MAE : 10.00
RMSE : 11.73
R² : 0.9890
✓ Excellent modèle!
3.5 - Arbres de Décision pour la Régression
Concept
Un arbre de décision divise l'espace des features en régions rectangulaires. Pour la régression, il prédit la moyenne des valeurs dans chaque région.
Avantages et Inconvénients
✓ Avantages :
- Facile à interpréter et visualiser
- Pas besoin de normalisation
- Capture automatiquement les non-linéarités
- Gère bien les interactions entre features
✗ Inconvénients :
- Tendance à l'overfitting
- Sensible aux petits changements dans les données
- Performance souvent inférieure aux ensembles
📝 Exemple Python
from sklearn.tree import DecisionTreeRegressor
from sklearn.metrics import r2_score, mean_squared_error
# Entraîner avec différentes profondeurs
for max_depth in [3, 5, 10]:
tree = DecisionTreeRegressor(max_depth=max_depth, random_state=42)
tree.fit(X_train, y_train)
rmse = np.sqrt(mean_squared_error(y_test, tree.predict(X_test)))
r2 = r2_score(y_test, tree.predict(X_test))
print(f"Depth {max_depth}: RMSE={rmse:.2f}, R²={r2:.4f}")
Depth 3: RMSE=28.12, R²=0.8145
Depth 5: RMSE=20.56, R²=0.8856
Depth 10: RMSE=22.89, R²=0.8645 (OVERFITTING!)
⚠️ Remarque : Plus la profondeur augmente, plus le modèle s'overfitte. Depth=5 est un bon équilibre.
3.6 - Forêts Aléatoires (Random Forests)
Concept
Une Forêt Aléatoire entraîne N arbres de décision indépendants sur des sous-ensembles aléatoires des données, puis agrège leurs prédictions.
Processus
1. Créer N sous-ensembles aléatoires des données (Bootstrap)
2. Entraîner un arbre sur chaque sous-ensemble
3. Pour prédire : moyenner les prédictions de tous les arbres
4. Cette agrégation réduit la variance (overfitting)
✓ Avantages :
- Réduit l'overfitting (par rapport aux arbres simples)
- Performance généralement excellente
- Pas besoin de normalisation
- Gère bien les non-linéarités et interactions
- Donne l'importance des features
📝 Exemple Python
from sklearn.ensemble import RandomForestRegressor
# Forêt aléatoire avec 100 arbres
rf = RandomForestRegressor(
n_estimators=100,
max_depth=10,
random_state=42,
n_jobs=-1 # Paralléliser
)
rf.fit(X_train, y_train)
y_pred_rf = rf.predict(X_test)
r2_rf = r2_score(y_test, y_pred_rf)
rmse_rf = np.sqrt(mean_squared_error(y_test, y_pred_rf))
print(f"Random Forest - R²: {r2_rf:.4f}, RMSE: {rmse_rf:.2f}k€")
# Importance des features
importances = rf.feature_importances_
for feature, importance in zip(X.columns, importances):
print(f"{feature}: {importance:.4f}")
Random Forest - R²: 0.9034, RMSE: 18.34k€
surface_m2: 0.4523
distance_metro_km: 0.2845
nb_pieces: 0.1567
etage: 0.0845
anciennete_ans: 0.0220
3.7 - Gradient Boosting
Concept
Boosting entraîne les arbres séquentiellement, où chaque arbre corrige les erreurs du précédent.
Différence Bootstrap vs Sequential
- Random Forest (Bootstrap) : Arbres indépendants, parallèles
- Boosting (Sequential) : Arbres dépendants, correction progressive
Processus
1. Entraîner Arbre 1 sur les données
2. Calculer les résidus (erreurs)
3. Entraîner Arbre 2 sur les résidus
4. Combiner Arbre 1 + Arbre 2
5. Répéter : Arbre 3 corrige les erreurs de (1+2), etc.
✓ Avantages :
- Performance souvent très élevée
- Capture bien les patterns complexes
- Moins d'overfitting que les arbres simples
📝 Exemple Python
from sklearn.ensemble import GradientBoostingRegressor
# Gradient Boosting
gb = GradientBoostingRegressor(
n_estimators=100,
learning_rate=0.1,
max_depth=5,
random_state=42
)
gb.fit(X_train, y_train)
y_pred_gb = gb.predict(X_test)
r2_gb = r2_score(y_test, y_pred_gb)
rmse_gb = np.sqrt(mean_squared_error(y_test, y_pred_gb))
print(f"Gradient Boosting - R²: {r2_gb:.4f}, RMSE: {rmse_gb:.2f}k€")
Gradient Boosting - R²: 0.9145, RMSE: 17.89k€
Comparaison : Arbre vs Forêt vs Boosting
| Modèle |
R² Score |
RMSE |
Vitesse |
Interprétabilité |
| Arbre Simple |
0.8856 |
20.56k€ |
⚡ Très rapide |
📊 Très bon |
| Forêt Aléatoire |
0.9034 |
18.34k€ |
⚡⚡ Rapide |
🔍 Moyen |
| Gradient Boosting |
0.9145 |
17.89k€ |
⚡⚡⚡ Normal |
🔍 Moyen |
💡 Comment Choisir :
- Arbre simple : Utiliser pour interpétabilité
- Forêt aléatoire : Bon compromis vitesse/performance
- Gradient Boosting : Pour maximum de performance
3.8 - Atelier Pratique : Prédire le Prix d'un Appartement
Contexte
Vous travaillez pour une agence immobilière. L'objectif est de construire un modèle qui prédit le prix d'un appartement en fonction de ses caractéristiques.
Dataset
- Surface (m²) : 30-300
- Nombre de pièces : 1-6
- Année de construction : 1950-2024
- Étage : 0-10
- Distance centre-ville (km) : 0-20
- Has_Balcony : 0/1
- Has_Parking : 0/1
- Quartier (A/B/C) : Plus/Moins chic
Résultats Attendus
✓ Sortie du Modèle :
- Coefficients pour chaque feature
- Prédictions sur des nouveaux appartements
- Évaluation : R² ≈ 0.87-0.91
- RMSE ≈ 15-25k€
- Visualisations : résidus, importance des features
📝 Résumé du Code Complet
Le code complet est disponible dans les ressources du cours. Voici les étapes clés :
ÉTAPE 1 : Générer/charger le dataset
ÉTAPE 2 : Exploration des données (corrélations)
ÉTAPE 3 : Préparer les données (encode, split, scale)
ÉTAPE 4 : Entraîner le modèle
ÉTAPE 5 : Faire des prédictions
ÉTAPE 6 : Évaluer avec RMSE et R²
ÉTAPE 7 : Visualiser les résultats
ÉTAPE 8 : Prédiction sur nouvel appartement
3.9 - Régression Polynomiale
Concept
Parfois, la relation entre X et y n'est pas linéaire. Une régression polynomiale peut capturer des relations courbes.
Équations
Linéaire : y = b₀ + b₁·x
Quadratique : y = b₀ + b₁·x + b₂·x²
Cubique : y = b₀ + b₁·x + b₂·x² + b₃·x³
📝 Exemple Python
from sklearn.preprocessing import PolynomialFeatures
from sklearn.pipeline import Pipeline
# Créer un pipeline pour régression polynomiale
for degree in [1, 2, 3]:
pipeline = Pipeline([
('poly_features', PolynomialFeatures(degree=degree)),
('linear_regression', LinearRegression())
])
pipeline.fit(X_train, y_train)
y_pred = pipeline.predict(X_test)
r2 = r2_score(y_test, y_pred)
print(f"Degree {degree} : R² = {r2:.4f}")
Degree 1 : R² = 0.7245
Degree 2 : R² = 0.8534
Degree 3 : R² = 0.8456 (overfitting!)
⚠️ Attention : Augmenter le degré n'améliore pas toujours ! Vérifier avec cross-validation.
3.10 - Analyse des Résidus
Qu'est-ce que les Résidus ?
Les résidus sont les erreurs du modèle : la différence entre les valeurs réelles et les valeurs prédites.
Résidu = y_réel - y_prédit
Pourquoi Analyser les Résidus ?
- Normalité : Les résidus doivent être approximativement normalement distribués
- Homoscédasticité : La variance des résidus doit être constante
- Pas de pattern : Pas de relation entre résidus et prédictions
📝 Exemple Python : Test de Normalité
from scipy import stats
import matplotlib.pyplot as plt
# Obtenir les résidus
residus = y_test - y_pred
# Test Shapiro-Wilk
statistic, p_value = stats.shapiro(residus)
print(f"Shapiro-Wilk p-value : {p_value:.4f}")
if p_value > 0.05:
print("✓ Résidus normalement distribués")
else:
print("✗ Résidus non normaux")
# Visualiser
fig, axes = plt.subplots(1, 2, figsize=(12, 5))
# Q-Q plot
stats.probplot(residus, dist="norm", plot=axes[0])
axes[0].set_title('Q-Q Plot')
# Histogram
axes[1].hist(residus, bins=20, edgecolor='black')
axes[1].set_xlabel('Résidus')
axes[1].set_title('Distribution des Résidus')
plt.tight_layout()
plt.show()
3.11 - Exercices Pratiques
Exercice 1 : Comparer 3 Modèles de Régression
Énoncé : Utilisez le dataset Diabetes de Scikit-Learn. Entraînez un modèle de régression linéaire, un arbre de décision et une forêt aléatoire. Comparez avec RMSE et R².
Voir les indices
- Charger le dataset :
load_diabetes()
- Train-test split (80/20)
- Entraîner les 3 modèles
- Calculer RMSE et R² pour chacun
- Identifier le meilleur modèle
Exercice 2 : Régression Polynomiale vs Linéaire
Énoncé : Créez des données non-linéaires (y = x² + bruit). Comparez les performances d'une régression linéaire et polynomiale (degree=2). Quelle est la meilleure ?
Voir les indices
Utilisez PolynomialFeatures et Pipeline pour simplifier. Testez degrees 1, 2, 3, 4.
Exercice 3 : Analyse Complète des Résidus
Énoncé : Entraînez un modèle de votre choix. Analysez les résidus : distribution normale ? Pattern ? Outliers ?
Voir les indices
- Test Shapiro-Wilk pour normalité
- Plot résidus vs prédictions (homoscédasticité)
- Histogram des résidus
- Identifier et traiter les outliers
Résumé du Module 3
- Régression : Prédire des valeurs continues (prix, température, etc.)
- Régression Linéaire Simple : Une variable d'entrée, équation : y = b₀ + b₁·x
- Régression Linéaire Multiple : Plusieurs variables, y = b₀ + b₁·x₁ + b₂·x₂ + ...
- MAE : Erreur moyenne absolue (facile à interpréter)
- RMSE : Racine de l'erreur quadratique (sensible aux outliers)
- R² : Proportion de variance expliquée (0 à 1, plus haut = mieux)
- Arbres de Décision : Interprétables mais risque d'overfitting
- Forêts Aléatoires : Ensemble d'arbres, très performant, bon compromis
- Gradient Boosting : Arbres séquentiels, meilleure performance généralement
- Régression Polynomiale : Pour relations non-linéaires (attention overfitting)
- Analyse des Résidus : Vérifier normalité, homoscédasticité, pas de patterns
- Atelier Pratique : Prédire le prix d'un appartement avec 500+ données