Skip to content

About

End-to-end supervised regression on 9,535 NYC buildings. IQR outlier removal, log-transform, collinearity pruning → 5-model CV → two-stage hyperparameter search → GradientBoosting MAE 8.6 R²=0.82. Feature importance + surrogate tree + LIME explainability.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

NYC Building Energy Star Score Predictor

Predicting urban energy efficiency from tabular data — a supervised learning pipeline applied to 9,535 records identified in this repository as NYC Local Law 84 Energy Benchmarking data. The result is an interpretable gradient-boosting model for educational analysis, not a production system.

Author: Sasi Sundhar — sasisundhar2211@gmail.com
Dataset: NYC Local Law 84 Energy Benchmarking, 2016
Best Result: MAE 8.6 pts · R² 0.824 · 65% improvement over baseline


Why This Problem Matters

Buildings account for roughly 70% of New York City's greenhouse gas emissions. NYC Local Law 84 mandates that every building over 25,000 sq ft publicly disclose its annual energy consumption — one of the most ambitious urban transparency policies in the world.

The disclosed data is messy, high-dimensional, and deeply non-linear. No single equation captures the relationship between a building's age, construction type, occupancy pattern, fuel mix, and its efficiency score. That is precisely what makes it a compelling machine learning problem.

This project turns that raw disclosure data into a regression model that predicts a building's ENERGY STAR Score (1–100) from its physical and operational features — and then goes further: it explains why the model made each prediction, making the output actionable for building managers, policymakers, and sustainability auditors, not just data scientists.


What Makes This Project Different

Most ML tutorials stop at accuracy. This one doesn't.

Statistical rigor first. Before any model is trained, the data is interrogated — outliers are removed using IQR fencing, skewed distributions are corrected with log transforms, and multicollinear features are pruned with Pearson correlation analysis. The model learns from signal, not noise.

Systematic model selection. Five algorithms — Linear Regression, K-Nearest Neighbors, Support Vector Regression, Random Forest, and Gradient Boosting — are evaluated head-to-head using shuffled 5-fold KFold cross-validation with random_state=42.

Two-stage hyperparameter optimization. RandomizedSearchCV explores 40 random configurations across a wide search space. GridSearchCV then refines around the best candidate. This mimics how practitioners actually tune models at scale, not how tutorials present it.

Three lenses of interpretability. Global feature importance shows which variables drive the model overall. A depth-3 surrogate decision tree distills the model into human-readable rules. LIME generates local explanations for individual buildings — including ones the model got wrong — so failures are as informative as successes.

The result is a model that predicts energy efficiency within 8.6 ENERGY STAR points on held-out data it has never seen, on a scale of 1–100, using only features available before an energy audit.


The Machine Learning Pipeline

The project is split into three notebooks that run in sequence. Each one reads from the data/ folder and writes its outputs back there.

Raw data → Part 1 (clean + engineer) → Part 2 (train + tune) → Part 3 (explain)

Part 1 — Data Cleaning & Feature Engineering

Takes the raw CSV and transforms it into model-ready features.

What it does:

  • Outlier removal — removes buildings with extreme EUI or score values using the IQR (interquartile range) fence method. Dropped ~282 rows (~3%).
  • Missing value imputation — fills in gaps with the median value per column using sklearn.impute.SimpleImputer.
  • Feature engineering — creates new derived features:
    • building_age = 2024 − year built
    • eui_ratio = source EUI ÷ site EUI
    • elec_intensity and gas_intensity = fuel use per square foot
    • log_floor_area, log_ghg = log-scaled versions of skewed features
  • Log transformation — applied to any feature with absolute skew > 0.75 to make distributions more normal and help linear models.
  • One-hot encoding — converts categorical columns (borough, property_type) into binary 0/1 columns so algorithms can use them.
  • Collinearity removal — drops features with Pearson correlation |r| > 0.90 to reduce redundancy.
  • Train/test split — 70% training (6,477 records), 30% testing (2,776 records), random_state=42.

Output: 43 engineered features saved as training_features.csv / testing_features.csv.


Part 2 — Model Comparison & Hyperparameter Tuning

Trains five different algorithms and picks the best one.

Baseline: Always predict the median score from training data → MAE = 24.8 pts. This is the floor we need to beat.

5-Fold Cross-Validation across all five models:

Model CV MAE (mean ± std)
Linear Regression 12.1 ± 1.2
K-Nearest Neighbors (k=10) 10.8 ± 0.9
Support Vector Regression (RBF) 9.6 ± 0.8
Random Forest (100 trees) 9.0 ± 0.7
Gradient Boosting (200 trees) 8.9 ± 0.7

Cross-validation trains and evaluates each model 5 times on different data splits to get a reliable estimate of real-world performance — not just one lucky split.

Tuning the winner — Gradient Boosting:

  1. RandomizedSearchCV (40 random combinations) to explore the hyperparameter space: tree depth, learning rate, number of estimators, subsampling ratio, max features.
  2. GridSearchCV (narrow grid around the best point) to fine-tune.

Best hyperparameters found:

GradientBoostingRegressor(
    n_estimators=200,
    learning_rate=0.05,
    max_depth=5,
    max_features=0.7,
    min_samples_leaf=2,
    subsample=0.7,
    random_state=42,
)

Final hold-out results (2,776 unseen records):

Model MAE RMSE R²
Median Baseline 24.8 pts — —
Linear Regression 12.1 pts 17.3 0.78
K-Nearest Neighbors 10.8 pts 15.2 0.81
SVR 9.6 pts 13.5 0.82
Random Forest 9.0 pts 12.8 0.823
Gradient Boosting (tuned) 8.6 pts 12.24 0.824

The tuned model is correct within 8.6 ENERGY STAR points on average — a 65% improvement over the naive baseline.


Part 3 — Model Interpretation & Explainability

Answers the question: why did the model predict what it predicted?

Three complementary techniques are used:

1. Global Feature Importance The built-in feature_importances_ from the gradient boosting model shows which features the model relied on most across all predictions.

  • Source EUI (energy use intensity, source) — ~52% of total importance
  • Site EUI (energy use intensity, site) — ~24% of total importance
  • Property type, borough, building age, fuel intensities — remaining ~24%

Only ~13–15 features out of 43 account for 95% of the model's decision-making.

2. Surrogate Decision Tree (Depth-3) A simple, human-readable decision tree is trained to mimic the gradient boosting model's predictions. It has higher error (MAE ~10–11 pts) but gives interpretable rules like:

"If Source EUI > X AND property type is not Office → predict low score"

This is useful for explaining the model to non-technical stakeholders.

3. LIME (Local Interpretable Model-Agnostic Explanations) LIME explains individual building predictions by building a small local linear model around each prediction. It shows which features pushed the score up or down for that specific building.

Three cases are analyzed:

  • A well-predicted building (low error)
  • An over-predicted building (model guessed too high)
  • An under-predicted building (model guessed too low)

Key Findings

  • Source EUI is the dominant signal. How much total energy (including generation losses) a building uses per square foot explains more than half of its score variance.
  • Office buildings score higher. On average ~6 points above warehouses and retail.
  • Manhattan buildings score higher. Approximately 6 points above the city-wide average.
  • Ensemble models beat linear models on this dataset because the relationship between features and score is non-linear — buildings behave differently by type and usage pattern.
  • Gradient Boosting outperformed Random Forest because it builds trees sequentially, each one correcting the previous model's mistakes (boosting), rather than averaging independent trees (bagging).

Project Structure

├── Machine Learning Project Part 1.ipynb   ← start here
├── Machine Learning Project Part 2.ipynb
├── Machine Learning Project Part 3.ipynb
├── auto_ml/
│   └── tpot_exported_pipeline.py           # TPOT-style exported pipeline (MaxAbsScaler + GBM)
├── data/
│   ├── raw/buildings.csv                   ← downloaded by ingest_real_data.py
│   ├── cleaned_data.csv                    # 9,253 records, 44 columns
│   ├── training_features.csv               # 6,477 records × 43 features
│   ├── training_labels.csv
│   ├── testing_features.csv                # 2,776 records × 43 features
│   ├── testing_labels.csv
│   ├── no_score.csv                        # 954 buildings excluded (no Energy Star Score)
│   └── final_model.pkl                     # serialized tuned GradientBoostingRegressor
├── images/                                 ← all 12 charts generated by the notebooks
├── deprecated/
│   └── Exploratory_Work.ipynb
└── scripts/
    ├── ingest_real_data.py                 # download real NYC 2016 data via Kaggle
    ├── generate_mock_data.py               # synthetic fallback (1,500 buildings)
    ├── 01_data_cleaning_eda.py
    ├── 02_model_comparison_tuning.py
    └── 03_model_interpretation.py

Setup & Quickstart

# Install dependencies
pip install -r requirements.txt kagglehub openpyxl

# Download real NYC 2016 data from Kaggle (no account required for public datasets)
python scripts/ingest_real_data.py

# OR generate a synthetic dataset instead
python scripts/generate_mock_data.py

# Open the notebooks
jupyter notebook

Open notebooks in order: Part 1 → Part 2 → Part 3.

Each notebook is self-contained. It reads from data/, does its work, and writes outputs back to data/ and images/.


Dependencies

pandas >= 2.0          # data manipulation
numpy >= 1.24          # numerical operations
scikit-learn >= 1.3    # ML algorithms, preprocessing, evaluation
matplotlib >= 3.7      # plotting
seaborn >= 0.12        # statistical visualizations
scipy >= 1.10          # statistical tests
lime >= 0.2.0.1        # local model explanations
jupyter >= 1.0         # notebook environment

Concepts Covered

This project is a practical walkthrough of the full supervised ML workflow:

Concept Where
Exploratory data analysis (EDA) Part 1
Outlier detection (IQR method) Part 1
Missing value imputation (median) Part 1
Feature engineering Part 1
Log transformation for skewed features Part 1
One-hot encoding Part 1
Multicollinearity detection and removal Part 1
Train/test split Part 1
Cross-validation (k-fold) Part 2
Regression baseline (dummy regressor) Part 2
Linear Regression Part 2
K-Nearest Neighbors Regression Part 2
Support Vector Regression Part 2
Random Forest (bagging ensemble) Part 2
Gradient Boosting (boosting ensemble) Part 2
Hyperparameter tuning (RandomizedSearchCV + GridSearchCV) Part 2
Model evaluation (MAE, RMSE, R²) Part 2
Feature importance (tree-based) Part 3
Surrogate / proxy model (decision tree) Part 3
LIME (local model-agnostic explanations) Part 3
Model serialization (pickle) Part 2

Dataset

NYC Local Law 84 Energy Benchmarking, 2016
Kaggle slug: claytonmiller/new-york-city-buildings-energy-consumption-survey

  • ~13,000 buildings originally reported
  • ~9,535 buildings with valid numeric features
  • ~9,254 kept after outlier removal
  • ~954 buildings excluded (missing ENERGY STAR Score — stored in data/no_score.csv)
  • Target variable: ENERGY STAR Score (integer 1–100, higher = more energy efficient)

Key raw features: gross floor area, year built, occupancy %, site EUI, source EUI, electricity use (kBtu), natural gas use (kBtu), steam use (kBtu), total GHG emissions, borough, property type.


License

MIT

About

End-to-end supervised regression on 9,535 NYC buildings. IQR outlier removal, log-transform, collinearity pruning → 5-model CV → two-stage hyperparameter search → GradientBoosting MAE 8.6 R²=0.82. Feature importance + surrogate tree + LIME explainability.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages