Régression linéaire Sklearn : guide complet avec des exemples Python
Updated on
Vous avez un jeu de données avec des variables explicatives (features) et une cible continue. Vous souhaitez prédire des résultats — prix de l’immobilier, revenus de ventes, tendances de température — mais vous ne savez pas quelle approche utiliser ni comment la configurer correctement en Python. Un mauvais choix de modèle ou l’absence d’étapes de prétraitement entraîne de mauvaises prédictions et du temps perdu à déboguer.
La régression linéaire est l’algorithme le plus utilisé pour les tâches de prédiction continue, mais bien l’utiliser implique plus que d’appeler .fit() et .predict(). Vous devez comprendre comment le modèle fonctionne en interne, quand il échoue, comment l’évaluer correctement, et quand passer à des variantes régularisées comme Ridge ou Lasso. Sauter ces étapes, c’est risquer de déployer des modèles qui marchent bien sur les données d’entraînement mais se dégradent sur de nouvelles observations.
Scikit-learn fournit LinearRegression ainsi qu’un écosystème complet d’outils pour le prétraitement, l’évaluation et la régularisation. Ce guide couvre tout, de l’usage de base à des pipelines de régression prêts pour la production.
Qu’est-ce que la régression linéaire ?
La régression linéaire modélise la relation entre une ou plusieurs variables d’entrée et une sortie continue en ajustant une droite (ou un hyperplan) qui minimise la somme des résidus au carré. L’équation d’un modèle avec n variables est :
y = b0 + b1*x1 + b2*x2 + ... + bn*xnOù b0 est l’interception (terme de biais), b1...bn sont les coefficients (poids) de chaque variable, et y est la valeur prédite.
Le modèle trouve les coefficients qui minimisent la fonction de coût Ordinary Least Squares (OLS) :
Cost = Sum of (y_actual - y_predicted)^2Elle admet une solution sous forme fermée, donc l’entraînement est rapide même sur de grands jeux de données.
Régression linéaire simple avec Sklearn
La régression linéaire simple utilise une seule variable pour prédire la cible. Voici un exemple complet :
from sklearn.linear_model import LinearRegression
import numpy as np
# Sample data: years of experience vs salary (in thousands)
X = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]).reshape(-1, 1)
y = np.array([35, 40, 45, 55, 60, 62, 70, 75, 82, 90])
# Create and train the model
model = LinearRegression()
model.fit(X, y)
# Model parameters
print(f"Coefficient (slope): {model.coef_[0]:.4f}")
print(f"Intercept: {model.intercept_:.4f}")
# Predict salary for 12 years of experience
prediction = model.predict([[12]])
print(f"Predicted salary for 12 years: ${prediction[0]:.2f}k")
# Coefficient (slope): 5.9394
# Intercept: 28.3333
# Predicted salary for 12 years: $99.61kComprendre la sortie
| Attribut | Signification | Exemple de valeur |
|---|---|---|
model.coef_ | Poids pour chaque variable | [5.94] — le salaire augmente d’environ 5 940 $ par an |
model.intercept_ | y prédit quand toutes les variables valent 0 | 28.33 — salaire de base de 28 330 $ |
model.score(X, y) | R-squared sur les données fournies | 0.98 |
Régression linéaire multiple
Quand vous avez plus d’une variable, le modèle ajuste un hyperplan plutôt qu’une droite :
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
from sklearn.datasets import fetch_california_housing
import numpy as np
# Load California housing dataset
housing = fetch_california_housing()
X, y = housing.data, housing.target
feature_names = housing.feature_names
print(f"Features: {feature_names}")
print(f"Dataset shape: {X.shape}") # (20640, 8)
# Split into train and test
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42
)
# Train model
model = LinearRegression()
model.fit(X_train, y_train)
# Print coefficients for each feature
print("\nFeature Coefficients:")
for name, coef in zip(feature_names, model.coef_):
print(f" {name:12s}: {coef:+.6f}")
print(f" {'Intercept':12s}: {model.intercept_:+.6f}")
# Evaluate
train_score = model.score(X_train, y_train)
test_score = model.score(X_test, y_test)
print(f"\nR² (train): {train_score:.4f}")
print(f"R² (test): {test_score:.4f}")Évaluation du modèle : R-squared, MSE et RMSE
Le R-squared seul ne raconte pas toute l’histoire. Utilisez plusieurs métriques pour évaluer les modèles de régression :
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error, mean_absolute_error, r2_score
from sklearn.datasets import fetch_california_housing
import numpy as np
housing = fetch_california_housing()
X_train, X_test, y_train, y_test = train_test_split(
housing.data, housing.target, test_size=0.2, random_state=42
)
model = LinearRegression()
model.fit(X_train, y_train)
y_pred = model.predict(X_test)
# Calculate metrics
r2 = r2_score(y_test, y_pred)
mse = mean_squared_error(y_test, y_pred)
rmse = np.sqrt(mse)
mae = mean_absolute_error(y_test, y_pred)
print(f"R² Score: {r2:.4f}")
print(f"MSE: {mse:.4f}")
print(f"RMSE: {rmse:.4f}")
print(f"MAE: {mae:.4f}")
# R² Score: 0.5758
# MSE: 0.5559
# RMSE: 0.7456
# MAE: 0.5332Explication des métriques d’évaluation
| Métrique | Formule | Plage | Interprétation |
|---|---|---|---|
| R-squared (R²) | 1 - (SS_res / SS_tot) | (-inf, 1] | Proportion de variance expliquée. 1.0 = parfait, 0 = pas mieux que la moyenne |
| MSE | mean((y - y_pred)²) | [0, inf) | Erreur quadratique moyenne. Pénalise davantage les grosses erreurs |
| RMSE | sqrt(MSE) | [0, inf) | Même unité que la cible. Plus facile à interpréter que la MSE |
| MAE | mean(|y - y_pred|) | [0, inf) | Erreur absolue moyenne. Plus robuste aux valeurs aberrantes |
Un R-squared faible ne signifie pas toujours un mauvais modèle. Sur des données réelles bruitées (comme les prix immobiliers), R² = 0.6 peut être raisonnable. Comparez toujours le RMSE à l’échelle de votre variable cible.
Mise à l’échelle des variables pour la régression linéaire
Le LinearRegression standard ne nécessite pas de mise à l’échelle des variables, car il utilise OLS avec une solution sous forme fermée. En revanche, la mise à l’échelle devient indispensable quand on utilise la régularisation :
from sklearn.linear_model import LinearRegression, Ridge
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split
from sklearn.pipeline import Pipeline
from sklearn.datasets import fetch_california_housing
housing = fetch_california_housing()
X_train, X_test, y_train, y_test = train_test_split(
housing.data, housing.target, test_size=0.2, random_state=42
)
# Without scaling (fine for basic LinearRegression)
model_no_scale = LinearRegression()
model_no_scale.fit(X_train, y_train)
print(f"LinearRegression R² (no scaling): {model_no_scale.score(X_test, y_test):.4f}")
# With scaling via Pipeline (required for regularized models)
pipeline = Pipeline([
('scaler', StandardScaler()),
('ridge', Ridge(alpha=1.0))
])
pipeline.fit(X_train, y_train)
print(f"Ridge R² (with scaling): {pipeline.score(X_test, y_test):.4f}")Pourquoi l’échelle est importante pour la régularisation : Ridge et Lasso pénalisent les grands coefficients de la même manière. Si une variable est dans [0, 1] et une autre dans [0, 100 000], la pénalisation réduira de façon disproportionnée le coefficient de la variable à petite plage. La mise à l’échelle met toutes les variables sur la même échelle pour que la pénalité soit appliquée équitablement.
Variables polynomiales : modéliser des relations non linéaires
Quand la relation entre variables et cible n’est pas linéaire, les variables polynomiales peuvent capturer les courbes et les interactions :
from sklearn.linear_model import LinearRegression
from sklearn.preprocessing import PolynomialFeatures
from sklearn.pipeline import Pipeline
from sklearn.model_selection import train_test_split
from sklearn.metrics import r2_score
import numpy as np
# Generate non-linear data
np.random.seed(42)
X = np.linspace(0, 10, 200).reshape(-1, 1)
y = 3 * X.ravel()**2 - 5 * X.ravel() + 10 + np.random.randn(200) * 15
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42
)
# Linear model
linear = LinearRegression()
linear.fit(X_train, y_train)
print(f"Linear R²: {r2_score(y_test, linear.predict(X_test)):.4f}")
# Polynomial (degree 2) model
poly_pipeline = Pipeline([
('poly', PolynomialFeatures(degree=2, include_bias=False)),
('linear', LinearRegression())
])
poly_pipeline.fit(X_train, y_train)
print(f"Poly (d=2) R²: {r2_score(y_test, poly_pipeline.predict(X_test)):.4f}")
# Polynomial (degree 3) model
poly3_pipeline = Pipeline([
('poly', PolynomialFeatures(degree=3, include_bias=False)),
('linear', LinearRegression())
])
poly3_pipeline.fit(X_train, y_train)
print(f"Poly (d=3) R²: {r2_score(y_test, poly3_pipeline.predict(X_test)):.4f}")Attention : les polynômes de degré élevé surapprennent rapidement. Utilisez la cross-validation pour choisir le bon degré, et privilégiez la régularisation pour les modèles polynomiaux.
Régularisation : Ridge, Lasso et ElasticNet
Quand votre modèle a beaucoup de variables ou de termes polynomiaux, la régularisation empêche le surapprentissage en ajoutant une pénalité aux grands coefficients.
Régression Ridge (pénalité L2)
Ridge ajoute la somme des coefficients au carré à la fonction de coût. Elle réduit les coefficients vers zéro sans jamais les mettre exactement à zéro.
from sklearn.linear_model import Ridge
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
from sklearn.model_selection import train_test_split, GridSearchCV
from sklearn.datasets import fetch_california_housing
import numpy as np
housing = fetch_california_housing()
X_train, X_test, y_train, y_test = train_test_split(
housing.data, housing.target, test_size=0.2, random_state=42
)
# Find best alpha with cross-validation
pipeline = Pipeline([
('scaler', StandardScaler()),
('ridge', Ridge())
])
param_grid = {'ridge__alpha': [0.01, 0.1, 1.0, 10.0, 100.0]}
grid = GridSearchCV(pipeline, param_grid, cv=5, scoring='r2')
grid.fit(X_train, y_train)
print(f"Best alpha: {grid.best_params_['ridge__alpha']}")
print(f"Best CV R²: {grid.best_score_:.4f}")
print(f"Test R²: {grid.score(X_test, y_test):.4f}")Régression Lasso (pénalité L1)
Lasso ajoute la somme des valeurs absolues des coefficients. Elle peut mettre des coefficients exactement à zéro, réalisant une sélection automatique de variables :
from sklearn.linear_model import Lasso
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
from sklearn.model_selection import train_test_split, GridSearchCV
from sklearn.datasets import fetch_california_housing
import numpy as np
housing = fetch_california_housing()
X_train, X_test, y_train, y_test = train_test_split(
housing.data, housing.target, test_size=0.2, random_state=42
)
pipeline = Pipeline([
('scaler', StandardScaler()),
('lasso', Lasso(max_iter=10000))
])
param_grid = {'lasso__alpha': [0.001, 0.01, 0.1, 1.0, 10.0]}
grid = GridSearchCV(pipeline, param_grid, cv=5, scoring='r2')
grid.fit(X_train, y_train)
print(f"Best alpha: {grid.best_params_['lasso__alpha']}")
print(f"Test R²: {grid.score(X_test, y_test):.4f}")
# Show which features were selected (non-zero coefficients)
lasso_model = grid.best_estimator_.named_steps['lasso']
feature_names = housing.feature_names
for name, coef in zip(feature_names, lasso_model.coef_):
status = "KEPT" if abs(coef) > 1e-6 else "DROPPED"
print(f" {name:12s}: {coef:+.6f} [{status}]")ElasticNet (pénalité L1 + L2)
ElasticNet combine les pénalités Ridge et Lasso. Le paramètre l1_ratio contrôle le mélange : 0 = Ridge pur, 1 = Lasso pur.
from sklearn.linear_model import ElasticNet
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
from sklearn.model_selection import train_test_split, GridSearchCV
from sklearn.datasets import fetch_california_housing
housing = fetch_california_housing()
X_train, X_test, y_train, y_test = train_test_split(
housing.data, housing.target, test_size=0.2, random_state=42
)
pipeline = Pipeline([
('scaler', StandardScaler()),
('elasticnet', ElasticNet(max_iter=10000))
])
param_grid = {
'elasticnet__alpha': [0.01, 0.1, 1.0],
'elasticnet__l1_ratio': [0.1, 0.3, 0.5, 0.7, 0.9]
}
grid = GridSearchCV(pipeline, param_grid, cv=5, scoring='r2')
grid.fit(X_train, y_train)
print(f"Best alpha: {grid.best_params_['elasticnet__alpha']}")
print(f"Best l1_ratio: {grid.best_params_['elasticnet__l1_ratio']}")
print(f"Test R²: {grid.score(X_test, y_test):.4f}")Comparaison : LinearRegression vs Ridge vs Lasso vs ElasticNet
| Modèle | Pénalité | Sélection de variables | Quand l’utiliser | Mise à l’échelle requise |
|---|---|---|---|---|
| LinearRegression | Aucune | Non | Peu de variables, pas de multicolinéarité, bon ratio signal/bruit | Non |
| Ridge | L2 (au carré) | Non (réduit vers zéro) | Beaucoup de variables corrélées, vous voulez conserver toutes les variables | Oui |
| Lasso | L1 (valeur absolue) | Oui (met des coefficients à zéro) | Beaucoup de variables, vous voulez une sélection automatique | Oui |
| ElasticNet | L1 + L2 | Oui (partielle) | Variables corrélées, vous voulez un peu de sélection | Oui |
Choisir le bon modèle
Utilisez LinearRegression comme baseline. Si le modèle surapprend (grand écart entre R-squared train et test), essayez Ridge en premier. Si vous suspectez beaucoup de variables non pertinentes, essayez Lasso. Si les variables sont corrélées et que vous voulez de la sélection, essayez ElasticNet. Utilisez toujours la cross-validation pour comparer.
Hypothèses de la régression linéaire
La régression linéaire produit des résultats fiables lorsque ces hypothèses sont respectées :
- Linéarité — La relation entre variables et cible est linéaire (ou rendue linéaire via des transformations).
- Indépendance — Les observations sont indépendantes les unes des autres. Cette hypothèse est violée en séries temporelles si l’on ne tient pas compte de l’autocorrélation.
- Homoscedasticité — La variance des résidus est constante pour tous les niveaux des valeurs prédites.
- Normalité des résidus — Les résidus suivent une loi normale. C’est surtout important pour les intervalles de confiance et les tests d’hypothèses, moins pour la précision de prédiction.
- Absence de multicolinéarité — Les variables ne sont pas fortement corrélées entre elles. La multicolinéarité gonfle la variance des coefficients et rend les coefficients individuels peu fiables.
Vérifier les hypothèses en code
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
from sklearn.datasets import fetch_california_housing
import numpy as np
housing = fetch_california_housing()
X_train, X_test, y_train, y_test = train_test_split(
housing.data, housing.target, test_size=0.2, random_state=42
)
model = LinearRegression()
model.fit(X_train, y_train)
y_pred = model.predict(X_test)
residuals = y_test - y_pred
# Check residual statistics
print(f"Residual mean: {residuals.mean():.6f}") # Should be near 0
print(f"Residual std: {residuals.std():.4f}")
print(f"Residual skewness: {float(np.mean((residuals - residuals.mean())**3) / residuals.std()**3):.4f}")
# Check for multicollinearity (correlation matrix)
corr_matrix = np.corrcoef(X_train, rowvar=False)
print(f"\nMax feature correlation: {np.max(np.abs(corr_matrix - np.eye(corr_matrix.shape[0]))):.4f}")Pipeline complet : régression en conditions réelles
Voici un pipeline de style production qui combine prétraitement, feature engineering et sélection de modèle :
from sklearn.linear_model import LinearRegression, Ridge, Lasso
from sklearn.preprocessing import StandardScaler, PolynomialFeatures
from sklearn.model_selection import train_test_split, cross_val_score
from sklearn.pipeline import Pipeline
from sklearn.datasets import fetch_california_housing
import numpy as np
# Load data
housing = fetch_california_housing()
X_train, X_test, y_train, y_test = train_test_split(
housing.data, housing.target, test_size=0.2, random_state=42
)
# Define models to compare
models = {
'LinearRegression': Pipeline([
('scaler', StandardScaler()),
('model', LinearRegression())
]),
'Ridge (alpha=1)': Pipeline([
('scaler', StandardScaler()),
('model', Ridge(alpha=1.0))
]),
'Lasso (alpha=0.01)': Pipeline([
('scaler', StandardScaler()),
('model', Lasso(alpha=0.01, max_iter=10000))
]),
'Poly(2) + Ridge': Pipeline([
('poly', PolynomialFeatures(degree=2, include_bias=False)),
('scaler', StandardScaler()),
('model', Ridge(alpha=10.0))
])
}
# Evaluate all models
print(f"{'Model':<25} {'CV R² (mean)':>12} {'CV R² (std)':>12} {'Test R²':>10}")
print("-" * 62)
for name, pipeline in models.items():
cv_scores = cross_val_score(pipeline, X_train, y_train, cv=5, scoring='r2')
pipeline.fit(X_train, y_train)
test_r2 = pipeline.score(X_test, y_test)
print(f"{name:<25} {cv_scores.mean():>12.4f} {cv_scores.std():>12.4f} {test_r2:>10.4f}")Explorer les résultats de régression avec PyGWalker
Après avoir entraîné votre modèle, comprendre les schémas de prédiction est crucial. PyGWalker (opens in a new tab) vous permet d’explorer visuellement les résidus, les importances de variables, et les relations prédits-vs-réels via une interface interactive de type drag-and-drop dans Jupyter :
import pandas as pd
import pygwalker as pyg
# Build a results DataFrame
results = pd.DataFrame(housing.data[len(X_train):], columns=housing.feature_names)
results['actual'] = y_test
results['predicted'] = y_pred
results['residual'] = y_test - y_pred
results['abs_error'] = np.abs(y_test - y_pred)
# Launch interactive exploration
walker = pyg.walk(results)Vous pouvez glisser des variables sur les axes, colorer selon l’amplitude des résidus, et identifier les segments de données où le modèle a du mal — le tout sans écrire de code de visualisation.
Pour mener des expérimentations itératives dans Jupyter, RunCell (opens in a new tab) propose un agent IA qui vous aide à tester différentes combinaisons de variables, d’hyperparamètres et d’étapes de prétraitement sans réécrire manuellement des cellules.
FAQ
Qu’est-ce que LinearRegression dans sklearn ?
sklearn.linear_model.LinearRegression est un modèle de régression Ordinary Least Squares (OLS). Il ajuste une équation linéaire aux données en minimisant la somme des carrés des écarts entre les valeurs réelles et les valeurs prédites. C’est le modèle de régression le plus simple et le plus interprétable de scikit-learn.
Comment interpréter le score R-squared ?
Le R-squared mesure la proportion de variance de la variable cible expliquée par le modèle. Un R-squared de 0,80 signifie que 80 % de la variance est expliquée. Une valeur de 1,0 correspond à un ajustement parfait, 0,0 signifie que le modèle n’est pas meilleur que la prédiction de la moyenne, et des valeurs négatives indiquent que le modèle est pire que l’utilisation de la moyenne.
Quand utiliser Ridge vs Lasso vs ElasticNet ?
Utilisez Ridge lorsque vous voulez conserver toutes les variables tout en réduisant le surapprentissage (variables multicolinéaires). Utilisez Lasso lorsque vous voulez une sélection automatique de variables (il met les coefficients des variables non pertinentes à zéro). Utilisez ElasticNet lorsque les variables sont corrélées et que vous voulez un compromis entre la stabilité de Ridge et la sparsité de Lasso.
LinearRegression a-t-il besoin de mise à l’échelle des variables ?
Le LinearRegression de base ne nécessite pas de mise à l’échelle, car la solution OLS est invariante à l’échelle. En revanche, Ridge, Lasso et ElasticNet exigent tous une mise à l’échelle, car leurs pénalités traitent toutes les magnitudes de coefficients de la même manière. Mettez toujours à l’échelle les variables avant une régression régularisée.
Comment gérer les variables catégorielles en régression linéaire ?
Convertissez les variables catégorielles en numériques avec OneHotEncoder ou pd.get_dummies() avant d’entraîner. Le LinearRegression de sklearn n’accepte que des entrées numériques. Dans des pipelines, utilisez ColumnTransformer pour appliquer des transformations différentes aux colonnes numériques et catégorielles.
Quelle est la différence entre MSE et RMSE ?
La MSE (Mean Squared Error) est la moyenne des carrés des écarts entre valeurs réelles et valeurs prédites. La RMSE (Root Mean Squared Error) est la racine carrée de la MSE. La RMSE est dans la même unité que la variable cible, ce qui la rend plus facile à interpréter. Par exemple, si vous prédisez des prix immobiliers en dollars, une RMSE de 50 000 signifie une erreur moyenne de prédiction d’environ 50 000 $.
Conclusion
Le LinearRegression de Sklearn est le point de départ de toute tâche de régression en Python. Il est rapide, interprétable et efficace lorsque la relation sous-jacente est approximativement linéaire. Pour des jeux de données réels avec du bruit, de la multicolinéarité ou de nombreuses variables, Ridge, Lasso et ElasticNet apportent une régularisation qui améliore la généralisation. Évaluez toujours avec plusieurs métriques (R-squared, RMSE, MAE), utilisez des séparations train-test pour éviter le surapprentissage, et analysez les résidus pour vérifier que les hypothèses du modèle tiennent. Construisez des pipelines avec StandardScaler et PolynomialFeatures pour garder un workflow propre et reproductible.