Every property portal has that number: open any listing and somewhere near the photos is an estimated value, computed by nobody in particular. For a while, at a property listing company in Singapore, that number was my job. I helped revamp the automated valuation model — the AVM — that priced homes across the country.
An AVM sounds like it should be one big model. Ours ended up being a portfolio, and understanding why taught me more about applied machine learning than building it did.
One model can't price Singapore
Singapore looks like one property market and behaves like three. Public HDB flats — where most of the country lives — trade constantly, in standardised blocks, with prices the government publishes openly. Private condos trade less often and vary wildly by project, facing, and floor. Landed houses barely trade at all: a good-class bungalow might change hands a handful of times in a decade, and no two are alike.
That's really a statement about data density. A flat in Toa Payoh has thousands of comparable transactions behind it; a bungalow off Holland Road might have five. Any single model trained across all of that will be mediocre everywhere and embarrassing at the edges. So the engine was split by segment — HDB resale, private non-landed resale and rental, landed — each with its own pipeline, features, and failure modes.
The fallback is not the budget version
Within a segment, the same problem repeats at smaller scale: some condo projects have deep transaction history, others have almost none. The revamp leaned into a hybrid design.
Where history was dense, a project got its own gradient-boosted model — trained on its transactions, tuned automatically, aware of floor, size, and timing. Where history was thin, the engine fell back to a comparables search: find recent transactions in the same planning area for units of similar size and age, adjust for floor, take the median price per square foot, and correct everything to today using a price index so that a two-year-old transaction could still speak.
I started out thinking of the fallback as the lesser path — the thing you do when you can't do machine learning. I ended up thinking the opposite. That comparables logic is exactly what a human valuer does when they price a house; we had just encoded it and made it run a few hundred thousand times a night. In the thin-data tail where models are least trustworthy, the system quietly switches to the method that is most defensible. The fallback carried the hardest cases.
The number has to show up
The other half of the revamp had nothing to do with modelling. A valuation engine that lives in a notebook is a research project; this one had to put a number on every listing page, instantly, and keep those numbers fresh as new transactions landed. That meant a central serving API, scheduled refresh pipelines that repriced whole segments overnight, and studies on accuracy and concurrency before anything shipped. We measured ourselves on absolute percentage error distributions per segment — not "is the model good" but "how wrong are we, how often, and for which kinds of homes".
Most of my time went into that plumbing, and none of it was glamorous. But it's what turned a model into a product.
If I had to compress the whole experience into one sentence: a city's worth of homes doesn't want one clever model — it wants a portfolio of honest ones, a fallback that thinks like a valuer, and pipes that never clog.