Instructions to use mki0809/geosearch-reranker with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- sentence-transformers
How to use mki0809/geosearch-reranker with sentence-transformers:
from sentence_transformers import CrossEncoder model = CrossEncoder("mki0809/geosearch-reranker") query = "Which planet is known as the Red Planet?" passages = [ "Venus is often called Earth's twin because of its similar size and proximity.", "Mars, known for its reddish appearance, is often referred to as the Red Planet.", "Jupiter, the largest planet in our solar system, has a prominent red spot.", "Saturn, famous for its rings, is sometimes mistaken for the Red Planet." ] scores = model.predict([(query, passage) for passage in passages]) print(scores) - Notebooks
- Google Colab
- Kaggle
geosearch-reranker
Cross-encoder reranker fine-tuned from cross-encoder/mmarco-mMiniLMv2-L12-H384-v1, the last
stage of a multilingual toponym search pipeline:
text
-> GLiNER NER
-> char-n-gram BM25 retrieval
-> cross-encoder reranker (this model)
-> ranked GeoNames places
It reorders a fixed candidate set; it does not choose one. Retrieval ends by ranking on BM25 score with population as the tiebreak and cutting to top-k, and the model only permutes those survivors.
Results
| system | RR | P@1 | R@5 | R@10 | R@25 | R@50 |
|---|---|---|---|---|---|---|
| baseline | 0.8692 | 0.8333 | 0.8357 | 0.8813 | 0.9429 | 0.9578 |
| rerank | 0.8293 | 0.7500 | 0.8404 | 0.8856 | 0.9492 | 0.9578 |
| ideal | 0.9833 | 0.9833 | 0.9341 | 0.9461 | 0.9566 | 0.9578 |
Input format
The model scores raw (query_text, document) text pairs β no hand-engineered
features. query_text is " ".join(entities), the flat NER span texts joined
in occurrence order β the exact same string BM25 retrieval scores against, not
the typed city/country/admin1 split (that split is a display-only field on the
API response). document is three lines:
<name> | <name> | <name>
<country in English>
<admin1 region in English>
The ' | ' separator is load-bearing. Joined by a space instead,
a place's spellings collapse into one pseudo-name a span naming it once would
only partially overlap with. Separated, each spelling stands on its own.
A cross-encoder attends jointly over both texts in a single forward pass, so β unlike the CatBoost model this project used before β there is no need for hand-computed span/document overlap features: the previous model's bag-of-words text columns could not see the intersection between a query span and the document, which is exactly what a cross-encoder's cross-attention computes directly.
Training
Fine-tuned pointwise with BinaryCrossEntropyLoss on the mined
(query_text, document, label) pairs (:mod:src.rerank.dataset) β one row per
retrieved candidate, gold geonameid(s) labelled positive, everything else
negative. top_k=50 retrieval mines roughly one positive per query against up
to 50 negatives, so the loss is given a pos_weight computed from the train
split's own class ratio.
- epochs: 4
- batch size: 32
- learning rate: 2e-05
- warmup ratio: 0.1
- weight decay: 0.01
- max length: 128
- pos_weight (BCE): 25.552
- seed: 42
- best epoch: 1
- best test P@1: 0.8636
- trained at: 2026-08-12T05:52:12+00:00
Model selection is by P@1 on the held-out mined pairs (grouped by query),
scored after every epoch and saved on improvement β not by the pointwise
eval_loss, which doesn't reflect whether the top-ranked candidate within a
query's group is the gold one. Split by query, not by place: a query is the
ranking group, so splitting on geonameid would tear one query's candidates
across train and test β leaking the query and leaving positive-less test groups.
Training provenance
use_gold_entities: False
That flag has to be false for a servable model. true trains on the query
dataset's gold spans instead of mined NER output β a useful ablation ("how good
would this be if NER were perfect?") that breaks train/serve parity by design,
because online the reranker always receives GLiNER spans. A model trained with
it set must not be served, and this line is on the card so that cannot happen
silently.
Known gap
admin1_name exists in English only (admin1CodesASCII.txt), so the
document's admin1 line rarely matches a ru/zh query lexically. Regions are
feature_class='A' and the ETL loads only 'P', so no localised region names
were ever ingested.
Data licence and attribution
Derived from GeoNames, licensed CC BY 4.0.
Modifications made to the source data:
- filtered to populated places only (
feature_class = 'P') - restricted to RU, US, TR, CN
- restricted to name variants in ru, en, tr, zh
- dropped feature codes PPLH, PPLQ, PPLW, PPLX
- name variants grouped per place and joined into single document strings
The fine-tune inherits any licence conditions of its base model; check
cross-encoder/mmarco-mMiniLMv2-L12-H384-v1 before commercial use.
- Downloads last month
- 9