Architettura del progetto
1. Layoutβ
ames-housing-price-pipeline/
βββ README.md Quick-start, risultati, badge.
βββ LICENSE MIT.
βββ pyproject.toml Build config + dipendenze.
βββ requirements.txt Lock approssimativo per chi non usa pyproject.
β
βββ src/ames_pipeline/ Codice sorgente (installabile via pip install -e .)
β βββ __init__.py
β βββ config.py Path, costanti, iperparametri di default.
β βββ data.py Download + load + split.
β βββ wrangling.py NaN strutturali + outlier.
β βββ features.py AmesFeatureEngineer (sklearn transformer).
β βββ preprocessing.py build_preprocessor β ColumnTransformer.
β βββ models.py 3 pipeline candidate (Ridge, RF, XGB).
β βββ tuning.py Grid/Randomized search con TransformedTargetRegressor.
β βββ evaluation.py Metriche, plot, feature importance.
β βββ inference.py predict_price() per inferenza singola/batch.
β βββ pipeline.py Orchestratore end-to-end + CLI.
β
βββ notebooks/ Documentazione esecutiva e didattica.
β βββ 01_eda.ipynb
β βββ 02_preprocessing_features.ipynb
β βββ 03_modeling_tuning.ipynb
β βββ 04_evaluation_inference.ipynb
β
βββ data/ Tutti i dataset (gitignored eccetto .gitkeep)
β βββ raw/ File originali da JSE (AmesHousing.txt, doc).
β βββ processed/ Output preprocessing (uso interno).
β βββ external/ Eventuali dataset arricchimento.
β
βββ reports/
β βββ figures/ PNG dei plot (predizioni, residui, importance).
β βββ models/ Modelli serializzati (.joblib) β gitignored.
β βββ cv_summary.csv Tabella CV scores.
β βββ holdout_metrics.json Metriche holdout JSON.
β
βββ scripts/
β βββ build_notebooks.py Genera i 4 notebook da sorgente Python.
β βββ run_full.sh Pipeline completa (training + notebook).
β
βββ tests/ Smoke test della pipeline.
β
βββ docs/
β βββ teoria/ 5 file Markdown didattici.
β βββ scelte_tecniche/ Documenti di design (questo file).
β
βββ venv/ Virtual environment (gitignored).
2. Principi di designβ
2.1 Separazione src/ vs notebooks/β
Il codice riutilizzabile vive in src/ames_pipeline/. I notebook sono solo presentazione: contengono solo importazioni, chiamate alle funzioni di src/, e narrazione didattica.
Vantaggi:
- Modifiche al codice riflesse automaticamente nei notebook (basta riavviare il kernel).
- Niente duplicazione: la logica esiste una sola volta.
- Test unitari possibili sul codice in
src/(i notebook non sono test-friendly).
2.2 Notebook generati da scriptβ
I 4 notebook sono prodotti da scripts/build_notebooks.py. Per modificare un notebook si edita lo script e si rilancia. Vantaggi:
- Diff Git puliti: niente cambi spuri di metadata, output cells, kernel hash.
- RiproducibilitΓ : chiunque puΓ² rigenerare i notebook identici.
- Sorgente in formato testuale: il
.pyè searchable/grep-abile come ogni Python file.
2.3 Pipeline come oggetto sklearnβ
Tutte le trasformazioni che dipendono da statistiche del dataset sono dentro un sklearn.pipeline.Pipeline. Vantaggi:
- No leakage (vedi
docs/teoria/05_pipeline_e_data_leakage.md). - Persistenza: un singolo
joblib.dump(pipeline)salva preprocessing + modello. - API uniforme:
fit/predict/scorestandard sklearn β integrabile con altri tool (ONNX, MLflow).
2.4 Configurazione centralizzataβ
Tutti i path, le costanti, le grid di iperparametri vivono in config.py. Niente magic number sparsi nel codice.
PipelineConfig Γ¨ un @dataclass(frozen=True): ogni esperimento crea un proprio config immutabile, nessuna mutazione accidentale.
3. Punti di estensioneβ
3.1 Aggiungere un nuovo modelloβ
- Implementare la pipeline in
models.py(es.lightgbm_pipeline). - Aggiungerla al dizionario in
get_all_pipelines. - Definire la grid in
config.py(LIGHTGBM_PARAM_GRID). - Aggiungere il caso in
tuning.tune_all_models.
Il resto del codice (evaluation, inference) funziona senza modifiche grazie al polimorfismo sklearn.
3.2 Aggiungere una feature derivataβ
Modificare AmesFeatureEngineer.transform in features.py. La feature finisce automaticamente nelle pipeline candidate al successivo training, senza altre modifiche (le inferenze sui gruppi numeric/ordinal/nominal sono dinamiche).
3.3 Cambiare il dataset di downloadβ
In config.py:
DATASET_URL: nuovo URL di download.DATASET_SHA256: hash atteso del nuovo file.DATASET_FILENAME: nome del file indata/raw/.
data.py fa giΓ la validazione SHA-256 automaticamente.
3.4 Sostituire scoring/metricβ
Modificare in tuning.py la stringa di scoring= (sklearn ne supporta 30+). Per metriche custom, definire un make_scorer.
4. Trade-off esplicitiβ
| Scelta | Pro | Contro |
|---|---|---|
Python 3.13 come target | Type hints moderni, performance | Alcune librerie ML potrebbero non avere wheel pronti |
xgboost come dipendenza | State-of-the-art tabular | ~50MB di binari, dipendenza C++ |
sklearn 1.6+ | Output naming uniforme post-FE | Esclude utenti su versioni vecchie |
| Notebook generati da script | Diff Git puliti, riproducibilitΓ | Editing meno comodo (no live cells) |
| Trasformazione log target | Migliora RΒ² ~3 pt | Predizione richiede expm1 esplicito |
| Stratified split su quintili | Metriche piΓΉ stabili | "Stratified regression" non Γ¨ standard |
min_frequency=2 su OneHot | Riduce dimensionalitΓ | Categorie rarissime perse |
RandomForest con max_features='sqrt' | Decorrelazione classica Breiman | Sub-ottimale su segnale lineare |
5. Testing strategyβ
Il progetto non implementa una test suite completa β Γ¨ un PW didattico, non production. Smoke test inclusi:
ames-train --quickesegue tutta la pipeline in <2 min con grid ridotte.- Esecuzione dei 4 notebook end-to-end via
nbconvert --execute. - Test di
predict_price()su 4 input (base, lusso, economica, parziale).
Per produzione si dovrebbero aggiungere:
- Unit test su
wrangling.fill_structural_missing(proprietΓ : tutti i NaN strutturali β 0/'None'). - Property-based test su
AmesFeatureEngineer(proprietΓ :TotalSF >= 0sempre). - Integration test sull'intera pipeline (dato un seed, RMSE deve restare entro tolleranza).
- Test di drift detection sui dati nuovi.