Régression Polynomiale : Guide Complet — Principes, Exemples et Implémentation Python

Régression Polynomiale : Guide Complet — Principes, Exemples et Implémentation Python

Régression Polynomiale : Guide Complet — Principes, Exemples et Implémentation Python

Résumé introductif

La régression polynomiale étend la régression linéaire en ajoutant des puissances de la variable d’entrée, permettant ainsi de capturer des relations non-linéaires entre les caractéristiques et la cible. C’est l’une des premières techniques à apprendre lorsque votre modèle linéaire échoue à épouser la courbure de vos données.

La régression polynomiale est un algorithme d’apprentissage supervisé qui transforme un problème de régression linéaire en un modèle capable d’ajuster des courbes complexes, tout en restant fondamentalement un modèle linéaire résolu par les moindres carrés. On l’utilise dès qu’un nuage de points révèle une tendance courbe : parabole, croissance exponentielle, décroissance asymptotique, etc.


Principe mathématique

Le modèle polynomial

Dans une régression linéaire simple, on prédit la variable cible y à partir d’une unique caractéristique x selon la formule :

ŷ = w₀ + w₁ · x

La régression polynomiale généralise cette formule en ajoutant des puissances successives de x :

ŷ = w₀ + w₁·x + w₂·x² + w₃·x³ + … + w_d·x^d

où :

  • d est le degré du polynôme, un hyperparamètre entier positif choisi par le praticien.
  • w₀ est le biais (ordonnée à l’origine).
  • w₁, w₂, …, w_d sont les coefficients appris par le modèle.

L’expansion de caractéristiques (feature expansion)

L’idée centrale est la suivante : on transforme la variable d’entrée x en un vecteur de caractéristiques étendu :

x  ⟶  [x, x², x³, …, x^d]

Puis on applique une régression linéaire ordinaire sur ce nouveau jeu de données. Autrement dit, la régression polynomiale est linéaire par rapport aux coefficients w, même si la relation avec x est non-linéaire. C’est cette astuce qui rend le problème convexe et facilement résolvable.

En cas de régression polynomiale multivariée (plusieurs caractéristiques x₁, x₂, …), l’expansion génère aussi des termes d’interaction :

[x₁, x₂, x₁², x₁·x₂, x₂², x₁³, …]

Le nombre de caractéristiques croît alors de façon combinatoire avec le degré d et le nombre de variables initiales p, suivant la formule du coefficient binomial :

Nombre de features = C(p + d, d) = (p + d)! / (p! · d!)

Par exemple, avec 2 variables et un degré 4, on passe de 2 à C(6,4) = 15 caractéristiques.

Fonction de coût : l’erreur quadratique moyenne (MSE)

Comme en régression linéaire, on minimise l’erreur quadratique moyenne :

MSE = (1/n) · Σ (y_i − ŷ_i)²

La solution analytique par les moindres carrés ordinaires (OLS) s’écrit :

w = (Xᵀ · X)⁻¹ · Xᵀ · y

X est la matrice de design contenant les caractéristiques polynomiales de chaque exemple, et y est le vecteur des cibles.

Le compromis biais-variance lié au degré

Le choix du degré d est l’enjeu principal de la régression polynomiale :

  • Degré trop faible (sous-apprentissage) : le modèle est trop rigide pour épouser la courbure des données. Le biais est élevé, l’erreur sur les données d’entraînement et de test est importante.
  • Degré bien choisi : le modèle capture la forme réelle de la relation sans mémoriser le bruit. Le compromis biais-variance est optimal.
  • Degré trop élevé (sur-apprentissage) : le modèle oscille sauvagement pour passer par chaque point d’entraînement, y compris le bruit. La variance explose, et les performances sur des données invisibles s’effondrent.

Ce compromis biais-variance structure tout le raisonnement autour de la régression polynomiale et justifie l’usage rigoureux de la validation croisée pour sélectionner le degré optimal.


Intuition — Comment le comprendre ?

Imaginez que vous tracez un nuage de points représentant la relation entre la vitesse d’un véhicule et sa distance de freinage. Les points ne s’alignent pas sur une droite : ils forment une courbe qui s’infléchit vers le haut. Une droite de régression linéaire couperait à côté de cette courbure.

Maintenant, ajoutez la puissance carrée de la vitesse comme nouvelle caractéristique. Le modèle peut désormais pondérer séparément x et . Avec un terme en , il peut dessiner une parabole. Avec , il peut ajouter une inflexion. Chaque degré supplémentaire offre un degré de liberté supplémentaire pour « plier » la courbe et mieux suivre les données.

Analogie géométrique

Pensez au degré d comme au nombre de charnières d’une règle flexible :

  • d = 1 : une règle rigide — une droite.
  • d = 2 : une charnière au milieu — une parabole.
  • d = 3 : deux charnières — une cubique avec un point d’inflexion.
  • d = 10 : neuf charnières — une courbe très flexible qui peut onduler de façon erratique.

Le piège du sur-apprentissage

Avec un degré élevé, le polynôme dispose de tellement de flexibilité qu’il finit par épouser non seulement le signal sous-jacent, mais aussi le bruit aléatoire. Le résultat est une courbe avec des oscillations extrêmes entre les points d’entraînement, sans aucune capacité de généralisation. C’est pourquoi la régression polynomiale s’accompagne presque toujours d’une régularisation (Ridge, Lasso) lorsque le degré est important, et d’une validation croisée pour choisir le degré optimal.


Implémentation Python — Exemple complet

Installation des dépendances

pip install scikit-learn numpy matplotlib

Code complet : données quadratiques bruitées

Le script ci-dessous génère des données suivant un modèle quadratique, applique la régression polynomiale avec différents degrés, visualise les courbes ajustées et compare les erreurs MSE.

# ============================================================
# Régression Polynomiale — Exemple complet avec scikit-learn
# ============================================================

import numpy as np
import matplotlib.pyplot as plt
from sklearn.preprocessing import PolynomialFeatures
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error
from sklearn.pipeline import make_pipeline

# ----------------------------------------------------------
# 1. Génération de données synthétiques quadratiques bruitées
# ----------------------------------------------------------
# On crée 100 points suivant y = 0.5 * x² + x + 2 + bruit gaussien
np.random.seed(42)
n_samples = 100
X = np.linspace(-3, 3, n_samples).reshape(-1, 1)
y_true = 0.5 * X.ravel()**2 + X.ravel() + 2  # relation quadratique réelle
noise = np.random.normal(0, 1.5, n_samples)   # bruit gaussien
y = y_true + noise

# ----------------------------------------------------------
# 2. Entraînement de modèles polynomiaux pour plusieurs degrés
# ----------------------------------------------------------
degrees = [1, 2, 3, 8, 15]  # degrés à tester
colors = ['gray', 'blue', 'green', 'orange', 'red']

fig, axes = plt.subplots(1, 2, figsize=(14, 5))

# --- Sous-graphique : courbes ajustées ---
ax1 = axes[0]
ax1.scatter(X, y, alpha=0.4, s=20, color='black', label='Données bruitées')
ax1.plot(X, y_true, linestyle='--', linewidth=2, color='purple',
         label='Vraie fonction (y = 0.5x² + x + 2)')

mse_train = []

for degree, color in zip(degrees, colors):
    # Pipeline : expansion polynomiale + régression linéaire
    model = make_pipeline(
        PolynomialFeatures(degree=degree, include_bias=False),
        LinearRegression()
    )
    model.fit(X, y)

    # Prédictions sur une grille fine pour un tracé lisse
    X_grid = np.linspace(-3.5, 3.5, 300).reshape(-1, 1)
    y_pred = model.predict(X_grid)

    # Calcul du MSE sur les données d'entraînement
    y_pred_train = model.predict(X)
    mse = mean_squared_error(y, y_pred_train)
    mse_train.append(mse)

    # Tracé de la courbe ajustée
    label = f'degré {degree} — MSE = {mse:.2f}'
    ax1.plot(X_grid, y_pred, linewidth=1.5, color=color, label=label)

ax1.set_title('Ajustement polynomial pour différents degrés')
ax1.set_xlabel('x')
ax1.set_ylabel('y')
ax1.legend(fontsize=8, loc='upper left')
ax1.grid(True, alpha=0.3)

# --- Sous-graphique : MSE par degré ---
ax2 = axes[1]
ax2.bar([str(d) for d in degrees], mse_train, color=colors, edgecolor='black')
ax2.set_title('Erreur MSE en fonction du degré')
ax2.set_xlabel('Degré du polynôme')
ax2.set_ylabel("MSE (données d'entraînement)")
ax2.grid(True, axis='y', alpha=0.3)

# Annotation : souligner le comportement de sur-apprentissage
ax2.annotate('Sur-apprentissage\\nà partir de degré 8',
             xy=('8', mse_train[3]), xytext=('10', mse_train[3] + 2),
             arrowprops=dict(arrowstyle='->', color='red'),
             fontsize=9, color='red')

plt.tight_layout()
plt.savefig('regression_polynomiale.png', dpi=150)
plt.show()

# ----------------------------------------------------------
# 3. Affichage détaillé des résultats
# ----------------------------------------------------------
print('=' * 50)
print('Régression Polynomiale — Résultats détaillés')
print('=' * 50)
for degree, mse in zip(degrees, mse_train):
    print(f"Degré {degree:2d}  |  MSE d'entraînement : {mse:.4f}")

Explication pas à pas

  1. Génération des données : On crée 100 points selon une relation quadratique vraie (y = 0,5x² + x + 2) avec un bruit gaussien d’écart-type 1,5. Cela simule un scénario réaliste où le signal sous-jacent est masqué par du bruit.
  2. Pipeline scikit-learn : L’outil make_pipeline enchaîne automatiquement PolynomialFeatures et LinearRegression. Pour chaque degré, les données X sont d’abord transformées en caractéristiques polynomiales, puis le modèle de régression linéaire est ajusté sur ces nouvelles caractéristiques.
  3. Évaluation : On calcule le MSE pour chaque degré sur l’ensemble d’entraînement. Le degré 2 devrait obtenir le MSE le plus proche de la variance du bruit (≈ 2,25), confirmant qu’il a identifié la bonne forme fonctionnelle.
  4. Visualisation : Le graphique de gauche superpose les courbes ajustées. Le graphique de droite montre l’évolution du MSE. On observe typiquement que le MSE diminue jusqu’au degré 2, puis continue de baisser (le modèle mémorise le bruit) tandis que la courbe devient erratique.

Ce qu’il faut retenir

Le degré 2 reconnaît la forme quadratique réelle. Le degré 1 est trop simple (biais élevé). Les degrés 8 et 15 surajustent : leurs courbes ondulent entre les points, signe classique de sur-apprentissage en régression polynomiale.

Sélection automatique du degré par validation croisée

Dans la pratique, on ne connaît pas la forme véritable de la fonction. Voici comment sélectionner le degré optimal par validation croisée :

from sklearn.model_selection import cross_val_score

degre_optimal = 0
meilleur_score = -np.inf

for d in range(1, 11):
    modele = make_pipeline(
        PolynomialFeatures(degree=d, include_bias=False),
        LinearRegression()
    )
    # R² moyen sur 5 plis de validation croisée
    scores = cross_val_score(modele, X, y, cv=5, scoring='r2')
    score_moyen = scores.mean()
    if score_moyen > meilleur_score:
        meilleur_score = score_moyen
        degre_optimal = d

print(f'Degré optimal : {degre_optimal}  |  R² moyen : {meilleur_score:.4f}')

Cette approche évalue la capacité de généralisation du modèle pour chaque degré et retient celui qui maximise le score R² moyen sur les plis de validation.


Hyperparamètres

Le tableau ci-dessous résume les hyperparamètres clés de la régression polynomiale dans scikit-learn :

Nom Rôle Valeurs typiques Impact
degree Degré du polynôme : nombre de puissances de x à générer 1 à 10 (rarement au-delà) Contrôle directement la flexibilité du modèle. Un degré faible sous-ajuste, un degré élevé sur-ajuste. C’est l’hyperparamètre le plus critique.
include_bias Ajoute ou non une colonne de 1 (terme constant) dans la matrice de caractéristiques True (défaut), False Si True, une colonne de 1 est ajoutée aux caractéristiques. En pratique, on préfère False pour laisser LinearRegression(fit_intercept=True) gérer le biais séparément, ce qui évite des redondances.
interaction_only Génère uniquement les termes d’interaction entre différentes variables, sans les puissances pures False (défaut), True Utile en régression multivariée quand on souhaite des interactions croisées (x₁·x₂) mais pas de termes quadratiques purs (x₁²). Réduit drastiquement le nombre de caractéristiques générées.
fit_intercept (LinearRegression) Indique si le modèle doit apprendre un biais w₀ True (défaut), False Si PolynomialFeatures(include_bias=False) est utilisé, il faut garder
it_intercept=True. Inversement, si include_bias=True, on peut positionner
it_intercept=False.

Avantages et Limites

Avantages

  • Simplicité conceptuelle : prolongement naturel de la régression linéaire, facile à expliquer et à implémenter.
  • Pas d’algorithme itératif : résolu analytiquement par les moindres carrés, donc convergence garantie et rapide.
  • Interprétabilité : les coefficients w₁, w₂, … indiquent directement la contribution de chaque puissance de x à la prédiction.
  • Pipeline natif scikit-learn : PolynomialFeatures combiné à n’importe quel estimateur linéaire se code en quelques lignes.
  • Excellente base pédagogique : porte d’entrée idéale pour comprendre le sur-apprentissage, le compromis biais-variance et les mécanismes de régularisation.
  • Extensible : s’associe naturellement avec Ridge, Lasso ou ElasticNet pour contrôler le sur-apprentissage quand le degré est élevé.

Limites

  • Explosion combinatoire : avec p variables et un degré d, le nombre de caractéristiques suit une croissance binomiale. Déjà pour p = 10, d = 4, on atteint 210 caractéristiques.
  • Sensibilité aux valeurs extrêmes : les puissances élevées amplifient les valeurs de x extrêmes, rendant le modèle instable en présence d’outliers.
  • Extrapolation dangereuse : un polynôme de degré élevé diverge rapidement en dehors de l’intervalle d’entraînement, produisant des prédictions totalement incohérentes.
  • Multicolinéarité : les colonnes x, x², x³, … sont fortement corrélées entre elles, ce qui dégrade la stabilité numérique de l’inversion de matrice.
  • Pas automatique : le choix du degré et la régularisation nécessitent une recherche manuelle ou une validation croisée systématique.
  • Inadapté aux structures complexes : ne capture pas les discontinuités, les seuils brutaux, ou les interactions non-polynomiales. Pour ces cas, les forêts aléatoires ou les réseaux de neurones sont plus appropriés.

Cas d’usage concrets

1. Trajectoire balistique et physique expérimentale

En physique expérimentale, la position d’un objet en chute libre suit une loi quadratique du temps (y = ½gt² + v₀t + y₀). La régression polynomiale de degré 2 permet d’estimer la gravité g et la vitesse initiale v₀ à partir de mesures bruitées. C’est un cas où le degré est déterminé par la théorie physique, pas par la recherche sur grille.

2. Courbe de rendement des cultures

En agronomie, le rendement d’une culture en fonction de la quantité d’engrais suit souvent une courbe en cloche (loi des rendements décroissants). Un polynôme de degré 2 ou 3 modélise efficacement cette relation et permet d’identifier le point optimal d’apport d’engrais — celui qui maximise le rendement sans gaspillage ni pollution.

3. Calibration de capteurs industriels

Les capteurs industriels (température, pression, humidité) présentent souvent une réponse non-linéaire par rapport à la grandeur mesurée. On utilise la régression polynomiale pour établir une courbe d’étalonnage qui transforme le signal brut du capteur en une mesure physique précise. Les degrés 2 à 4 sont les plus courants dans cette application.

4. Modélisation de la demande énergétique

La consommation électrique d’un bâtiment en fonction de la température extérieure forme une courbe en U : forte en hiver (chauffage), faible au printemps et en automne, forte en été (climatisation). Un polynôme de degré 2 ou 3 capture cette courbe en U et alimente des modèles de prévision de charge pour les gestionnaires de réseau électrique.


Voir aussi


Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur la façon dont les données de vos commentaires sont traitées.