Régression linéaire
Apprenez le fonctionnement de la régression linéaire, la mathématique sous-jacente et son implémentation simple ou multiple en Python avec scikit-learn.
La régression linéaire est l'un des algorithmes les plus fondamentaux du machine learning. Elle modélise la relation entre une variable dépendante (ce que vous souhaitez prédire) et une ou plusieurs variables indépendantes (les entrées) en ajustant une droite — ou un hyperplan — aux données.
Cette page couvre :
- Le fonctionnement mathématique de la régression linéaire simple et multiple
- La méthode des moindres carrés ordinaires (MCO) pour ajuster une droite
- Les hypothèses clés à vérifier avant de faire confiance à votre modèle
- Un tutoriel complet avec scikit-learn : chargement des données, entraînement, évaluation et interprétation des résultats
- Comment lire les coefficients du modèle et identifier les pièges courants
Fonctionnement de la régression linéaire
L'équation
La régression linéaire simple (une seule variable d'entrée) ajuste cette droite :
y = β₀ + β₁x + εy— la variable dépendante (cible)x— la variable indépendante (caractéristique)β₀— l'ordonnée à l'origine (valeur de y quand x = 0)β₁— la pente (variation de y pour une augmentation d'une unité de x)ε— le terme d'erreur (bruit que le modèle ne peut pas expliquer)
La régression linéaire multiple étend cela à n caractéristiques :
y = β₀ + β₁x₁ + β₂x₂ + ... + βₙxₙ + εChaque coefficient βᵢ indique de combien y varie lorsque xᵢ augmente d'une unité, toutes les autres caractéristiques restant constantes.
Moindres carrés ordinaires (MCO)
Le modèle apprend les coefficients en minimisant la somme des carrés des résidus — la différence entre chaque valeur réelle yᵢ et la prédiction du modèle ŷᵢ :
SSR = Σ(yᵢ - ŷᵢ)²La mise au carré des résidus pénalise davantage les grandes erreurs que les petites, et garantit que les erreurs positives et négatives ne s'annulent pas. Ce critère possède une solution analytique exacte en forme fermée, ce qui explique pourquoi la régression linéaire s'entraîne quasi instantanément, même sur de grands jeux de données.
Hypothèses clés
La régression linéaire produit des prédictions fiables uniquement lorsque ces conditions sont satisfaites :
| Hypothèse | Ce qu'il faut vérifier |
|---|---|
| Linéarité | La relation entre les caractéristiques et la cible est approximativement linéaire |
| Indépendance | Les observations sont indépendantes les unes des autres |
| Homoscédasticité | La variance des résidus est à peu près constante pour toutes les prédictions |
| Normalité des résidus | Les résidus sont approximativement distribués normalement |
| Absence de multicolinéarité | Les variables indépendantes ne sont pas fortement corrélées entre elles |
Lorsque ces hypothèses sont violées, les estimations des coefficients peuvent être biaisées ou le modèle peut mal performer sur des données inédites.
Exemple de régression linéaire simple
Avant de passer à plusieurs caractéristiques, voyons comment l'algorithme ajuste une droite à une seule variable. Cela rend la géométrie facile à visualiser.
import numpy as np
import matplotlib
matplotlib.use('Agg') # non-interactive backend for scripts
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression
# Simulate: house size (sq ft) vs price ($1000s)
rng = np.random.default_rng(42)
X_simple = rng.uniform(500, 3000, 50).reshape(-1, 1)
y_simple = 50 + 0.1 * X_simple.ravel() + rng.normal(0, 15, 50)
model = LinearRegression()
model.fit(X_simple, y_simple)
print(f"Intercept (β₀): {model.intercept_:.2f}")
print(f"Slope (β₁): {model.coef_[0]:.4f}")
print(f"Interpretation: each extra sq ft adds ${model.coef_[0]*1000:.0f} to the predicted price")Résultat attendu :
Intercept (β₀): 46.17
Slope (β₁): 0.1007
Interpretation: each extra sq ft adds $101 to the predicted priceL'ordonnée à l'origine et la pente sont calculées automatiquement par MCO — vous n'avez pas à faire l'algèbre vous-même.
Régression linéaire multiple avec scikit-learn
Les jeux de données réels comportent de nombreuses caractéristiques. Cette section présente un pipeline complet sur le jeu de données California Housing, qui recense des statistiques immobilières au niveau des îlots de recensement en Californie en 1990.
Étape 1 : Importer les bibliothèques
import pandas as pd
import numpy as np
from sklearn.datasets import fetch_california_housing
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error, r2_scoreÉtape 2 : Charger et explorer le jeu de données
california = fetch_california_housing()
df = pd.DataFrame(california.data, columns=california.feature_names)
df['MedHouseVal'] = california.target # median house value in $100,000s
print(df.shape) # (20640, 9)
print(df.head())
print(df.describe())Le jeu de données contient 20 640 lignes et 8 caractéristiques d'entrée :
| Caractéristique | Description |
|---|---|
MedInc | Revenu médian de l'îlot (en dizaines de milliers de dollars) |
HouseAge | Âge médian des logements dans l'îlot |
AveRooms | Nombre moyen de pièces par ménage |
AveBedrms | Nombre moyen de chambres par ménage |
Population | Population de l'îlot |
AveOccup | Occupation moyenne des ménages |
Latitude | Latitude de l'îlot |
Longitude | Longitude de l'îlot |
La cible MedHouseVal est la valeur médiane des logements en unités de 100 000 $.
Étape 3 : Choisir les caractéristiques et diviser les données
Pour une démonstration simple, nous utilisons les 8 caractéristiques. Consultez Train/Test Split pour une explication détaillée de pourquoi nous divisons les données.
X = df[california.feature_names] # all 8 features
y = df['MedHouseVal']
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42
)
print(f"Training samples: {len(X_train)}") # 16512
print(f"Test samples: {len(X_test)}") # 4128Le paramètre random_state=42 garantit des divisions reproductibles à chaque exécution du script.
Étape 4 : Entraîner le modèle
model = LinearRegression()
model.fit(X_train, y_train)C'est tout ce qu'il faut. La méthode fit() résout le problème MCO de manière analytique via l'algèbre matricielle — aucune descente de gradient itérative n'est impliquée par défaut.
Étape 5 : Inspecter les coefficients appris
Comprendre ce que le modèle a appris est aussi important que sa précision :
coef_df = pd.DataFrame({
'Feature': california.feature_names,
'Coefficient': model.coef_
}).sort_values('Coefficient', key=abs, ascending=False)
print(coef_df.to_string(index=False))
print(f"\nIntercept: {model.intercept_:.4f}")Résultat typique :
Feature Coefficient
AveBedrms 0.7831
MedInc 0.4487
Longitude -0.4337
Latitude -0.4198
AveRooms -0.1233
HouseAge 0.0097
AveOccup -0.0035
Population -0.0000
Intercept: -37.0233Lecture des coefficients :
AveBedrms = 0.783: une augmentation d'une unité du nombre moyen de chambres prédit une hausse de 78 300 $ de la valeur du logement — mais cela est entremêlé avecAveRooms(ils sont corrélés). Lorsque des caractéristiques corrélées sont toutes deux présentes, les coefficients individuels peuvent devenir grands, instables, voire contre-intuitifs. C'est la multicolinéarité.MedInc = 0.449: une augmentation d'une unité du revenu médian (environ 10 000 $) prédit une hausse de 44 900 $ de la valeur du logement, toutes choses égales par ailleurs.Longitude = -0.434etLatitude = -0.420: des contrôles purement géographiques ; le modèle les utilise pour capturer les effets de localisation, même s'il ne peut pas modéliser la géographie non linéaire efficacement.
Étape 6 : Évaluer le modèle
y_pred = model.predict(X_test)
mse = mean_squared_error(y_test, y_pred)
rmse = np.sqrt(mse)
r2 = r2_score(y_test, y_pred)
print(f"RMSE: {rmse:.4f} (in $100,000s, so ±${rmse*100_000:,.0f})")
print(f"R²: {r2:.4f}")Résultat attendu :
RMSE: 0.7456 (in $100,000s, so ±$74,560)
R²: 0.5758Interprétation des métriques :
- RMSE (Root Mean Squared Error) — l'erreur de prédiction moyenne dans les mêmes unités que la cible. Plus la valeur est basse, mieux c'est.
- R² (coefficient de détermination) — la proportion de variance de
yexpliquée par le modèle. Un R² de 0,58 signifie que le modèle explique environ 58 % de la variance des prix immobiliers. Les valeurs proches de 1,0 sont meilleures ; les valeurs proches de 0 indiquent que le modèle fait à peine mieux que prédire la moyenne.
Un R² d'environ 0,58 est typique pour ce jeu de données avec la régression linéaire. La relation entre les prix immobiliers et ces caractéristiques est partiellement non linéaire, ce qui explique pourquoi des méthodes telles que la régression polynomiale ou le gradient boosting obtiennent souvent de meilleurs scores.
Étape 7 : Visualiser les valeurs prédites vs réelles
Le graphique diagnostique le plus clair pour un modèle de régression est prédit vs réel — il fonctionne quel que soit le nombre de caractéristiques :
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
plt.figure(figsize=(7, 5))
plt.scatter(y_test, y_pred, alpha=0.3, s=10, color='steelblue')
plt.plot([y_test.min(), y_test.max()],
[y_test.min(), y_test.max()],
'r--', linewidth=1.5, label='Perfect prediction')
plt.xlabel('Actual Median House Value ($100,000s)')
plt.ylabel('Predicted Median House Value ($100,000s)')
plt.title('Linear Regression: Predicted vs Actual')
plt.legend()
plt.tight_layout()
plt.savefig('lr_predicted_vs_actual.png', dpi=120)
print("Plot saved.")Les points qui tombent sur la ligne rouge en pointillés correspondent à des prédictions parfaites. La dispersion autour de la ligne représente l'erreur. Une forme en éventail (dispersion plus large aux valeurs élevées) signale une hétéroscédasticité — l'une des hypothèses clés est violée.
Pipeline complet (toutes les étapes réunies)
import pandas as pd
import numpy as np
from sklearn.datasets import fetch_california_housing
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error, r2_score
# Load data
california = fetch_california_housing()
df = pd.DataFrame(california.data, columns=california.feature_names)
df['MedHouseVal'] = california.target
# Split
X = df[california.feature_names]
y = df['MedHouseVal']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# Train
model = LinearRegression()
model.fit(X_train, y_train)
# Evaluate
y_pred = model.predict(X_test)
rmse = np.sqrt(mean_squared_error(y_test, y_pred))
r2 = r2_score(y_test, y_pred)
print(f"RMSE: {rmse:.4f}")
print(f"R²: {r2:.4f}")Quand utiliser la régression linéaire
La régression linéaire est un bon premier choix lorsque :
- La relation entre les entrées et la sortie est approximativement linéaire
- L'interprétabilité est importante — vous devez expliquer les prédictions aux parties prenantes
- Le jeu de données est de taille petite ou moyenne et la vitesse d'entraînement est importante
- Vous souhaitez obtenir rapidement une référence avant d'essayer des modèles plus complexes
Envisagez des alternatives lorsque :
- Les caractéristiques et la cible ont des relations non linéaires fortes → essayez la régression polynomiale ou les arbres de décision
- Vous avez de nombreuses caractéristiques potentiellement non pertinentes → les variantes régularisées (Ridge, Lasso) préviennent le surapprentissage en réduisant les coefficients
- La cible est une catégorie et non un nombre → utilisez plutôt la régression logistique
Pièges courants
Oublier de mettre les caractéristiques à l'échelle. Les coefficients de régression linéaire reflètent les unités de chaque caractéristique. Si une caractéristique est en milliers et une autre en fractions, les tailles brutes des coefficients ne sont pas comparables. Utilisez StandardScaler avant de comparer les importances des caractéristiques. Voir Feature Scaling pour plus de détails.
Multicolinéarité. Des caractéristiques fortement corrélées rendent les coefficients individuels peu fiables — ils peuvent même changer de signe. Vérifiez la matrice de corrélation avec df.corr() et supprimez ou combinez les caractéristiques corrélées.
Extrapolation. Un modèle linéaire entraîné sur des données dans une certaine plage peut donner des prédictions totalement erronées en dehors de cette plage. Vérifiez toujours que les nouvelles entrées se situent dans la distribution d'entraînement.
Ignorer les graphiques de résidus. Tracez toujours les résidus après l'ajustement. Des motifs dans les résidus (courbes, éventails, groupes d'outliers) indiquent que les hypothèses du modèle sont violées et que les prédictions ne doivent pas être utilisées sans investigation complémentaire.
Prochaines étapes
Une fois que vous disposez d'une référence de régression linéaire fonctionnelle, explorez ces sujets connexes :
- Multiple Regression — approfondissement de l'utilisation de plusieurs caractéristiques et de l'interprétation de chaque coefficient
- Polynomial Regression — ajuster des courbes plutôt que des droites en ajoutant des termes polynomiaux
- Train/Test Split — comprendre pourquoi et comment évaluer correctement les performances du modèle
- Feature Scaling — standardiser les entrées pour que les coefficients et les solveurs à gradient se comportent correctement
- Logistic Regression — prédire des catégories (oui/non, spam/non-spam) plutôt que des valeurs continues