Woningwaardering ML

A gradient boosting regression model for predicting Dutch housing valuation points (woningwaardering points) based on property characteristics.

[!INFO] This project is done for learning and educational purposes. It is not intended to be used for real-world applications.

Model Details

Model Description

This is a gradient boosting regression model that predicts Dutch housing valuation points (woningwaardering points) based on property characteristics. The model uses scikit-learn's GradientBoostingRegressor with hyperparameter tuning.

  • Developed by: Tomer Gabay (Woonstad Rotterdam)
  • Model type: Gradient Boosting Regressor
  • Language: Python
  • License: MIT

Intended Use

Primary Use Cases

  • Researching the impact of housing characteristics on woningwaardering points
  • Predicting housing valuation points for properties in the Netherlands
  • Real estate valuation assistance
  • Housing market analysis

Out-of-Scope Use Cases

  • Legal or official property valuation (this is a predictive model, not an official assessment)
  • Properties outside the Netherlands
  • Properties with characteristics significantly different from the training data

Quick Start

Installation

Using uv (recommended)

# Install uv if you haven't already
curl -LsSf https://astral.sh/uv/install.sh | sh

# Install dependencies
uv pip install -e .

Using pip

# Install as package (recommended)
pip install -e .

# Or just install dependencies
pip install -r requirements.txt

Training the Model

  1. Open and run the train.ipynb notebook
  2. The notebook includes:
    • Data loading from Hugging Face
    • Data preprocessing and feature engineering
    • Model training with hyperparameter tuning (RandomizedSearchCV with 5-fold cross-validation)
    • Model evaluation and metrics
    • Feature importance analysis
    • Visualizations
    • Model saving

Using a Trained Model

Option 1: Using the High-Level API (Recommended)

from woningwaardering_ml import WoningwaarderingPredictor
import pandas as pd

# Initialize predictor (loads model and preprocessing components)
predictor = WoningwaarderingPredictor()

# Prepare your data
new_property = pd.DataFrame({
    'year_built': [1990],
    'number_of_rooms': [5],
    'number_of_bedrooms': [3],
    'indoor_area': [120],
    'outdoor_area': [50],
    'energy_label': ['B'],
    'property_value': [350000]
})

# Make prediction
predictions = predictor.predict(new_property)
print(f"Predicted woningwaardering points: {predictions.iloc[0]}")

# Batch prediction
multiple_properties = pd.DataFrame({
    'year_built': [1990, 2010, 1985],
    'number_of_rooms': [5, 4, 6],
    'number_of_bedrooms': [3, 2, 4],
    'indoor_area': [120, 90, 150],
    'outdoor_area': [50, 30, 80],
    'energy_label': ['B', 'A', 'C'],
    'property_value': [350000, 280000, 420000]
})

batch_predictions = predictor.predict(multiple_properties)
print(batch_predictions)

Option 2: Using Lower-Level Functions

from woningwaardering_ml import load_model, load_preprocessing_components, preprocess_data
import pandas as pd

# Load model and preprocessing components
model = load_model('woningwaardering_model.pkl')
energy_label_encoder, feature_cols = load_preprocessing_components()

# Prepare your data
new_property = pd.DataFrame({
    'year_built': [1990],
    'number_of_rooms': [5],
    'number_of_bedrooms': [3],
    'indoor_area': [120],
    'outdoor_area': [50],
    'energy_label': ['B'],
    'property_value': [350000]
})

# Preprocess data
new_property_processed, _ = preprocess_data(
    new_property, 
    energy_label_encoder=energy_label_encoder
)

# Select features in the same order as training
X_new = new_property_processed[feature_cols]

# Make prediction
prediction = model.predict(X_new)
print(f"Predicted woningwaardering points: {prediction[0]}")

Option 3: Using Command Line Interface

# Interactive mode
python main.py

# With JSON input
python main.py --property '{"year_built":1990,"number_of_rooms":5,"number_of_bedrooms":3,"indoor_area":120,"outdoor_area":50,"energy_label":"B","property_value":350000}'

# With input file
python main.py --input properties.json --output predictions.csv

Required Input Features

The model requires the following features:

  • year_built (int): Year the property was built
  • number_of_bedrooms (int): Number of bedrooms
  • indoor_area (float): Indoor area in square meters
  • outdoor_area (float): Outdoor area in square meters
  • energy_label (str): Energy label (G, F, E, D, C, B, A, A+, A++, A+++, A++++)
  • property_value (float): Property value in euros

Project Structure

woningwaardering-ml/
β”œβ”€β”€ woningwaardering_ml/        # Python package
β”‚   β”œβ”€β”€ __init__.py             # Package initialization
β”‚   β”œβ”€β”€ preprocessing.py        # Data preprocessing utilities
β”‚   β”œβ”€β”€ model.py                # Model loading utilities
β”‚   └── inference.py            # High-level inference API
β”œβ”€β”€ train.ipynb                 # Main training and evaluation notebook
β”œβ”€β”€ main.py                     # CLI entry point for inference
β”œβ”€β”€ push_to_hub.py              # Script to push model to Hugging Face Hub
β”œβ”€β”€ pyproject.toml              # Project dependencies (uv)
β”œβ”€β”€ requirements.txt            # Alternative requirements file (pip)
β”œβ”€β”€ PUBLISHING_GUIDE.md         # Guide for publishing to Hugging Face
β”œβ”€β”€ README.md                   # This file
β”œβ”€β”€ LICENSE                     # MIT License
β”œβ”€β”€ .gitignore                  # Git ignore rules
β”‚
β”œβ”€β”€ Generated files (after training):
β”œβ”€β”€ woningwaardering_model.pkl  # Trained model
β”œβ”€β”€ energy_label_encoder.pkl    # Energy label encoder
β”œβ”€β”€ feature_columns.json        # Feature column names (order matters)
└── model_metadata.json         # Model metadata and hyperparameters

Training Data

Dataset

  • Name: woonstadrotterdam/woningwaarderingen
  • Source: Hugging Face Datasets
  • Splits: Train (80%), Validation (10%), Test (10%)
  • Total samples: 16,000
  • Training samples: 12,800
  • Truth Label Date: Truth labels are based on Dutch law as of April 22, 2025

For detailed dataset information, see the dataset card.

Data Preprocessing

  • Removed description and single_family_home columns
  • Ordinal encoding for energy_label (G to A++++) β†’ energy_label_encoded
  • Final model uses 6 features:
    • year_built
    • number_of_bedrooms
    • indoor_area
    • outdoor_area
    • property_value
    • energy_label_encoded

Dataset Curation

The dataset is based on data from houses of the social housing corporation Woonstad Rotterdam. The amount of woningwaardering points for each house has been calculated using the woningwaardering package. To avoid bias from over-represented dwelling archetypes, observations whose feature set and target value were exact duplicates were removed.

Performance

Metrics

  • Test MAE: 2.97 points
  • Test MAPE: 1.91%

Evaluation Results

The model was evaluated on a held-out test set of 1,600 samples.

Model Architecture

Hyperparameters

  • Algorithm: GradientBoostingRegressor
  • Hyperparameter Tuning: RandomizedSearchCV with 5-fold cross-validation
  • Reproducibility: Random seed = 42 (set for NumPy, Python random, and all scikit-learn models)
  • Features: 6 features (year_built, number_of_bedrooms, indoor_area, outdoor_area, property_value, energy_label_encoded)
  • Best parameters found:
    • n_estimators: 1500
    • max_depth: 9
    • learning_rate: 0.01
    • subsample: 0.6
    • min_samples_split: 5
    • min_samples_leaf: 1

Development

Requirements

  • Python >= 3.13
  • See pyproject.toml or requirements.txt for dependencies

Reproducibility

The model uses a fixed random seed (42) for reproducibility. This is set for:

  • NumPy random number generation
  • Python's random module
  • All scikit-learn models

Running Tests

Currently, the main training and evaluation is done in the train.ipynb notebook. The notebook includes:

  • Train/validation/test split evaluation
  • Cross-validation during hyperparameter tuning
  • Feature importance analysis

Or use the notebook cell to push directly.

Citation

If you use this model, please cite:

@software{woningwaardering_ml,
  title = {Woningwaardering ML Model},
  author = {Gabay, Tomer},
  organization = {Woonstad Rotterdam},
  year = {2025},
  url = {https://huggingface.co/woonstadrotterdam/woningwaardering-ml}
}

License

MIT

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

Contact

Limitations

  1. Geographic Scope: Trained on Rotterdam data, may not generalize to other regions
  2. Temporal Limitations:
    • Truth labels are based on Dutch law as of April 22, 2025
    • Based on historical data, may not reflect future regulatory changes
  3. Dwelling Type: Only trained on self-contained dwellings; will not work for non-self-contained dwellings
  4. Feature Coverage: Does not account for all factors influencing housing valuation:
    • Shared spaces, parking spots, and extra kitchen amenities are NOT accounted for in truth labels
    • Storage spaces and outdoor areas are underrepresented in the dataset
  5. Data Quality: Performance depends on quality and completeness of input features
  6. Dataset Bias: The dataset is biased towards social housing dwellings and may have less representation of higher-end dwellings

For more information about the dataset, see the dataset card.

Downloads last month

-

Downloads are not tracked for this model. How to track
Inference Providers NEW
This model isn't deployed by any Inference Provider. πŸ™‹ Ask for provider support

Dataset used to train woonstadrotterdam/woningwaardering-ml

Space using woonstadrotterdam/woningwaardering-ml 1

Evaluation results