Passa al contenuto principale

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/score standard 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​

  1. Implementare la pipeline in models.py (es. lightgbm_pipeline).
  2. Aggiungerla al dizionario in get_all_pipelines.
  3. Definire la grid in config.py (LIGHTGBM_PARAM_GRID).
  4. 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 in data/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​

SceltaProContro
Python 3.13 come targetType hints moderni, performanceAlcune librerie ML potrebbero non avere wheel pronti
xgboost come dipendenzaState-of-the-art tabular~50MB di binari, dipendenza C++
sklearn 1.6+Output naming uniforme post-FEEsclude utenti su versioni vecchie
Notebook generati da scriptDiff Git puliti, riproducibilitΓ Editing meno comodo (no live cells)
Trasformazione log targetMigliora RΒ² ~3 ptPredizione richiede expm1 esplicito
Stratified split su quintiliMetriche piΓΉ stabili"Stratified regression" non Γ¨ standard
min_frequency=2 su OneHotRiduce dimensionalitΓ Categorie rarissime perse
RandomForest con max_features='sqrt'Decorrelazione classica BreimanSub-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 --quick esegue 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 >= 0 sempre).
  • Integration test sull'intera pipeline (dato un seed, RMSE deve restare entro tolleranza).
  • Test di drift detection sui dati nuovi.