Modèle de régression linéaire from scratch pour la prédiction du poids corporel à partir de la taille — implémenté par descente de gradient batch avec normalisation z-score, validation complète des hypothèses OLS et tests statistiques rigoureux sur 25 000 observations.
Note finale : 9.5 / 10
BodyLine construit une régression linéaire simple sans bibliothèque de machine learning, à partir des gradients mathématiques, sur le dataset SOCR Height/Weight (25 000 individus). L'objectif est de prédire le poids (lbs) à partir de la taille (pouces) tout en respectant les hypothèses de la régression linéaire (OLS) et en validant chaque étape par comparaison avec scikit-learn.
Équation finale :
ŷ = 3.0693 × x_taille − 81.6062
Chaque pouce de taille supplémentaire est associé en moyenne à +3.07 lbs de poids.
| Métrique | Train | Test (hold-out) |
|---|---|---|
| R² | 0.2509 | 0.2606 |
| RMSE | — | 10.12 lbs |
| MAE | — | 8.03 lbs |
| MAPE | — | 6.44% |
Delta R² (test − train) = +0.010 → aucun overfitting.
R² max théorique = r² = 0.503² ≈ 0.253 → le modèle atteint son plafond théorique.
BodyLine/
├── main.ipynb # Notebook complet — pipeline from scratch
├── SOCR-HeightWeight.csv # Dataset (25 000 observations)
├── index.html # Dashboard d'analyse interactif
└── README.md # Ce fichier
| Propriété | Valeur |
|---|---|
| Source | SOCR Height/Weight Dataset (domaine public) |
| Observations | 25 000 |
| Variable prédictive X | Height en pouces (60.28 – 75.15 in) |
| Variable cible Y | Weight en livres (78.02 – 170.92 lbs) |
| Valeurs manquantes | 0 |
| Corrélation de Pearson | r = 0.5029 |
| R² max théorique | 0.2529 |
- Split train/test 80/20 (seed = 42) → 20 000 train, 5 000 test
- Normalisation z-score sur le train uniquement — pas de data leakage :
x_n = (x - μ_x) / σ_x # μ = 67.99, σ = 1.897
y_n = (y - μ_y) / σ_y # μ = 127.06, σ = 11.66Fonction de coût (MSE/2) :
J(w, b) = (1 / 2m) × Σ (w·x_i + b − y_i)²Descente de gradient batch :
dw = (1/m) × Σ (ŷ_i − y_i) · x_i
db = (1/m) × Σ (ŷ_i − y_i)
w ← w − lr · dw
b ← b − lr · dbHyperparamètres :
| Paramètre | Valeur |
|---|---|
Taux d'apprentissage lr |
0.01 |
| Itérations max | 10 000 |
| Tolérance (critère d'arrêt) | 1e-9 |
| Convergence effective | itération 733 |
Coût : 0.4975 (init) → 0.3746 (final) — réduction de 24.7%.
w_orig = w_n × (σ_y / σ_x) = 3.0693
b_orig = μ_y + σ_y × b_n − w_orig × μ_x = −81.6062| Paramètre | From Scratch | Sklearn | Δ |
|---|---|---|---|
| Pente w | 3.0693 | 3.0693 | < 1e-4 ✓ |
| Biais b | −81.6062 | −81.6062 | < 1e-4 ✓ |
| R² Test | 0.2606 | 0.2606 | 0.0000 ✓ |
| Hypothèse | Test | Résultat | Verdict |
|---|---|---|---|
| Normalité des résidus | Shapiro-Wilk | p = 0.40 | ✅ OK |
| Normalité des résidus | Kolmogorov-Smirnov | p = 0.62 | ✅ OK |
| Autocorrélation | Durbin-Watson | DW = 1.9975 | ✅ OK |
| Significativité pente | t de Student | t = 81.79, p ≈ 0 | ✅ OK |
| Homoscédasticité | Corr. |résidus|~x | r = −0.04, p = 0.004 | |
| Linéarité | Pearson r | r = 0.503 | ✅ OK |
Via la distribution de Student (df = n − 2 = 19 998) :
w : 3.0693 IC95% [2.996 ; 3.143] lbs/in SE = 0.0375
b : −81.61 IC95% [−84.17 ; −79.05] lbs
La pente exclut 0 → significativité statistique absolue (t = 81.79).
def predict(height_in_inches):
"""
Prédit le poids (lbs) à partir de la taille (pouces).
Plage valide : 60.28 – 75.15 in (plage du train).
Raises: TypeError (non-numérique) · ValueError (hors plage)
"""
if not isinstance(height_in_inches, (int, float)):
raise TypeError(...)
if not (HEIGHT_MIN <= height_in_inches <= HEIGHT_MAX):
raise ValueError(...)
return w_orig * height_in_inches + b_origExemples :
| Taille | Taille (cm) | Prédiction | Prédiction (kg) |
|---|---|---|---|
| 62.0 in | 157.5 cm | 109.1 lbs | 49.5 kg |
| 67.5 in | 171.5 cm | 125.8 lbs | 57.1 kg |
| 70.0 in | 177.8 cm | 133.3 lbs | 60.5 kg |
| 72.0 in | 182.9 cm | 139.4 lbs | 63.2 kg |
| Critère | Note | Détail |
|---|---|---|
| Normalisation & No-Leak | 10/10 | z-score sur train uniquement, dénormalisation correcte |
| Convergence réelle | 10/10 | Iter 733 · tol=1e-9 · courbe monotone |
| Évaluation complète | 10/10 | R²/RMSE/MAE train+test · courbe d'apprentissage |
| Robustesse predict() | 10/10 | TypeError + ValueError + 6 tests |
| Homoscédasticité | 7/10 | r=−0.04, p=0.004 — légère, inhérente au dataset |
| R² = 0.26 | — | Non pénalisé — plafond théorique du dataset |
Note finale : 9.5 / 10
- Plafond R² ≈ 0.26 : la corrélation height/weight (r=0.503) plafonne mécaniquement le R² à ~0.253. Un modèle multivarié (âge, sexe, composition corporelle) serait significativement plus précis.
- Variable unique : le poids dépend de nombreux facteurs non capturés dans ce dataset.
- Légère hétéroscédasticité : r=−0.04, p=0.004 — amplitude faible, attendu pour des données physiologiques univariées.
- Extrapolation interdite : la fonction
predict()rejette toute valeur hors de [60.28 ; 75.15] pouces. - Usage : démonstration pédagogique. Ne pas utiliser comme outil médical ou décisionnel.
# Cloner le dépôt
git clone https://github.com/delsDin/BodyLine.git
cd BodyLine
# Installer les dépendances
pip install pandas numpy matplotlib seaborn scipy scikit-learn
# Lancer le notebook
jupyter notebook main.ipynb
# Ouvrir le dashboard
open index.htmlDépendances :
| Package | Rôle |
|---|---|
numpy |
Calculs vectorisés (gradient, normalisation) |
pandas |
Chargement et exploration du dataset |
matplotlib / seaborn |
Visualisations |
scipy.stats |
Tests Shapiro-Wilk, KS, Durbin-Watson, t de Student |
scikit-learn |
Split train/test + référence de validation |
Dels Dinla Marcel — Licence 1 Informatique · IFRI, Bénin Certifications : Python & Data Science (OpenClassrooms), Regression Linéaire (Machine Learning | IBM - Coursera)
Projets connexes : Delsat · Delsio · SalaryMapper
BodyLine — Régression linéaire from scratch · SOCR Height/Weight · 25 000 obs · Gradient Descent · z-score · OLS