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
- Open and run the
train.ipynbnotebook - 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 builtnumber_of_bedrooms(int): Number of bedroomsindoor_area(float): Indoor area in square metersoutdoor_area(float): Outdoor area in square metersenergy_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
descriptionandsingle_family_homecolumns - Ordinal encoding for
energy_label(G to A++++) βenergy_label_encoded - Final model uses 6 features:
year_builtnumber_of_bedroomsindoor_areaoutdoor_areaproperty_valueenergy_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.tomlorrequirements.txtfor 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
- Email: tomer.gabay@woonstadrotterdam.nl
- Organization: Woonstad Rotterdam
Limitations
- Geographic Scope: Trained on Rotterdam data, may not generalize to other regions
- Temporal Limitations:
- Truth labels are based on Dutch law as of April 22, 2025
- Based on historical data, may not reflect future regulatory changes
- Dwelling Type: Only trained on self-contained dwellings; will not work for non-self-contained dwellings
- 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
- Data Quality: Performance depends on quality and completeness of input features
- 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.
Dataset used to train woonstadrotterdam/woningwaardering-ml
Space using woonstadrotterdam/woningwaardering-ml 1
Evaluation results
- Mean Absolute Error on woonstadrotterdam/woningwaarderingentest set self-reported2.970
- Mean Absolute Percentage Error on woonstadrotterdam/woningwaarderingentest set self-reported1.910