- 🚀 Objectif du projet
- 🧰 Stack technologique
- ⚡ Démarrage rapide
- 🛠️ Commandes Make
- 🧪 Procédure de soutenance
- 📦 Utilisation
- 📝 Données
- 🧠 Architecture
- 🛠️ Fichiers de configuration
- 🧪 Tests
- 🔍 Qualité du code
- 📚 Documentation liée
- 🛡️ Licence
Implémenter un premier algorithme de Machine Learning : une régression linéaire simple.
👉 Prédire le prix d’une voiture en fonction de son kilométrage via :
- Deux programmes obligatoires :
train.py→ entraîne le modèle (descente de gradient, mise à jour simultanée de θ).predict.py→ prédit un prix à partir d’un kilométrage (0 avant entraînement).
🎯 Conformité stricte à l’énoncé 42 :
- Pas de
numpy.polyfit/sklearn.LinearRegression. - θ sauvegardés entre runs dans
theta.json. - Prédiction = 0 avant tout entraînement.
- Pas de crash en soutenance.
- Python : 3.10.18 (Ubuntu 22.04.5 Jammy)
- Gestion dépendances : Poetry
- Qualité / CI :
pytest,coverage,ruff,mypy,mutmut(mutation testing) - Visualisation (bonus uniquement) : matplotlib (installé sur demande via
poetry install --with viz)
En cas d’entrée invalide (ex. kilométrage négatif ou non numérique) : le programme écrit un message
ERROR: ...sur stderr et quitte avec exit 2.
# Avec Poetry (recommandé) poetry install --with devℹ️ Bonus non installé par défaut
Pour activer uniquement la visualisation bonus :
poetry install --with viz --with dev
# Entraînement poetry run train --data data/samples/data.csv --alpha 0.1 --iters 1000 --theta theta.json # Prédiction poetry run predict 85000 --theta theta.jsonℹ️ Si la droite rouge affichée par
vizreste quasiment horizontale, vérifiez le contenu detheta.json. Une valeur de--alphatrop faible (par exemple1e-7) laisse les coefficients proches de zéro. Utilisez--alpha 0.1(ou0.01) et suffisamment d'itérations pour obtenir une pente négative réaliste.
Les principales cibles du Makefile facilitent l'installation, la qualité du code et l'utilisation du modèle :
| Commande | Description |
|---|---|
make install | Installe les dépendances avec Poetry (groupe dev inclus). |
make lint | Analyse statique du code avec Ruff. |
make format | Formate le code et applique les corrections automatiques de Ruff. |
make type | Vérifie les types avec Mypy. |
make test | Lance les tests unitaires via Pytest. |
make cov | Produit les rapports de couverture (JSON, HTML, console). |
make mut | Exécute les tests de mutation avec Mutmut. |
make train | Entraîne le modèle ; variables personnalisables : DATA, ALPHA, ITERS, THETA. |
make predict [km] | Prédit le prix pour un kilométrage donné. |
make viz | (Bonus) Affiche les données et la droite de régression. |
Scénario officiel à démontrer en soutenance, en trois étapes obligatoires :
Étape A : prédiction avant tout entraînement
Suppression du fichier de paramètres
rm -f theta.json python3 -m src.predict 50000 --theta theta.json→ Résultat attendu : 0 (θ₀=0, θ₁=0 par défaut)
Étape B : entraînement du modèle
poetry run train --data data.csv --alpha 0.1 --iters 1000 --theta theta.json→ Apprentissage des paramètres θ₀ et θ₁, sauvegardés dans theta.json
Étape C : prédiction après entraînement → Résultat attendu : prix non nul, cohérent avec la droite apprise (≈ CSV)
python3 -m src.predict 50000 --theta theta.jsonÉvaluable uniquement si le mandatory est parfait. Non requis pour la soutenance.
poetry run python -m src.viz --data data.csv --theta theta.json --show-residualsAjoutez --show-residuals pour tracer des lignes verticales représentant les résidus. Utilisez --sigma-k (défaut 2) pour colorer en orange les points dont |résidu| > k·σ; ils sont ajoutés à la légende sous le nom « outliers ».
Nuage de points et droite θ₀ + θ₁·x (après entraînement).
- Mode interactif :
predict.pydemande un kilométrage si non fourni.
$ make predict poetry run predict --theta theta.json Enter mileage: 23000 Predicted price: 7991.88 €- End-to-End :
predict (0)→train→predict ≈ prix.
- Fichier :
data/samples/data.csv(colonneskm,price). - Hypothèses :
- km ≥ 0
- valeurs numériques uniquement
- 24 lignes d’exemple (corrélation ≈ −0,86)
. ├── AGENTS.md ├── author ├── codecov.yml ├── CONTRIBUTING.md ├── coverage.json ├── data │ ├── benchmarks │ │ ├── data_anscombe_I.csv │ │ ├── data_anscombe_II.csv │ │ ├── data_anscombe_III.csv │ │ ├── data_anscombe_IV.csv │ │ ├── data_away.csv │ │ ├── data_bullseye.csv │ │ ├── data_circle.csv │ │ ├── data_collinear.csv │ │ ├── data.csv │ │ ├── data_dino.csv │ │ ├── data_dots.csv │ │ ├── data_duplicate.csv │ │ ├── data_flat.csv │ │ ├── data_high_lines.csv │ │ ├── data_h_lines.csv │ │ ├── data_inverse.csv │ │ ├── data_noise.csv │ │ ├── data_nonlinear.csv │ │ ├── data_outlier.csv │ │ ├── data_slant_down.csv │ │ ├── data_slant_up.csv │ │ ├── data_small.csv │ │ ├── data_sparse.csv │ │ ├── data_star.csv │ │ ├── data_step.csv │ │ ├── data_v_lines.csv │ │ ├── data_wide_lines.csv │ │ └── data_x_shape.csv │ └── samples │ └── data.csv ├── docs │ ├── assets │ │ └── plots │ │ ├── confiance │ │ │ ├── fig01_donnees.png │ │ │ ├── fig02_droite_ols.png │ │ │ ├── fig03_residus_sigma.png │ │ │ ├── fig04_effet_levier.png │ │ │ ├── fig05_SE.png │ │ │ ├── fig06_bande_95.png │ │ │ └── fig07_tableau.png │ │ ├── examples │ │ │ └── price-vs-km-regression.png │ │ └── regression │ │ ├── etape1_donnees_brutes.png │ │ ├── etape2_droite_initiale.png │ │ ├── etape3_droites_successives.png │ │ ├── etape4_erreurs_initiales.png │ │ ├── etape5_erreurs_finales.png │ │ ├── etape6_theta0_vs_iter.png │ │ ├── etape7_theta1_vs_iter.png │ │ └── etape8_cout_vs_iter.png │ ├── confidence_band.md │ └── regression_lineaire.md ├── LICENSE ├── Makefile ├── poetry.lock ├── poetry.toml ├── pyproject.toml ├── README.md ├── src │ ├── linear_regression.py │ ├── metrics.py │ ├── predict │ │ ├── __init__.py │ │ ├── __main__.py │ │ └── predict.py │ ├── train │ │ ├── __init__.py │ │ ├── __main__.py │ │ └── train.py │ └── viz.py └── tests ├── test_accuracy_main.py ├── test_cli.py ├── test_data_parsing.py ├── test_e2e.py ├── test_estimate_price.py ├── test_gradient.py ├── test_json.py ├── test_main_modules.py ├── test_metrics.py ├── test_parser.py ├── test_predict_logic.py └── test_viz.py (Bonus : viz.py affiche données + droite de régression) Les tests E2E vérifient aussi les messages d’erreurs exacts (snapshot) et les codes de sortie (0/1/2).
pyproject.toml(Poetry, dépendances, lint, type check)- Groupe optionnel [tool.poetry.group.viz] (non installé par défaut, réservé au bonus)
requirements.txt(fallback sans Poetry).coveragerc,.gitignore,Makefile(raccourcis CI/CD)- Note :
theta.jsonest listé dans.gitignore→ ne jamais le versionner.
- Portée des tests (mandatory) :
train.py,predict.py,io_utils.py, CLI, I/O θ, stratégie GD. viz.pyest hors mandatory et hors périmètre des exigences minimales (peut être testé si le bonus est activé).
- Comparaisons float avec
pytest.approxuniquement (rtol=1e-2), jamais==. - Test dédié qui échoue si la mise à jour des θ n’est pas simultanée (utilisation de temporaires).
- Tests robustesse I/O : CSV manquant, colonnes inattendues, valeurs non numériques, JSON
thetaabsent/corrompu. - Vérification des messages d’erreurs et codes retour (exemples attendus) :
ERROR: invalid CSV format (expected columns: km,price)→ exit 2ERROR: invalid mileage (must be a non-negative number)→ exit 2ERROR: theta file not found: <path>→ exit 2
predict(0)=0→train→predict(km_csv) ≈ price.- CLI
--help(exit 0), erreurs d’options (exit ≠ 0, message).- Entrée interactive : prompt si kilométrage manquant, gestion EOF/pipe.
pytest -q coverage run -m pytest coverage json coverage report --fail-under=100 coverage html --skip-empty --show-contextsLes programmes doivent imprimer ces messages à l’identique sur stderr et quitter avec le code indiqué.
ERROR: theta file not found: <path>→ exit 2ERROR: invalid CSV format (expected columns: km,price)→ exit 2ERROR: invalid mileage (must be a non-negative number)→ exit 2
Règles générales :
- 0 : exécution nominale (train/predict OK).
- 2 : erreur d’usage/entrée/I‑O/validation (fichier manquant, CSV invalide, saisie invalide, etc.).
- 1 : erreur interne inattendue (exception non prévue).
Tests recommandés :
- Snapshot minimal des messages d’aide (
--help) et d’erreur (texte essentiel, stable). - Asserts explicites sur
returncode(0, 1 ou 2 selon les cas).
✅ Objectifs qualité (mandatory) :
- Coverage 100 % (statements + branches + diff + contrôle fichier).
- Mutation testing ≥90 % (scope global mandatory, avec survivants justifiés).
- Tolérance floats stricte : toujours utiliser
pytest.approx(..., rel=1e-2)(jamais==sur floats). - Test dédié “MAJ simultanée” : un test échoue explicitement si θ₀, θ₁ sont mis à jour séquentiellement (sans temporaires).
- Tests E2E :
predict(0)=0 → train → predict≈csv. - Tests robustesse I/O : CSV manquant, mal formé, km négatif, NaN, EOF/pipe.
- Tests CLI :
--help, erreurs d’options → exit ≠ 0 avec message clair. - Codes retour : 0 succès, ≠0 échec.
- Formatage & imports :
ruff format,isort. - Typage statique :
mypy. - Lint :
ruff check. - CI/CD Ubuntu-only (GitHub Actions).
- Hooks
pre-commitpour vérifier format/lint/tests rapides avant commit.
AGENTS.md→ Blueprint complet CI/CD + checklist défense-proof.ft_linear_regression_checklist_défense-proof.txt→ Qualité tests & couverture.ft_linear_regression_murphy_law.txt→ Risques & contre-mesures.- Énoncé officiel : ft_linear_regression.en.subject.pdf.
- Le bonus est cloisonné : il ne doit pas interférer avec le mandatory ni impacter la CI de base.
Les contenus suivants ont été essentiels pour comprendre et implémenter la régression linéaire et l’algorithme du gradient :
-
🎥 Playlist YouTube — Machine Learning from Scratch
Série pédagogique détaillant les fondements du Machine Learning et la régression linéaire. -
📄 Wikipédia — Fonction linéaire (analyse)
Définitions et propriétés mathématiques de la fonction linéaire. -
📄 Wikipédia — Algorithme du gradient
Explication théorique de la descente de gradient et de ses applications en optimisation.