name-gender-nn-py
Gender classifier for first names
A small fully connected neural network written in pure Python, no dependencies. Multilingual: train on any dataset with its own alphabet.
name-gender-nn-py - gender classifier for first names. nn stands for neural network. A small fully connected network written in pure Python, no dependencies. Multilingual: train on any dataset with its own alphabet.
Determines whether a first name is male or female. Ships with two datasets:
- Russian (
data/names_ru.json) - Cyrillic alphabet, 108 names - English (
data/names_en.json) - Latin alphabet, 100 names
Each dataset defines its own alphabet. You train a separate model per dataset, and each model works only with names from its own alphabet.
⚠️ Educational project
Not production-ready. Shows how a small neural network works from scratch, without external ML libraries.
Scope: models are trained on full name forms (александр, екатерина, alexander, elizabeth). Diminutive and hypocoristic forms are not in the datasets and are not supported. Extending the datasets with such forms is possible, but requires a balanced addition (both male and female) to avoid degrading accuracy.
Determines whether a first name is male or female. Ships with two datasets:
- Russian (
data/names_ru.json) - Cyrillic alphabet, 108 names - English (
data/names_en.json) - Latin alphabet, 100 names
Each dataset defines its own alphabet. You train a separate model per dataset, and each model works only with names from its own alphabet.
- Alphabet. Each dataset defines its own alphabet as a string of characters plus a
_pad character. The Russian dataset uses the 33-letter Cyrillic alphabet; the English dataset uses the 26-letter Latin alphabet. - Features. Each name is split into three blocks: letters from the start, letters from the end, and the 2-letter suffix. Every character is one-hot encoded over the dataset alphabet.
- Model. Fully connected: input → hidden layer (40 neurons, sigmoid) → output (1 neuron, sigmoid). Trained with SGD,
lr = 0.1, 8000 epochs. - Data. Russian: 108 names (49 female, 59 male). English: 100 names (50 female, 50 male). Training takes ~40 seconds on a typical CPU.
- Accuracy. 100% on the training set for both datasets.
git clone https://github.com/smartlegionlab/name-gender-nn-py.git cd name-gender-nn-py # train the Russian model (~40 seconds) python train.py --data data/names_ru.json --out weights_ru.json # run it python predict.py --weights weights_ru.json
Requirements: Python 3.8+. Standard library only. No virtual environment needed.
Predict (interactive)
python predict.py --weights weights_ru.json Enter a name (or 'exit' to quit): > анна анна -> female (confidence 99.8%) > дмитрий дмитрий -> male (confidence 100.0%) > ольга ольга -> female (confidence 99.5%) > exit
Predict (one-liner)
python predict.py --weights weights_ru.json александр # александр -> male (confidence 99.7%)
Train the English model
python train.py --data data/names_en.json --out weights_en.json python predict.py --weights weights_en.json Enter a name (or 'exit' to quit): > mary mary -> female (confidence 99.0%) > john john -> male (confidence 100.0%) > elizabeth elizabeth -> female (confidence 99.7%) > exit
Validate a dataset
python check_data.py --data data/names_ru.json python check_data.py --data data/names_en.json
Output for the Russian dataset:
File: data/names_ru.json Alphabet size: 34 Loaded 49 female and 59 male names Alphabet check: OK Duplicate check: OK Cross-gender check: OK All checks passed.
Checks: all names use only characters from the dataset alphabet; no duplicates inside each list; no name appears in both female and male.
Russian dataset
Loaded 108 names from data/names_ru.json Alphabet size: 34 epoch 0 error=13.357281 t=0.0s epoch 500 error=0.019567 t=2.6s ... epoch 7500 error=0.000808 t=38.6s Train accuracy: 108/108 = 100.0% Weights saved to weights_ru.json Total time: 41.2s
English dataset
Loaded 100 names from data/names_en.json Alphabet size: 27 epoch 0 error=13.525733 t=0.0s epoch 500 error=0.030255 t=2.4s ... epoch 7500 error=0.001139 t=35.9s Train accuracy: 100/100 = 100.0% Weights saved to weights_en.json Total time: 38.3s
Inputs from the datasets
анна -> female (confidence 99.8%) дмитрий -> male (confidence 100.0%) ольга -> female (confidence 99.5%) mary -> female (confidence 99.0%) john -> male (confidence 100.0%) elizabeth -> female (confidence 99.7%)
Full forms not in the datasets
сара -> female (confidence 86.1%) мара -> female (confidence 94.4%) федот -> male (confidence 95.6%) karl -> male (confidence 93.5%)
name-gender-nn-py/ ├── data/ │ ├── names_ru.json # Russian dataset (Cyrillic) │ └── names_en.json # English dataset (Latin) ├── model.py # network architecture ├── train.py # training -> writes weights file ├── predict.py # CLI: input name -> gender ├── check_data.py # dataset validation ├── LICENSE # BSD 3-Clause License ├── DISCLAIMER.md # full legal disclaimer └── README.md
weights_*.json files are generated by train.py and are not tracked by git.
Open the dataset file you want to extend and add a name to either female or male:
{
"alphabet": "абвгдеёжзийклмнопрстуфхцчшщъыьэюя_",
"female": ["анна", "...", "александра"],
"male": ["иван", "...", "александр"]
}
Then retrain that dataset:
python train.py --data data/names_ru.json --out weights_ru.json
No code changes needed.
Create data/names_XX.json with the correct alphabet and name lists, then train:
python train.py --data data/names_XX.json --out weights_XX.json python predict.py --weights weights_XX.json
The model reads the alphabet from the dataset, so the same code can be reused for other languages by providing a new dataset file.
- name-gender-nn-rs - Rust port. Same algorithm, same datasets, ~40× faster training.
By using this software, you agree to the full disclaimer terms.
Software provided "AS IS" without warranty. You assume all risks.
Full legal disclaimer: See DISCLAIMER.md
License: BSD 3-Clause License