genderize — cora / ultra

Two models that take a personal name and return a gender (M/F) and a country (226 ISO-3166 alpha-2 codes), with probabilities. Byte-level, CPU-only, no tokenizer and no vocabulary file: you feed them a string.

Package contents

File What it is
genderize_cora.pt weights, cora (3.1 MB) — CC BY-NC 4.0
genderize_ultra.pt weights, ultra (12.9 MB) — CC BY-NC 4.0
genderize_cora.config.json {"ch": 160} — CC BY-NC 4.0
genderize_ultra.config.json {"ch": 384} — CC BY-NC 4.0
genderize_cora.calibration.json per-head temperature — CC BY-NC 4.0
genderize_ultra.calibration.json per-head temperature (the file additionally records a calibration-error metric) — CC BY-NC 4.0
maps.json class ids: gender M/F, 226 countries — CC BY-NC 4.0
genderize_infer.py standalone inference code (needs torch and numpy) — MIT
LICENSE full text of CC BY-NC 4.0 (weights)
LICENSE-CODE full text of the MIT License (inference code)
COMMERCIAL_USE.md what counts as non-commercial use, and how to obtain a commercial licence

What the models do

Variant Gender Country Size
genderize-cora 2 classes (M/F) 226 classes ~0.77M parameters, ch=160
genderize-ultra 2 classes (M/F) 226 classes ~3.21M parameters, ch=384

ultra is the larger, more accurate variant; cora is the lighter one. Both run on CPU: on an Intel i3-6100T (2 cores, 2 threads used) the network alone processes about 850 names/s (cora) and 160 names/s (ultra) in batches of 100.

How it works

1. Normalisation. The input name is normalised before anything else: Unicode NFC, lowercase, whitespace collapsed (internal runs and leading/trailing spaces become a single space). The normalised form is what the weights saw, so this step must not be changed or skipped:

"  MARÍA   GARCÍA  "  ->  "maría garcía"

2. Encoding. The normalised text is encoded as UTF-8 and truncated to 48 bytes (not 48 characters: an accented or non-Latin character takes more than one byte, so the effective character budget is smaller). Each byte becomes an integer in 0–255; byte value 0 is the padding value. A name shorter than 48 bytes is padded with zeros.

3. Network. Byte-level, dual-head 1-D convolutional classifier:

  • one embedding table, 256 entries (one per byte value) of width 64, padding index 0;
  • a 1×1 convolution projecting 64 → ch channels;
  • four residual 1-D convolution blocks, kernel sizes 3, 5, 7, 3, each with convolution + BatchNorm + GELU around a residual connection, padding to keep the length;
  • the masked positions are pooled twice — mean-pooling and max-pooling — and the two vectors are concatenated;
  • a shared layer of 512 units (GELU, plus a dropout layer that is inactive at inference);
  • two linear heads read out from it: gender, 2 classes, and country, 226 classes.

cora uses ch = 160, ultra ch = 384; those are the only differences between the two configs.

4. Probabilities. Because it is a convolutional stack, the model sees all byte positions at once: character order matters through the convolution kernels, not through a recurrent state. Logits are divided by a per-head temperature before softmax — temp_gender and temp_country from the calibration file:

Variant temp_gender temp_country
cora 1.0096479654312134 1.0
ultra 1.0460342168807983 0.939997673034668

5. Decision rule. Gender is reported as male when P(M) ≥ 0.5, otherwise female; the reported probability is the probability of the reported class. Countries are returned as the top-k codes (default 5, --top) sorted by probability.

6. Output. One record per input name:

{"name": "...", "gender": "male|female", "probability": 0.0-1.0,
 "countries": [{"code": "IT", "probability": 0.0-1.0}, ...], "model": "cora|ultra"}

Loading and using the weights

All files sit flat in this repository. Download them (for example with huggingface_hub.snapshot_download("textpie/genderize")) and run the reference driver from that directory:

pip install torch numpy
python genderize_infer.py --variant ultra --top 3 "Andrea Rossi"

In Python:

from genderize_infer import Genderize

model = Genderize("ultra")              # or Genderize("cora"); pass models_dir=... if the files live elsewhere
model.predict(["Andrea Rossi"], top=3)

Output for the five names published with the examples (--variant ultra), reproduced locally against these exact weight files:

Input Gender P Country top-3
Andrea Rossi male 0.849 IT 0.84, FR 0.05, US 0.02
Yuki Tanaka female 0.589 JP 0.98, US 0.01, ID 0.00
María García female 0.995 ES 0.42, MX 0.13, AR 0.09
Chen Wei male 0.692 CN 0.56, TW 0.13, SG 0.09
Fatima Al Sayed female 0.996 AE 0.35, OM 0.19, SA 0.14

Benchmarks

Source: dbtool.it/benchmark. These are not new measurements taken for this card and no re-measurement was performed here.

  • Bench: 25,000 names never seen in training, scored on the network alone.
  • The dictionary layer used by the hosted API does not contribute on unseen names, so these figures describe the released weights.
Metric cora ultra
Gender accuracy 97.9 % 98.2 %
Country top-1 accuracy 82.6 % 83.7 %

Per-country figures for the full hosted system are on https://dbtool.it/academic; an independent open bench on public WGND 2.0 names (network alone, losses included) is on https://dbtool.it/benchmark.

What this release does NOT include

  • The dictionary layer of the API. The hosted API combines the network with a proprietary frequency layer (exact-name and per-country M/F frequencies) derived from production data. That layer is not part of this release: you get the network alone. Consequence: the public API can answer differently from the weights you download, especially on very frequent names. Documented example: Yuki Tanaka scores female 0.59 with the network alone (the value reproduced above), while the API with its dictionary layer answers male 0.58.
  • Everything about how the models were trained: no recipe, no epochs, no optimiser, no data split, no training hyperparameters, no data sources and no per-country counts. This release ships a usable model, not the process behind it, and no training example.

Training data — nature only

The models were trained on name–gender–country pairs covering 226 countries, tens of millions of examples. That is the whole description this release provides: the corpus is not redistributed, and its sources, composition and per-country sizes are not part of the package.

Limitations

  • East Asian names: accuracy drops to roughly 82–88 %; Chinese, Korean and Japanese names are frequently confused with one another.
  • Names ambiguous across countries: many names are plausible in several countries, so a top-1 of ~83 % means roughly one name in six gets the wrong country. Andrea is the classic case: male in Italy, female elsewhere. Treat the country score as a prior, and never as a single-country verdict.
  • 48-byte truncation: only the first 48 UTF-8 bytes reach the model. Long names and long compounds are silently cut, and multi-byte characters consume more of the budget than plain ASCII.
  • Empty or near-empty input: an empty or fully-trimmed name is encoded as 48 padding bytes and still returns a prediction. Validate your input.
  • Binary gender: the gender head has two classes; names that do not fit them are forced into the closer one.
  • Transliteration: results depend on how the name was romanised upstream; different romanisations of the same name can disagree.
  • Dictionary gap: the released weights are the network alone, so for very frequent names they can differ from the hosted API (see above).

Licence

Two licences, one per artefact:

  • Weightsgenderize_cora.pt, genderize_ultra.pt, their .config.json and .calibration.json, and maps.json — are released under Creative Commons Attribution-NonCommercial 4.0 International (CC BY-NC 4.0), full text in LICENSE. You may download, run, study, modify and redistribute them and their derivatives for non-commercial purposes, with attribution (dbtool.it, genderize cora/ultra, 2026) and an indication of changes.
  • Inference codegenderize_infer.py — is released under the MIT License, full text in LICENSE-CODE. It can be reused freely; it carries no model knowledge.

Commercial use of the weights is not granted by this licence. The commercial channel is dbtool.it (the hosted API and the on-premise licence), or a separate written licence from the rights holder. What counts as commercial use, and how to request a licence, is set out in COMMERCIAL_USE.md.

The training data is not part of this release, and neither is the dictionary layer of the hosted API (see above).

Contact

dbtool — https://dbtool.it — open-weights page: https://dbtool.it/open-models.html Domenico Gigante, d.gigante@tech-time.it

Downloads last month

-

Downloads are not tracked for this model. How to track
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support