
Cross-City Building Age Classification
Predict the majority construction-age class of buildings inside 30 m Landsat pixels from decades of spectral reflectance, trained on Madrid and transferred to Amsterdam. Class-conditional CORAL lifts zero-shot macro-F1 from 0.36 to 0.65 with no Amsterdam labels.
Hack4Dev Data Science Hackathon. Domain adaptation under a real city shift: feature engineering from satellite time series, class-balanced Random Forests, CORAL alignment, few-shot transfer, and a spatial adjacency audit that stress-tested whether our own evaluation was inflating few-shot gains.
The task was to estimate which of four construction-age groups dominates a 30 m satellite patch, using roughly forty years of Landsat spectral reflectance. Models were trained primarily on Madrid and had to generalise to Amsterdam (a city never seen in training), creating a classic domain-adaptation problem scored on macro-F1.
We engineered about 108 per-pixel features: multi-period band statistics, spectral indices, the size and timing of major spectral change, and neighbourhood feature averages. Stage 1 was a class-balanced Random Forest (500 trees). For zero-shot transfer we used class-conditional CORAL, aligning each Madrid age group to the covariance of Amsterdam pixels the model assigned to that group over two rounds, with no Amsterdam labels. With a few local labels we added budget-scaled feature whitening, a small local forest, probability blending with Stage 1, and inverse-distance neighbour smoothing.
Madrid in-city 5x5 CV macro-F1 reached 0.664 ± 0.004. Raw Amsterdam zero-shot scored 0.358; pooled CORAL 0.578; class-conditional CORAL 0.651, roughly 0.36 to 0.65 macro-F1 with zero Amsterdam labels. Few-shot rose from 0.662 ± 0.003 at 5 labels/class to 0.737 ± 0.005 at 200.
We also audited spatial adjacency in the few-shot protocol. Under the organisers' random split, roughly 80% of support pixels had an immediate map neighbour in the query set; a spatial-block re-run showed that about half the few-shot lift at higher budgets was proximity rather than labels. The zero-shot result uses no labels, has no adjacency issue, and remains the strongest transferable number. Treating the few-shot curve as an upper bound was a deliberate evaluation stress test, not a footnote.
Project goal
Build a Madrid to Amsterdam building-age transfer pipeline that works with few or zero Amsterdam labels, and honestly measure how much of any few-shot gain is real skill versus spatial proximity in the evaluation design.
Screenshots
Cross-city feature spaceKey features
- 108 engineered features from Landsat time series (spectral stats, indices, change timing, neighbourhood averages)
- Class-balanced Random Forest (500 trees) as Stage-1 Madrid model
- Pooled and class-conditional CORAL for label-free domain alignment
- Budget-scaled feature whitening, local few-shot modelling, and probability blending
- Inverse-distance spatial neighbour smoothing (prediction-only)
- Madrid 5×5 CV ceiling: 0.664 ± 0.004 macro-F1
- Zero-shot Amsterdam: 0.358 → 0.651 macro-F1 via class-conditional CORAL
- Spatial adjacency audit showing ~half of higher-budget few-shot lift was proximity
Project details
Event
Hack4Dev Data Science Hackathon
Type
Domain Adaptation / Remote Sensing
Zero-shot
0.36 → 0.65 macro-F1
Madrid CV
0.664 ± 0.004
Features
108 engineered
Few-shot (200)
0.737 ± 0.005
Technologies
Links