FR admin-split — pre-GPU self-validation (2026-06-19)
The international admin-split retrain (night 2026-06-19, surpass-v1.5.0) rests on one premise: that teaching the modelneural classifierThe machine learning model at the core of Mailwoman's parser — a transformer encoder (~30M parameters) trained from scratch to do BIO token classification over addresses. It learns the 'grammar' of address formats; the gazetteer supplies the 'atlas.' to split the département out of the localitylocalityThe city / town / settlement component of an address: a populated place sitting between region and neighbourhood in the hierarchy. moves the assembled, anchor-ON coordinate. The whole measurement-integrity campaign says to prove that before spending an A100 — the v1.7.0 trap was a labelcomponent tagOne of the 33 labels in Mailwoman's address schema — street, locality, region, postcode, house_number, unit, po_box, country, venue, intersection, and others. Each parsed span carries exactly one component tag. change the resolverresolverThe component that converts parsed address components (locality, region, postcode) into coordinates by looking them up in the gazetteer. The resolver ranks candidates by name match, population, and proximity, and returns the best-matching place with its centroid or polygon. ignored. So this is the falsification gate, run before any trainingtrainingThe process of adjusting a model's parameters so its predictions match labeled examples, by repeatedly measuring error and nudging the weights to reduce it. Distinct from inference, when the trained model is run on new input..
Method
For each sampled FR commune (truth = its own WOFWOF (Who's On First). An open-source gazetteer of places maintained by Mapzen/whosonfirst. Mailwoman builds a custom SQLite database from WOF GeoJSON repos, extended with postcode data, importance scores, and coincident-role relations. centroid), resolve three parseaddress parsingThe process of decomposing a free-text postal address string into structured components — house number, street name, locality, region, postcode, and country — so a geocoder can resolve them to coordinates. statesregionThe first-level administrative subdivision of a country — a US state, a French region, a province. The component between country and locality. through the
same resolverresolverThe component that converts parsed address components (locality, region, postcode) into coordinates by looking them up in the gazetteer. The resolver ranks candidates by name match, population, and proximity, and returns the best-matching place with its centroid or polygon. the geocoder ships (createWOFResolver over admin-global-priority.db,
defaultCountry: FR), and measure great-circle error to the truth centroid:
- dropped
{locality:[commune]}— the modelneural classifierThe machine learning model at the core of Mailwoman's parser — a transformer encoder (~30M parameters) trained from scratch to do BIO token classification over addresses. It learns the 'grammar' of address formats; the gazetteer supplies the 'atlas.''s observed "région → null" failure - merged
{locality:[commune + " " + dept]}— the AUCANBERRA ACTfuse failure - split
{locality:[commune], region:[dept]}— the corrected parseaddress parsingThe process of decomposing a free-text postal address string into structured components — house number, street name, locality, region, postcode, and country — so a geocoder can resolve them to coordinates.
Two strata: collision communes (a name shared by >1 département — where the région is the only
disambiguator) and unique communes (control). Unresolved is penalized to the countrycountryThe top-level address component (an ISO country). Closed-vocabulary, so it is best handled by a deterministic matcher feeding a proposal rather than a retrained model head. centroid
(the coordinate the geocoder actually falls back to on a miss), so the three statesregionThe first-level administrative subdivision of a country — a US state, a French region, a province. The component between country and locality. are comparable on
one metric instead of averaging over different resolved subsets. n=200 per stratum (scripts/eval/fr-admin-split-selfvalidation.ts).
Result
Collision communes (n=200) — the région disambiguates
| stateregionThe first-level administrative subdivision of a country — a US state, a French region, a province. The component between country and locality. | mean km | p50 | p90 | resolve-rate |
|---|---|---|---|---|
| dropped (région→null) | 172.4 | 132.0 | 391.8 | 92% |
| merged (loc = commune+dept) | 247.2 | 248.5 | 394.8 | 0% |
| split (corrected) | 66.7 | 0.0 | 281.4 | 97% |
SPLIT vs DROPPED: −61.3% mean error, split beats dropped by >2 km on 100/200.
Unique communes (n=200) — control
| stateregionThe first-level administrative subdivision of a country — a US state, a French region, a province. The component between country and locality. | mean km | p50 | p90 | resolve-rate |
|---|---|---|---|---|
| dropped (région→null) | 112.7 | 0.0 | 363.1 | 65% |
| merged (loc = commune+dept) | 318.0 | 315.5 | 453.6 | 0% |
| split (corrected) | 50.4 | 0.0 | 219.1 | 87% |
SPLIT vs DROPPED: −55.3%.
Read
Three findings, all the same direction:
- The région tag is decisive. Collision communes drop 172 → 67 km (p50 132 → 0). Without the région, the resolverresolverThe component that converts parsed address components (locality, region, postcode) into coordinates by looking them up in the gazetteer. The resolver ranks candidates by name match, population, and proximity, and returns the best-matching place with its centroid or polygon. picks the wrong same-named commune about half the time — exactly the disambiguation the split restores.
- The merge failure is catastrophic, not cosmetic.
locality = "Villeneuve Creuse"resolves to nothing (0% across both strata). The AU-style localitylocalityThe city / town / settlement component of an address: a populated place sitting between region and neighbourhood in the hierarchy.+admin fuse doesn't mis-resolve — it fails to resolve at all. Fixing it is pure upside. - Even unique communes benefit. Adding the département lifts resolve-rate 65 → 87%: a bare
{commune}doesn't always resolve, and the admin context helps the resolverresolverThe component that converts parsed address components (locality, region, postcode) into coordinates by looking them up in the gazetteer. The resolver ranks candidates by name match, population, and proximity, and returns the best-matching place with its centroid or polygon. find it.
Verdict: the lever is real — the resolverresolverThe component that converts parsed address components (locality, region, postcode) into coordinates by looking them up in the gazetteer. The resolver ranks candidates by name match, population, and proximity, and returns the best-matching place with its centroid or polygon. demonstrably uses the région tag, so a modelneural classifierThe machine learning model at the core of Mailwoman's parser — a transformer encoder (~30M parameters) trained from scratch to do BIO token classification over addresses. It learns the 'grammar' of address formats; the gazetteer supplies the 'atlas.' that emits the split will move the anchor-ON coordinate. The GPU is justified.
Honest caveat: this measures the ceiling with perfect, hand-constructed splits. The retrain
must still learn to (a) emit the right département and (b) keep the commune right. So the live gate
on the trained candidate (gate rubric in the night plan — FR centroid-shift, anchor-ON, vs v1.5.0)
is what counts; this only proves the ceiling is worth climbing toward. It is: a 55–61% reduction and
a 0% → 97% resolve-rate flip on the merge class.
Reproduce: node scripts/eval/fr-admin-split-selfvalidation.ts --n 200.