Du linéaire au polynomial et au multivarié
Le moteur construit dans les leçons précédentes (model, cost_function, grad, gradient_descent) ne sait rien de la « régression linéaire » en tant que telle : il ne fait qu’optimiser des paramètres theta pour une matrice X donnée. Changer la nature du problème revient simplement à changer la construction de X.
Une métrique pour comparer les modèles
Section titled “Une métrique pour comparer les modèles”Avant de comparer plusieurs variantes, il faut une métrique d’évaluation en régression : le coefficient de détermination R² (déjà présenté au module 1), qui indique la part de variance expliquée par le modèle.
def r_squared(y, y_pred): ss_res = np.sum((y - y_pred) ** 2) ss_tot = np.sum((y - y.mean()) ** 2) return 1 - ss_res / ss_totCapturer un effet non linéaire
Section titled “Capturer un effet non linéaire”Au-delà d’un certain seuil de charge CPU, un phénomène de throttling thermique dégrade l’efficacité énergétique : la relation cesse d’être parfaitement linéaire.
consommation_nl = 8 * charge_cpu + 0.05 * charge_cpu ** 2 + 120 + bruit
charge_cpu_sq_std = standardize(charge_cpu ** 2)X_poly = make_design_matrix(charge_cpu_std, charge_cpu_sq_std)y_nl = consommation_nl.reshape(-1, 1)
theta_poly, cost_history_poly = gradient_descent( X_poly, y_nl, np.random.randn(3, 1), learning_rate=0.05, n_iterations=3000)pred_poly = model(X_poly, theta_poly)Aucune nouvelle fonction n’a été écrite : ajouter une colonne charge_cpu² à la matrice de design suffit à transformer une régression linéaire en régression polynomiale. C’est le modèle qui reste linéaire — linéaire en ses paramètres, pas nécessairement en la feature d’origine.
Un modèle linéaire sous-performe sur des données non linéaires
Section titled “Un modèle linéaire sous-performe sur des données non linéaires”theta_lin_on_nl, _ = gradient_descent( X_simple, y_nl, np.random.randn(2, 1), learning_rate=0.05, n_iterations=2000)pred_lin_on_nl = model(X_simple, theta_lin_on_nl)
print("R2 polynomial:", r_squared(y_nl, pred_poly))print("R2 lineaire (sous-ajuste):", r_squared(y_nl, pred_lin_on_nl))R2 polynomial: 0.9983942784910511R2 lineaire (sous-ajuste): 0.990557913374649L’écart est modeste ici (le terme quadratique reste discret sur la plage de charge observée), mais il est réel et mesurable : le modèle polynomial capture un peu mieux la courbure que le modèle purement linéaire, qui la lisse — un exemple concret de sous-apprentissage tel que défini au module 1.
Généraliser à plusieurs variables
Section titled “Généraliser à plusieurs variables”Le même principe s’applique pour ajouter des variables plutôt que des puissances d’une même variable :
ram_pct = np.random.uniform(20, 90, n_samples)trafic_reseau = np.random.uniform(5, 500, n_samples)consommation_multi = 6 * charge_cpu + 3 * ram_pct + 0.2 * trafic_reseau + 80 + np.random.normal(0, 20, n_samples)
X_multi = make_design_matrix(standardize(charge_cpu), standardize(ram_pct), standardize(trafic_reseau))y_multi = consommation_multi.reshape(-1, 1)
theta_multi, _ = gradient_descent( X_multi, y_multi, np.random.randn(4, 1), learning_rate=0.05, n_iterations=5000)pred_multi = model(X_multi, theta_multi)print("theta appris [cpu, ram, reseau, biais]:", theta_multi.ravel())print("R2:", r_squared(y_multi, pred_multi))theta appris [cpu, ram, reseau, biais]: [149.15378882 62.87138007 31.77429367 600.26004814]R2: 0.9855857992044985Trois variables standardisées, une colonne de biais, et c’est exactement le même gradient_descent qui s’applique — sans aucune modification. C’est la généralité de la formulation matricielle : model, cost_function et grad ne connaissent que la forme de X, jamais son contenu métier.
Prochaine étape
Section titled “Prochaine étape”Le moteur sait désormais prédire une quantité continue. Passons à la prédiction d’une catégorie.
👉 Basculer vers la classification
Junior TSAFACK – 12/09/2026