Teaching a Recommender Where People Want to Live: Geo-Embeddings
A housing recommender swapped raw latitude and longitude for learned H3 geo-embeddings in a two-tower model. How it was built and the A/B results it reported.
This article is published in English.
Sources: **Location Matters: Leveraging Multi-Resolution Geo-Embeddings for Housing Search**
A housing marketplace with millions of listings has a discovery problem. With that much inventory, showing each person the right home is the whole game, and for most people the deciding factor is where the home sits. This account follows how the recommender team at Latin America's largest housing platform, one that helps tenants, buyers and landlords rent and buy without the usual paperwork, rebuilt the way its model understands place. The work was presented at RecSys 2025 in Prague, and all figures below are the team's own reported numbers.
Why location deserves special care
A survey of nearly 800 users on the platform found that more than half ranked location as the single most important factor in a rental decision, ahead of price, size and amenities. That sounds obvious, yet location is among the hardest signals to get right in a recommender.
The rest of the story is about geo-aware embeddings: learned vectors that encode where a property is, and how similar places are to each other, in a way the recommender can use directly.
Where the first version stood
The recommender is a two-tower model, the architecture popularised by Google and YouTube for retrieval across very large catalogues. One tower reads information about a user and the other reads information about a house. Each projects into one shared embedding space, and a dot product there scores how good the match is. The platform's internal family of these models is called HUE, short for House User Embeddings.
The first version was deliberately simple and entirely tabular. Each attribute on the house side had a counterpart on the user side, calculated as a rolling statistic over the person's last fifteen interactions.
It's a tidy design: houses get described by their attributes, users by a digest of what they looked at, and the towers figure out how the two connect. Rent, floor area and bedroom count behaved nicely under this scheme, because the median rent across someone's last fifteen viewed listings tracks their budget fairly well. Location did not, and the reasons are the reason this project exists.
Why raw coordinates make poor features
A coordinate has no usable meaning. Latitude and longitude form a global grid with no connection to how people think about places, and a value like -22.97 tells the model nothing about Copacabana. To act on it, dense layers must carve every neighbourhood of every city out of a continuous plane, learning the boundaries from interaction data alone. That spends a lot of model capacity on something any local resident already knows.
Numeric closeness isn't functional similarity. A river, a motorway or a ridge can separate two spots only 500 metres apart, giving them different transit, prices and character. Two neighbourhoods ten kilometres apart might be near-perfect substitutes for a particular renter. Euclidean distance between coordinates is a weak stand-in for the question that matters: would this person be equally happy in both places?
Averaging coordinates wipes out the signal. This is the fatal one, and it hits the user tower. Imagine a renter in Rio de Janeiro comparing Copacabana and Barra da Tijuca, a common pairing. A median coordinate over their viewing history falls in the Tijuca massif, where almost nothing is for rent. Anyone weighing two or three distinct areas, which describes most people, gets squashed into a single point they'd never consider.
Before replacing the representation, the team tried to patch it by adding squared latitude and longitude, so dense layers could describe curved regions more easily. The improvement was small, and that smallness was the diagnosis. A feature that needs polynomial expansion before the model can use it points to a flawed representation, not a flawed model. So the team stopped handing the model coordinates and began teaching it geography.
Two structural difficulties
Any approach has to cope with two problems.
The first is sparsity. The number of homes in a micro-location is small and unevenly spread. Recommend strictly inside a tight boundary and inventory runs out quickly, while the model sees too few interactions per place to learn anything dependable.
The second is that functional similarity is written down nowhere. Nothing in a listing says one neighbourhood substitutes for another, or why: beach access, transit, safety, price level. That knowledge exists only in how people search, so the model must learn it from behaviour or go without.
The approach: a two-tower model over multi-resolution H3 cells
Instead of hand-crafting features, the team trained a two-tower network with a contrastive objective, so that location representations come from observed behaviour. A user tower encodes people, a location tower encodes places, and training draws together the vectors for users and places that show up together in real, high-intent interactions.
What matters most is the way a place gets described. Raw coordinates are out. Each property is instead indexed on Uber's H3 grid, which maps a latitude and longitude pair onto a hexagonal cell ID. Because H3 is hierarchical, any point lies in one cell per resolution, from coarse (around 36 km² per cell at resolution 6) to fine (about 0.105 km² at resolution 9). Each cell ID is a discrete token, so an embedding can be learned for it in the way word embeddings are learned in text models.
Cells at H3 resolutions 6, 7, 8 and 9 each pass through an embedding layer of their own, and a city-level embedding is added to capture the broad shape of urban areas. The location tower concatenates all of these and runs them through a pair of fully connected ReLU layers, ending in a 32-dimensional vector per location.
The user side is kept deliberately thin: a user-ID embedding followed by dense layers, so nearly all the learning happens in the location tower. It exists to nudge each location embedding toward the places a user really engaged with. After training it's thrown away, and what remains is the set of location vectors, which downstream models then reuse.
Why several resolutions at once? A single fine-grained cell gives precision but starves for data. A single coarse cell has data in abundance yet smears over differences that matter. Layering the resolutions lets the model lean on the surrounding region when one specific cell has seen few interactions, while preserving local detail wherever there's plenty of evidence. Think of it as a feature pyramid for space, and a direct remedy for sparsity.
Training signal. The loss is the InfoNCE objective from contrastive predictive coding. Rows are (user, location) pairs drawn from real high-intent interactions, meaning a booked visit or a submitted offer. No negatives are sampled by hand. Inside each batch, the locations belonging to other users act as negatives, which costs nothing and mirrors real demand.
There's one wrinkle. A place isn't like an arbitrary item ID, because many users can legitimately be positive for the same location at once. When an in-batch negative turns out to be a location the same user engaged with, the loss treats it as a false negative and masks it out, so the pair isn't pushed apart by mistake. Similarities carry a temperature, and cross-entropy is applied in both directions, from user to location and back.
The model is built in PyTorch Lightning with Xavier uniform initialisation, 32-dimensional embeddings, the Adam optimiser and a batch size of 512. Training data came to about 4 million high-intent events, generated by around one million distinct users. Only strong signals such as booking a visit or making an offer were kept, and noisy low-intent events like clicks were dropped.
How it was evaluated
The comparison covered three models: a matrix factorisation baseline (implicit-feedback ALS over only the finest H3 cell), a two-tower model using H3 resolution 9 alone, and the complete multi-resolution two-tower design. Two evaluation tracks ran side by side.
Intrinsic evaluation looks at embedding quality directly, independent of any downstream task, using two checks for collapse. The first is Information Abundance, defined in recent work on embedding collapse as the sum of the embedding matrix's singular values divided by the largest one. With 32 dimensions it runs from 1 (complete collapse) to 32 (every dimension contributing equally), so higher is better. The second is the spectrum of singular values of the normalised embedding covariance matrix, which shows how variance spreads across dimensions. A gentle, flat decay means the model is making full use of its capacity, while a sharp drop signals dimensional collapse, where embeddings degenerate into a low-rank subspace.
The reported spectrum is clear. The single-resolution model drops steeply at higher rank indices, a symptom of collapse. The multi-resolution model decays most flatly of the three, meaning its variance is spread evenly and it uses the embedding space fully.
Extrinsic evaluation asks whether better embeddings help users. It used a month of production logs (March 2025) from a "similar houses" module, an item-to-item recommender that shows homes resembling an anchor listing. For each anchor, the original recommendations were re-ranked by cosine similarity between the anchor's geo-embedding and each candidate's, and recommendations below a similarity threshold were then progressively pruned.
The headline business metric is the rent-flow rate, the proportion of displayed recommendations that ended in a strong-intent action: an in-person visit or a rental offer. Clicks are noisy, so rent flows are used instead because they reflect genuine interest. For each model and threshold, uplift was computed relative to that model's unfiltered production recommendations that had valid similarity scores, and the table gives the average over thresholds. Training ended in December 2024 and evaluation used March 2025 logs, so nothing from the evaluation period leaked into training.
Across the curve, as the recommendation list shrinks, the multi-resolution model comes out on top at the most aggressive cut-offs, whereas the learned approaches bunch together through the middle. The most telling comparison is against a plain radial-distance filter: the biggest gains came from learned similarity and not from favouring nearby homes.
Results
The platform runs two main business lines, Rent and Sale. The offline evaluation focuses on rental interactions, where high-intent volume is highest, while online impact was evaluated across both.
Both offline tracks got better with each step up in model sophistication. A caveat before the numbers: the rent-flow uplift is a simulation based on re-ranking historical production logs, and not a live experiment. Live A/B results are covered further down.
Going from matrix factorisation to the single-resolution two-tower model lifted Information Abundance by 158% and simulated rent-flow uplift by 84%. Multi-resolution H3 embeddings then added another 40% to Information Abundance, reaching 21.7, and took simulated uplift to 10.9%, nearly twice the previous step. In short, giving the model spatial context at several scales improved the embedding itself and its simulated effect on users.
To make the embeddings easier to grasp, the team built an internal tool that plots nearest neighbours on a map. Pick a dark anchor hexagon in Copacabana and a cluster of nearby cells lights up, the ones the model treats as functionally similar. It's a handy sanity check that learned geography agrees with how people picture a city.
Online A/B test on similar houses. At the time the paper was written, the experiment on the "similar houses" carousel was still in progress. It has since concluded, and the reported gains for that carousel were:
- Rent: a 4.18% rise in click-through, and a 3.38% rise in clicks that went on to book a visit.
- Sale: click-through rate up 5.53%.
The live result is what counts. Both the offline metrics and the A/B test point the same way: the geo-embeddings pay off.
Bringing GeoEmbeddings into HUE
The re-ranking study served as proof of concept. The real goal was to swap latitude and longitude out of the recommender itself, which became the production recommender's second iteration. The pretrained GeoEmbeddings sit in a shared location tower and stay frozen, so the recommender receives a steady geographic signal and doesn't have to relearn geography. The two towers use it in different ways.
The house tower change is a simple swap. Where it once received the listing's coordinates, it now receives the GeoEmbedding of the H3 cell containing the listing.
The user tower needs a deeper rethink, because medians can't simply be replaced with something equivalent. There's nothing meaningful to average. The tower is instead fed a sequence covering the cells from the person's last ten events, in order. Each entry records the event type, so a casual view and an offer count differently, and a recency encoding that lets the model learn how quickly a signal should fade.
The renter weighing Copacabana against Barra is no longer squashed into a spot in the hills between them. Both places are visible to the model now. It can tell which was just browsed, which produced a booked visit, and which came earlier.
Between them, these two changes gave the biggest lift the team had seen from altering a single feature. Measured by permutation importance, GeoEmbeddings became the most important feature in the second-iteration recommender, and the live A/B test recorded +1% visits booked in Rent and +3.3% offers submitted in Sale. Gains in platform-level conversion like these show how strongly representation quality feeds through to downstream results.
What comes next
Geography itself has more to give. The plans include explicit proximity signals such as distance to metro stations, schools and parks, and finer resolutions for representations that are more granular and more dynamic.
A more significant finding arrived almost by accident. The user-tower redesign was the first time HUE treated someone's history as an ordered series of events instead of a bundle of summary statistics, and the approach paid off. It prompted a natural question: if a sequence is the right way to describe where someone has been searching, wouldn't it also suit everything else they did?
Chasing that question produced SENNA, a sequential multimodal recommender whose entire user tower is a sequence of the houses a person interacted with, each house described in full, photos included. GeoEmbeddings come along as a frozen geographic input.
Location was always what users cared about most. Teaching a model to reason about where at several scales, instead of treating a coordinate as one more number, gave the team a way to act on that preference.
Background reading
The ideas rest on a handful of public sources: the YouTube two-tower retrieval paper by Covington, Adams and Sargin (2016), the sampling-bias-corrected two-tower work by Yi and colleagues (2019), the contrastive predictive coding paper by van den Oord, Li and Vinyals (2018), the embedding-collapse study by Guo and colleagues (2024), and the H3 geospatial index documentation at h3geo.org.