⚡ Consommation énergétique des bâtiments — Seattle (CatBoost multi-cible)

Projet de formation AI Engineer (OpenClassrooms) — P5 — Déployez un modèle de Machine Learning, réalisé par William Derue.

Deux régresseurs CatBoost entraînés sur le jeu de données ouvert de la ville de Seattle, qui prédisent la consommation d'énergie et les émissions de gaz à effet de serre d'un bâtiment à partir de ses 17 caractéristiques.


🎓 Projet de formation « AI Engineer »

Formation AI Engineer — OpenClassrooms (parcours)
Étape du projet P5 — Déployez un modèle de Machine Learning
Auteur William Derue
Client fictif Futurisys
Code source github.com/WillIsback/OC-P5_Deployez_un_modele_de_Machine_Learning
Démo en ligne Space Hugging Face — interface Gradio (johndoe / secret)
MLflow run 9c4a71a8c47e4f0fa4bbebf320e51ede

Ce dépôt ne contient que le modèle entraîné. Tout le reste du projet (service d'API FastAPI, base PostgreSQL, ingestion des données, suivi MLflow, supervision Grafana, interface Gradio, CI/CD et sécurité) vit dans le dépôt GitHub.


🎯 Contexte et problématique

Le Buildings Performance Alliance publie chaque année, pour chaque bâtiment non résidentiel de Seattle, la consommation d'énergie et les émissions constatées. Cette publication sert d'abord d'inventaire : elle identifie les bâtiments les plus énergivores, mais elle est produite avec un an ou deux de retard et ne permet pas encore d'anticiper la performance d'un bâtiment rénové ou d'un nouveau programme immobilier.

La question posée est donc : peut-on estimer la consommation et les émissions d'un bâtiment à partir de sa seule morphologie, avant que la mesure ne soit disponible ?

C'est un problème de régression tabulaire multi-sortie : une seule ligne de 17 features, deux cibles numériques, toutes deux fortement asymétriques (quelques ordres de grandeur entre le plus petit et le plus grand bâtiment).

Le parti pris du projet

Le modèle ne sert pas à vérifier une facture, mais à donner un ordre de grandeur avant mesure. C'est ce que dit la métrique de sélection : MedAPE (erreur absolue en pourcentage médiane), robuste aux valeurs extrêmes, plutôt que la MAE ou le R², qui sont toutes deux dominées par une poignée de très grands bâtiments.


📊 Données

Source : Building Energy Benchmarking Data — Seattle Office of Sustainability & Office of Energy & Environment, data.seattle.gov.

Année Rôle Lignes dans le périmètre
2016 Entraînement (split 80 / 20) 1 668
2017 → 2019 Bâtiments jamais vus (démonstration) 238 consultables

Le périmètre du modèle exclut le résidentiel (Multifamily*) et toute ligne comportant une feature obligatoire manquante. Les années 2017 à 2019 sont publiées dans un format différent de 2016 (renommage de colonnes, EPAPropertyType, regroupement des BuildingType) : elles sont réalignées sur le schéma 2016 par une couche d'harmonisation avant tout traitement.

Les 17 features

# Feature Type Rôle
1 BuildingType catégorielle grand type de bâtiment
2 PrimaryPropertyType catégorielle usage principal (EPA)
3 Neighborhood catégorielle quartier
4 Latitude / 5. Longitude numérique localisation
6 YearBuilt numérique année de construction
7 NumberofBuildings numérique nombre de bâtiments du site
8 NumberofFloors numérique étages
9 PropertyGFAParking numérique surface de parking
10 PropertyGFABuilding(s) numérique surface bâtie
11 LargestPropertyUseType catégorielle 1ᵉʳ usage
12 SecondLargestPropertyUseType + 13. sa surface mixte 2ᵉ usage
14 ThirdLargestPropertyUseType + 15. sa surface mixte 3ᵉ usage
16 Has_NaturalGas flag 0/1 NaturalGas(kBtu) > 0
17 Has_Steam flag 0/1 SteamUse(kBtu) > 0

Les 6 catégorielles manquantes sont remplacées par "UNKNOWN" ; les numériques restent NaN, ce que CatBoost traite nativement.

Prétraitement

Aucune transformation n'est appliquée aux features — pas de log, pas de ratio, pas d'imputation. Les deux seules opérations sont la normalisation du quartier et le passage de NumberofBuildings == 0 à 1. Les deux cibles en revanche sont entraînées sur log1p(y), et la prédiction est repassée en unités réelles par expm1 à l'inférence.


📈 Métriques

Évaluation sur le split test de l'année d'entraînement (310 bâtiments de 2016, jamais vus à l'entraînement), en unités réelles.

Cible Modèle R² MAE MedAE MedAPE
Énergie (kBtu/an) CatBoost 0,236 5 171 124 857 047 35,0 %
Énergie (kBtu/an) Kumo-Tabular (zero-shot) 0,447 4 710 104 883 031 35,1 %
Émissions (t CO2e/an) CatBoost 0,106 146 19,0 43,7 %
Émissions (t CO2e/an) Kumo-Tabular (zero-shot) 0,207 137 24,2 48,3 %

Lecture honnête de ces chiffres

Le modèle est modeste, et il faut le dire.

  • Le R² de 0,24 (énergie) et 0,11 (émissions) paraît faible. Il ne faut pas y lire un échec du modèle : le R² est calculé sur des valeurs réelles très asymétriques, quelques bâtiments très extrêmes écrivent à eux seuls la majeure partie de la variance. Le MedAPE — la métrique de sélection retenue par le projet — est de 35 % : l'erreur typique est d'un facteur ~1,5, ce qui est cohérent avec un usage de fourchette.
  • Sur les émissions, l'écart est plus net (43,7 %). Le signal est plus faible : les émissions dépendent surtout du mix énergétique et du combustible. Les features n'en donnent que la présence (gaz naturel, vapeur), pas la part.
  • Kumo-Tabular, le modèle de fondation tabulaire de NVIDIA utilisé sans entraînement, affiche un meilleur R² et une meilleure MAE sur les deux cibles, à MedAPE comparable sur l'énergie. Les expériences de la section suivante montrent que cet écart tient à un ou deux bâtiments extrêmes et n'est pas statistiquement significatif.

Ce que cela dit de l'usage

Une erreur médiane d'un tiers interdit toute automatisation de décision énergétique (déclencher des travaux, certifier une performance). L'usage réaliste est un ordre de grandeur : comparer deux scénarios, vérifier qu'un bâtiment ne sort pas de la norme, préremplir une étude de faisabilité — toujours avec un contrôle métrologique avant toute communication.


🔬 Comparaison avec Kumo-Tabular

Le projet compare ce CatBoost à nvidia/Kumo-Tabular, un modèle de fondation tabulaire qui prédit par in-context learning : il ne s'entraîne pas, il reçoit à chaque appel des exemples étiquetés (le contexte, ici exactement le jeu d'entraînement de CatBoost). Quatre expériences complètent les scores ci-dessus. Le détail est dans l'article « Prédire sans entraîner ».

Question Résultat
L'écart de R² est-il significatif ? Non. Bootstrap apparié (2 000 tirages) : écart de R² énergie entre −0,23 et +0,52 (IC 95 %). Un bâtiment porte 65 à 76 % de l'erreur quadratique ; sans le site industriel et le data center du test, CatBoost repasse devant (R² 0,58 contre 0,53).
Kumo est-il stable ? Son inférence est aléatoire : R² énergie de 0,42 à 0,46 selon la graine, contexte identique.
Que se passe-t-il avec plus ou moins de données (100 → 4 700 lignes) ? Kumo garde le meilleur R², mais CatBoost a la meilleure erreur médiane avec peu de données (émissions à 100 lignes : 55 % contre 71 %). Kumo plafonne dès 1 236 lignes.
Combien coûte une prédiction ? CPU, 4 threads : 0,8 ms pour CatBoost, ~25 s pour Kumo, quel que soit le nombre de lignes prédites dans l'appel (1 000 lignes : 42,5 s). La durée croît linéairement avec la taille du contexte.
Sur quoi s'appuient les modèles ? Importance par permutation : surface bâtie puis usage pour les deux ; CatBoost lit PrimaryPropertyType, Kumo LargestPropertyUseType. Sur les émissions, Has_NaturalGas arrive juste après la surface.

Pour un ordre de grandeur sur un bâtiment typique, ce qui est l'usage visé, ce CatBoost reste le modèle servi : il est au moins aussi précis en MedAPE, et environ 30 000 fois plus rapide à l'unité.


🚀 Utilisation

import json
import numpy as np
import pandas as pd
from catboost import CatBoostRegressor
from huggingface_hub import hf_hub_download

repo = "Willisback/seattle-energy-catboost"
config = json.load(open(hf_hub_download(repo, "config.json", repo_type="model")))

FEATURES = config["feature_columns"]
CATS = config["cat_features"]

# Une ligne du jeu de données, au format du CSV Seattle 2016.
row = pd.DataFrame([{
    "BuildingType": "SPS-District K-12",
    "PrimaryPropertyType": "K-12 School",
    "Neighborhood": "SOUTHEAST",
    "Latitude": 47.54576,
    "Longitude": -122.26853,
    "YearBuilt": 1961,
    "NumberofBuildings": 1,
    "NumberofFloors": 2,
    "PropertyGFAParking": 0,
    "PropertyGFABuilding(s)": 56228,
    "LargestPropertyUseType": "K-12 School",
    "SecondLargestPropertyUseType": "UNKNOWN",
    "SecondLargestPropertyUseTypeGFA": np.nan,
    "ThirdLargestPropertyUseType": "UNKNOWN",
    "ThirdLargestPropertyUseTypeGFA": np.nan,
    "Has_NaturalGas": 1,
    "Has_Steam": 0,
}])

# Catégorielles : aucune valeur manquante ne doit atteindre CatBoost.
for col in CATS:
    row[col] = row[col].astype("string").fillna("UNKNOWN").astype(str)
row = row[FEATURES]

energy = CatBoostRegressor()
energy.load_model(hf_hub_download(repo, "data/energy.cbm", repo_type="model"))

print(np.expm1(energy.predict(row))[0])
# 3088219.812954494  kBtu/an

⚠️ L'ordre des colonnes est significatif. Les .cbm embarquent leur propre feature_names_, mais il doit correspondre à FEATURES ci-dessus. La transformation expm1 est obligatoire : le modèle prédit log1p(y).


📁 Contenu du dépôt

Fichier Rôle
config.json contrat d'inférence : features, catégorielles, hyperparamètres, prétraitement
data/energy.cbm régresseur énergie (299 arbres)
data/emissions.cbm régresseur émissions (813 arbres)
data/scores.json métriques de validation, par cible et par modèle
data/scores.csv mêmes métriques, à plat
data/version.json version servie et mlflow_run_id

⚖️ Limites connues

  • Un seul climat, une seule ville, une seule année d'entraînement (Seattle, 2016). Aucune généralisation à d'autres climates n'a été testée.
  • Pas d'incertitude prédictive : le modèle renvoie un point, sans intervalle. Sur des données aussi asymétriques, un intervalle serait plus utile qu'un point.
  • Pas d'explicabilité par building au-delà des importances de features globales : la surface bâtie et l'usage du bâtiment dominent, le raccordement au gaz pèse sur les émissions, le quartier presque pas.
  • La moitié du parc n'est pas couverte : 1 668 des 3 376 lignes de 2016 seulement entrent dans le périmètre (hors résidentiel, features obligatoires complètes).

📄 Licence et provenance

Code et modèle : MIT. Données d'origine : Seattle Building Energy Benchmarking Data, open data sous CC BY 4.0.

Downloads last month
21
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support