genderfluid-tiny 1.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- genderfluid_tiny-1.0.0/PKG-INFO +369 -0
- genderfluid_tiny-1.0.0/README.md +345 -0
- genderfluid_tiny-1.0.0/genderfluid/__init__.py +78 -0
- genderfluid_tiny-1.0.0/genderfluid/__main__.py +6 -0
- genderfluid_tiny-1.0.0/genderfluid/calibration.py +110 -0
- genderfluid_tiny-1.0.0/genderfluid/classifier.py +181 -0
- genderfluid_tiny-1.0.0/genderfluid/cli.py +270 -0
- genderfluid_tiny-1.0.0/genderfluid/features.py +83 -0
- genderfluid_tiny-1.0.0/genderfluid/inference.py +213 -0
- genderfluid_tiny-1.0.0/genderfluid/model_io.py +166 -0
- genderfluid_tiny-1.0.0/genderfluid/models/genderfluid-tiny.bin +0 -0
- genderfluid_tiny-1.0.0/genderfluid/preprocessing.py +57 -0
- genderfluid_tiny-1.0.0/genderfluid_tiny.egg-info/PKG-INFO +369 -0
- genderfluid_tiny-1.0.0/genderfluid_tiny.egg-info/SOURCES.txt +19 -0
- genderfluid_tiny-1.0.0/genderfluid_tiny.egg-info/dependency_links.txt +1 -0
- genderfluid_tiny-1.0.0/genderfluid_tiny.egg-info/entry_points.txt +2 -0
- genderfluid_tiny-1.0.0/genderfluid_tiny.egg-info/requires.txt +2 -0
- genderfluid_tiny-1.0.0/genderfluid_tiny.egg-info/top_level.txt +1 -0
- genderfluid_tiny-1.0.0/pyproject.toml +47 -0
- genderfluid_tiny-1.0.0/setup.cfg +4 -0
- genderfluid_tiny-1.0.0/tests/test_all.py +292 -0
|
@@ -0,0 +1,369 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: genderfluid-tiny
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Tiny local name-gender association classifier. Estimates statistical associations between names and gendered naming conventions.
|
|
5
|
+
Author: Max Edgar
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/MaxEdgar/genderfluid-tiny
|
|
8
|
+
Project-URL: Repository, https://github.com/MaxEdgar/genderfluid-tiny
|
|
9
|
+
Project-URL: Issues, https://github.com/MaxEdgar/genderfluid-tiny/issues
|
|
10
|
+
Keywords: name,gender,classifier,nlp,offline
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Operating System :: OS Independent
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Topic :: Text Processing :: Linguistic
|
|
20
|
+
Requires-Python: >=3.10
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
Requires-Dist: scikit-learn>=1.0
|
|
23
|
+
Requires-Dist: numpy>=1.20
|
|
24
|
+
|
|
25
|
+
# genderfluid tiny
|
|
26
|
+
|
|
27
|
+
Tiny local name-gender association classifier.
|
|
28
|
+
|
|
29
|
+
Estimates statistical associations between names and gendered naming conventions
|
|
30
|
+
in its training data. Does not determine a person's gender identity.
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
[](https://www.python.org/downloads/)
|
|
35
|
+
[](tests/)
|
|
36
|
+
[](models/)
|
|
37
|
+
[](LICENSE)
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## Overview
|
|
42
|
+
|
|
43
|
+
A small offline classifier that estimates whether a name is statistically
|
|
44
|
+
associated with feminine or masculine naming conventions. The classifier
|
|
45
|
+
uses character n-gram features and logistic regression. It outputs three
|
|
46
|
+
categories: `girl-associated`, `boy-associated`, and `uncertain`.
|
|
47
|
+
|
|
48
|
+
| Property | Value |
|
|
49
|
+
|----------|-------|
|
|
50
|
+
| Architecture | Character n-gram + logistic regression |
|
|
51
|
+
| Inference | CPU only |
|
|
52
|
+
| Internet | Not required |
|
|
53
|
+
| GPU | Not required |
|
|
54
|
+
| Model size | 0.05 MB (49,689 bytes) |
|
|
55
|
+
| Python | 3.10+ |
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## Installation
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
git clone https://github.com/MaxEdgar/genderfluid-tiny.git
|
|
63
|
+
cd genderfluid-tiny
|
|
64
|
+
python -m venv .venv
|
|
65
|
+
source .venv/bin/activate
|
|
66
|
+
pip install -r requirements.txt
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Or install as a package:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
pip install -e .
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
After installation, the `genderfluid` command is available system-wide.
|
|
76
|
+
|
|
77
|
+
Windows:
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
python -m venv .venv
|
|
81
|
+
.venv\Scripts\activate
|
|
82
|
+
pip install -r requirements.txt
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Quick start
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
python predict.py "Elva Retta"
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Or after `pip install -e .`:
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
genderfluid predict "Elva Retta"
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Output:
|
|
98
|
+
|
|
99
|
+
```
|
|
100
|
+
Name: Elva Retta
|
|
101
|
+
|
|
102
|
+
Girl-associated: 97.5%
|
|
103
|
+
Boy-associated: 1.2%
|
|
104
|
+
Uncertain: 1.2%
|
|
105
|
+
|
|
106
|
+
Classification: girl-associated
|
|
107
|
+
Confidence: high
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Python API
|
|
111
|
+
|
|
112
|
+
There are two ways to use the Python API.
|
|
113
|
+
|
|
114
|
+
**Option 1: Simple one-liners**
|
|
115
|
+
|
|
116
|
+
```python
|
|
117
|
+
from genderfluid import classify_name, is_girl_name, is_boy_name, name_probability
|
|
118
|
+
|
|
119
|
+
classify_name("Emma") # "girl-associated"
|
|
120
|
+
classify_name("James") # "boy-associated"
|
|
121
|
+
classify_name("Alex") # "uncertain"
|
|
122
|
+
|
|
123
|
+
is_girl_name("Emma") # True
|
|
124
|
+
is_boy_name("James") # True
|
|
125
|
+
|
|
126
|
+
name_probability("Emma") # 0.9731
|
|
127
|
+
name_probability("Alex") # 0.2692
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
**Option 2: Full result dict**
|
|
131
|
+
|
|
132
|
+
```python
|
|
133
|
+
from genderfluid import predict_name, predict_names
|
|
134
|
+
|
|
135
|
+
result = predict_name("Alex")
|
|
136
|
+
print(result["classification"]) # "uncertain"
|
|
137
|
+
print(result["girl_associated_probability"]) # 0.2692
|
|
138
|
+
|
|
139
|
+
results = predict_names(["Emma", "James", "Alex"])
|
|
140
|
+
for r in results:
|
|
141
|
+
print(f"{r['name']}: {r['classification']}")
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
**Option 3: Model instance (recommended for repeated use)**
|
|
145
|
+
|
|
146
|
+
```python
|
|
147
|
+
from genderfluid import GenderfluidModel
|
|
148
|
+
|
|
149
|
+
model = GenderfluidModel() # loads default model
|
|
150
|
+
|
|
151
|
+
result = model.predict("Elva Retta")
|
|
152
|
+
print(result["classification"]) # "girl-associated"
|
|
153
|
+
|
|
154
|
+
# Batch prediction (more efficient for many names)
|
|
155
|
+
results = model.predict_batch(["Emma", "James", "Alex", "Max", "Taylor"])
|
|
156
|
+
for r in results:
|
|
157
|
+
print(f"{r['name']}: {r['classification']} ({r['confidence']})")
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
The model is loaded once and cached. Subsequent predictions are fast.
|
|
161
|
+
|
|
162
|
+
**Prediction result format:**
|
|
163
|
+
|
|
164
|
+
```python
|
|
165
|
+
{
|
|
166
|
+
"name": "Elva Retta",
|
|
167
|
+
"girl_associated_probability": 0.975,
|
|
168
|
+
"boy_associated_probability": 0.012,
|
|
169
|
+
"uncertain_probability": 0.012,
|
|
170
|
+
"classification": "girl-associated",
|
|
171
|
+
"confidence": "high"
|
|
172
|
+
}
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
Confidence levels: `high` (>= 90%), `medium` (>= 70%), `low` (< 70%).
|
|
176
|
+
|
|
177
|
+
## CLI
|
|
178
|
+
|
|
179
|
+
After `pip install -e .`, use the `genderfluid` command. Or run directly
|
|
180
|
+
with `python -m genderfluid` or `python predict.py`.
|
|
181
|
+
|
|
182
|
+
**Predict a name:**
|
|
183
|
+
|
|
184
|
+
```bash
|
|
185
|
+
genderfluid predict "Elva Retta"
|
|
186
|
+
genderfluid "Alex" # shorthand
|
|
187
|
+
python predict.py "Elva Retta" # backward-compatible
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
**Compare multiple names:**
|
|
191
|
+
|
|
192
|
+
```bash
|
|
193
|
+
genderfluid predict --compare "Emma" "James" "Alex" "Max" "Taylor"
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
Output:
|
|
197
|
+
|
|
198
|
+
```
|
|
199
|
+
Name Classification Girl Boy Confidence
|
|
200
|
+
----------------------------------------------------------------------
|
|
201
|
+
Emma girl-associated 97% 0% high
|
|
202
|
+
James boy-associated 8% 79% medium
|
|
203
|
+
Alex uncertain 27% 59% low
|
|
204
|
+
Max boy-associated 7% 77% medium
|
|
205
|
+
Taylor uncertain 42% 17% low
|
|
206
|
+
|
|
207
|
+
5 names in 31.6 ms
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
**Batch from file:**
|
|
211
|
+
|
|
212
|
+
```bash
|
|
213
|
+
genderfluid predict --file names.txt
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
Reads one name per line, outputs JSONL with timing info.
|
|
217
|
+
|
|
218
|
+
**JSON output:**
|
|
219
|
+
|
|
220
|
+
```bash
|
|
221
|
+
genderfluid predict --json "Michelle Renatta Chan"
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
**Interactive mode:**
|
|
225
|
+
|
|
226
|
+
```bash
|
|
227
|
+
genderfluid interactive
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
**Model statistics:**
|
|
231
|
+
|
|
232
|
+
```bash
|
|
233
|
+
genderfluid stats
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
**Benchmark:**
|
|
237
|
+
|
|
238
|
+
```bash
|
|
239
|
+
genderfluid benchmark
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
## Model
|
|
243
|
+
|
|
244
|
+
The classifier works as follows:
|
|
245
|
+
|
|
246
|
+
```
|
|
247
|
+
Input name
|
|
248
|
+
|
|
|
249
|
+
Unicode normalization + lowercase
|
|
250
|
+
|
|
|
251
|
+
Character n-gram extraction (2-5 grams)
|
|
252
|
+
|
|
|
253
|
+
Hashing trick (compact fixed-size feature vector)
|
|
254
|
+
|
|
|
255
|
+
Logistic regression (3 classes)
|
|
256
|
+
|
|
|
257
|
+
Sigmoid calibration
|
|
258
|
+
|
|
|
259
|
+
Output: girl-associated / boy-associated / uncertain
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
Trained on 102,927 real names from SSA (1880-2020) and Census 2020 data.
|
|
263
|
+
Test accuracy: 70.7%. Macro F1: 0.64.
|
|
264
|
+
|
|
265
|
+
## Training
|
|
266
|
+
|
|
267
|
+
```bash
|
|
268
|
+
python process_real_data.py # download and process SSA + Census data
|
|
269
|
+
python prepare_data.py # validate and split data
|
|
270
|
+
python train.py # train and save model
|
|
271
|
+
python evaluate.py # evaluate on validation/test splits
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
The training script loads and validates the dataset, trains a logistic
|
|
275
|
+
regression classifier, calibrates probabilities, and saves the model
|
|
276
|
+
to `models/genderfluid-tiny.bin`.
|
|
277
|
+
|
|
278
|
+
## Dataset
|
|
279
|
+
|
|
280
|
+
JSONL format, one entry per line:
|
|
281
|
+
|
|
282
|
+
```json
|
|
283
|
+
{"name": "Emma", "label": "girl-associated"}
|
|
284
|
+
{"name": "James", "label": "boy-associated"}
|
|
285
|
+
{"name": "Alex", "label": "uncertain"}
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
Optional fields: `weight`, `country`, `language`, `year`.
|
|
289
|
+
|
|
290
|
+
The included dataset is built from real public data:
|
|
291
|
+
|
|
292
|
+
1. U.S. Social Security Administration baby names (1880-2020)
|
|
293
|
+
2. U.S. Census Bureau 2020 Census first names
|
|
294
|
+
|
|
295
|
+
Processed by `process_real_data.py`. Names with 85% or stronger
|
|
296
|
+
statistical association are labeled `girl-associated` or `boy-associated`.
|
|
297
|
+
Names below that threshold are `uncertain`.
|
|
298
|
+
|
|
299
|
+
## Benchmark
|
|
300
|
+
|
|
301
|
+
Measured on Intel Celeron N4000 @ 1.10GHz, Python 3.14:
|
|
302
|
+
|
|
303
|
+
```
|
|
304
|
+
Model size: 0.05 MB (49,689 bytes)
|
|
305
|
+
Loading time: 0.3 ms
|
|
306
|
+
Single name: 0.93 ms
|
|
307
|
+
Batch (10): 2.5 ms (4,065 names/sec)
|
|
308
|
+
Batch (100): 18.7 ms (5,335 names/sec)
|
|
309
|
+
Batch (1000): 180.1 ms (5,551 names/sec)
|
|
310
|
+
Peak RSS: 198 MB
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
Run `genderfluid benchmark` to measure on your own hardware.
|
|
314
|
+
|
|
315
|
+
## Limitations
|
|
316
|
+
|
|
317
|
+
The model estimates statistical patterns in its training data. It does not
|
|
318
|
+
determine gender identity.
|
|
319
|
+
|
|
320
|
+
Name associations vary by culture, language, and generation. The classifier
|
|
321
|
+
may be wrong. The `uncertain` category exists for ambiguous cases. Training
|
|
322
|
+
data can contain bias.
|
|
323
|
+
|
|
324
|
+
## Privacy
|
|
325
|
+
|
|
326
|
+
All inference runs locally. Names are not transmitted to any external service.
|
|
327
|
+
Logging of names is disabled by default (`config.yaml`).
|
|
328
|
+
|
|
329
|
+
## Repository
|
|
330
|
+
|
|
331
|
+
```
|
|
332
|
+
genderfluid-tiny/
|
|
333
|
+
├── genderfluid/
|
|
334
|
+
│ ├── __init__.py
|
|
335
|
+
│ ├── __main__.py
|
|
336
|
+
│ ├── cli.py
|
|
337
|
+
│ ├── preprocessing.py
|
|
338
|
+
│ ├── features.py
|
|
339
|
+
│ ├── classifier.py
|
|
340
|
+
│ ├── calibration.py
|
|
341
|
+
│ ├── inference.py
|
|
342
|
+
│ └── model_io.py
|
|
343
|
+
├── data/
|
|
344
|
+
│ ├── names.jsonl
|
|
345
|
+
│ └── README.md
|
|
346
|
+
├── models/
|
|
347
|
+
│ └── genderfluid-tiny.bin
|
|
348
|
+
├── native/
|
|
349
|
+
│ ├── main.cpp
|
|
350
|
+
│ ├── model.cpp
|
|
351
|
+
│ └── model.h
|
|
352
|
+
├── tests/
|
|
353
|
+
│ └── test_all.py
|
|
354
|
+
├── train.py
|
|
355
|
+
├── predict.py
|
|
356
|
+
├── evaluate.py
|
|
357
|
+
├── benchmark.py
|
|
358
|
+
├── prepare_data.py
|
|
359
|
+
├── process_real_data.py
|
|
360
|
+
├── requirements.txt
|
|
361
|
+
├── pyproject.toml
|
|
362
|
+
├── config.yaml
|
|
363
|
+
├── .gitignore
|
|
364
|
+
└── README.md
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
## License
|
|
368
|
+
|
|
369
|
+
MIT
|
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
# genderfluid tiny
|
|
2
|
+
|
|
3
|
+
Tiny local name-gender association classifier.
|
|
4
|
+
|
|
5
|
+
Estimates statistical associations between names and gendered naming conventions
|
|
6
|
+
in its training data. Does not determine a person's gender identity.
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
[](https://www.python.org/downloads/)
|
|
11
|
+
[](tests/)
|
|
12
|
+
[](models/)
|
|
13
|
+
[](LICENSE)
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Overview
|
|
18
|
+
|
|
19
|
+
A small offline classifier that estimates whether a name is statistically
|
|
20
|
+
associated with feminine or masculine naming conventions. The classifier
|
|
21
|
+
uses character n-gram features and logistic regression. It outputs three
|
|
22
|
+
categories: `girl-associated`, `boy-associated`, and `uncertain`.
|
|
23
|
+
|
|
24
|
+
| Property | Value |
|
|
25
|
+
|----------|-------|
|
|
26
|
+
| Architecture | Character n-gram + logistic regression |
|
|
27
|
+
| Inference | CPU only |
|
|
28
|
+
| Internet | Not required |
|
|
29
|
+
| GPU | Not required |
|
|
30
|
+
| Model size | 0.05 MB (49,689 bytes) |
|
|
31
|
+
| Python | 3.10+ |
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## Installation
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
git clone https://github.com/MaxEdgar/genderfluid-tiny.git
|
|
39
|
+
cd genderfluid-tiny
|
|
40
|
+
python -m venv .venv
|
|
41
|
+
source .venv/bin/activate
|
|
42
|
+
pip install -r requirements.txt
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Or install as a package:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
pip install -e .
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
After installation, the `genderfluid` command is available system-wide.
|
|
52
|
+
|
|
53
|
+
Windows:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
python -m venv .venv
|
|
57
|
+
.venv\Scripts\activate
|
|
58
|
+
pip install -r requirements.txt
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Quick start
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
python predict.py "Elva Retta"
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Or after `pip install -e .`:
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
genderfluid predict "Elva Retta"
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Output:
|
|
74
|
+
|
|
75
|
+
```
|
|
76
|
+
Name: Elva Retta
|
|
77
|
+
|
|
78
|
+
Girl-associated: 97.5%
|
|
79
|
+
Boy-associated: 1.2%
|
|
80
|
+
Uncertain: 1.2%
|
|
81
|
+
|
|
82
|
+
Classification: girl-associated
|
|
83
|
+
Confidence: high
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## Python API
|
|
87
|
+
|
|
88
|
+
There are two ways to use the Python API.
|
|
89
|
+
|
|
90
|
+
**Option 1: Simple one-liners**
|
|
91
|
+
|
|
92
|
+
```python
|
|
93
|
+
from genderfluid import classify_name, is_girl_name, is_boy_name, name_probability
|
|
94
|
+
|
|
95
|
+
classify_name("Emma") # "girl-associated"
|
|
96
|
+
classify_name("James") # "boy-associated"
|
|
97
|
+
classify_name("Alex") # "uncertain"
|
|
98
|
+
|
|
99
|
+
is_girl_name("Emma") # True
|
|
100
|
+
is_boy_name("James") # True
|
|
101
|
+
|
|
102
|
+
name_probability("Emma") # 0.9731
|
|
103
|
+
name_probability("Alex") # 0.2692
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
**Option 2: Full result dict**
|
|
107
|
+
|
|
108
|
+
```python
|
|
109
|
+
from genderfluid import predict_name, predict_names
|
|
110
|
+
|
|
111
|
+
result = predict_name("Alex")
|
|
112
|
+
print(result["classification"]) # "uncertain"
|
|
113
|
+
print(result["girl_associated_probability"]) # 0.2692
|
|
114
|
+
|
|
115
|
+
results = predict_names(["Emma", "James", "Alex"])
|
|
116
|
+
for r in results:
|
|
117
|
+
print(f"{r['name']}: {r['classification']}")
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
**Option 3: Model instance (recommended for repeated use)**
|
|
121
|
+
|
|
122
|
+
```python
|
|
123
|
+
from genderfluid import GenderfluidModel
|
|
124
|
+
|
|
125
|
+
model = GenderfluidModel() # loads default model
|
|
126
|
+
|
|
127
|
+
result = model.predict("Elva Retta")
|
|
128
|
+
print(result["classification"]) # "girl-associated"
|
|
129
|
+
|
|
130
|
+
# Batch prediction (more efficient for many names)
|
|
131
|
+
results = model.predict_batch(["Emma", "James", "Alex", "Max", "Taylor"])
|
|
132
|
+
for r in results:
|
|
133
|
+
print(f"{r['name']}: {r['classification']} ({r['confidence']})")
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
The model is loaded once and cached. Subsequent predictions are fast.
|
|
137
|
+
|
|
138
|
+
**Prediction result format:**
|
|
139
|
+
|
|
140
|
+
```python
|
|
141
|
+
{
|
|
142
|
+
"name": "Elva Retta",
|
|
143
|
+
"girl_associated_probability": 0.975,
|
|
144
|
+
"boy_associated_probability": 0.012,
|
|
145
|
+
"uncertain_probability": 0.012,
|
|
146
|
+
"classification": "girl-associated",
|
|
147
|
+
"confidence": "high"
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
Confidence levels: `high` (>= 90%), `medium` (>= 70%), `low` (< 70%).
|
|
152
|
+
|
|
153
|
+
## CLI
|
|
154
|
+
|
|
155
|
+
After `pip install -e .`, use the `genderfluid` command. Or run directly
|
|
156
|
+
with `python -m genderfluid` or `python predict.py`.
|
|
157
|
+
|
|
158
|
+
**Predict a name:**
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
genderfluid predict "Elva Retta"
|
|
162
|
+
genderfluid "Alex" # shorthand
|
|
163
|
+
python predict.py "Elva Retta" # backward-compatible
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
**Compare multiple names:**
|
|
167
|
+
|
|
168
|
+
```bash
|
|
169
|
+
genderfluid predict --compare "Emma" "James" "Alex" "Max" "Taylor"
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
Output:
|
|
173
|
+
|
|
174
|
+
```
|
|
175
|
+
Name Classification Girl Boy Confidence
|
|
176
|
+
----------------------------------------------------------------------
|
|
177
|
+
Emma girl-associated 97% 0% high
|
|
178
|
+
James boy-associated 8% 79% medium
|
|
179
|
+
Alex uncertain 27% 59% low
|
|
180
|
+
Max boy-associated 7% 77% medium
|
|
181
|
+
Taylor uncertain 42% 17% low
|
|
182
|
+
|
|
183
|
+
5 names in 31.6 ms
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
**Batch from file:**
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
genderfluid predict --file names.txt
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
Reads one name per line, outputs JSONL with timing info.
|
|
193
|
+
|
|
194
|
+
**JSON output:**
|
|
195
|
+
|
|
196
|
+
```bash
|
|
197
|
+
genderfluid predict --json "Michelle Renatta Chan"
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
**Interactive mode:**
|
|
201
|
+
|
|
202
|
+
```bash
|
|
203
|
+
genderfluid interactive
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
**Model statistics:**
|
|
207
|
+
|
|
208
|
+
```bash
|
|
209
|
+
genderfluid stats
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
**Benchmark:**
|
|
213
|
+
|
|
214
|
+
```bash
|
|
215
|
+
genderfluid benchmark
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
## Model
|
|
219
|
+
|
|
220
|
+
The classifier works as follows:
|
|
221
|
+
|
|
222
|
+
```
|
|
223
|
+
Input name
|
|
224
|
+
|
|
|
225
|
+
Unicode normalization + lowercase
|
|
226
|
+
|
|
|
227
|
+
Character n-gram extraction (2-5 grams)
|
|
228
|
+
|
|
|
229
|
+
Hashing trick (compact fixed-size feature vector)
|
|
230
|
+
|
|
|
231
|
+
Logistic regression (3 classes)
|
|
232
|
+
|
|
|
233
|
+
Sigmoid calibration
|
|
234
|
+
|
|
|
235
|
+
Output: girl-associated / boy-associated / uncertain
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
Trained on 102,927 real names from SSA (1880-2020) and Census 2020 data.
|
|
239
|
+
Test accuracy: 70.7%. Macro F1: 0.64.
|
|
240
|
+
|
|
241
|
+
## Training
|
|
242
|
+
|
|
243
|
+
```bash
|
|
244
|
+
python process_real_data.py # download and process SSA + Census data
|
|
245
|
+
python prepare_data.py # validate and split data
|
|
246
|
+
python train.py # train and save model
|
|
247
|
+
python evaluate.py # evaluate on validation/test splits
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
The training script loads and validates the dataset, trains a logistic
|
|
251
|
+
regression classifier, calibrates probabilities, and saves the model
|
|
252
|
+
to `models/genderfluid-tiny.bin`.
|
|
253
|
+
|
|
254
|
+
## Dataset
|
|
255
|
+
|
|
256
|
+
JSONL format, one entry per line:
|
|
257
|
+
|
|
258
|
+
```json
|
|
259
|
+
{"name": "Emma", "label": "girl-associated"}
|
|
260
|
+
{"name": "James", "label": "boy-associated"}
|
|
261
|
+
{"name": "Alex", "label": "uncertain"}
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
Optional fields: `weight`, `country`, `language`, `year`.
|
|
265
|
+
|
|
266
|
+
The included dataset is built from real public data:
|
|
267
|
+
|
|
268
|
+
1. U.S. Social Security Administration baby names (1880-2020)
|
|
269
|
+
2. U.S. Census Bureau 2020 Census first names
|
|
270
|
+
|
|
271
|
+
Processed by `process_real_data.py`. Names with 85% or stronger
|
|
272
|
+
statistical association are labeled `girl-associated` or `boy-associated`.
|
|
273
|
+
Names below that threshold are `uncertain`.
|
|
274
|
+
|
|
275
|
+
## Benchmark
|
|
276
|
+
|
|
277
|
+
Measured on Intel Celeron N4000 @ 1.10GHz, Python 3.14:
|
|
278
|
+
|
|
279
|
+
```
|
|
280
|
+
Model size: 0.05 MB (49,689 bytes)
|
|
281
|
+
Loading time: 0.3 ms
|
|
282
|
+
Single name: 0.93 ms
|
|
283
|
+
Batch (10): 2.5 ms (4,065 names/sec)
|
|
284
|
+
Batch (100): 18.7 ms (5,335 names/sec)
|
|
285
|
+
Batch (1000): 180.1 ms (5,551 names/sec)
|
|
286
|
+
Peak RSS: 198 MB
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
Run `genderfluid benchmark` to measure on your own hardware.
|
|
290
|
+
|
|
291
|
+
## Limitations
|
|
292
|
+
|
|
293
|
+
The model estimates statistical patterns in its training data. It does not
|
|
294
|
+
determine gender identity.
|
|
295
|
+
|
|
296
|
+
Name associations vary by culture, language, and generation. The classifier
|
|
297
|
+
may be wrong. The `uncertain` category exists for ambiguous cases. Training
|
|
298
|
+
data can contain bias.
|
|
299
|
+
|
|
300
|
+
## Privacy
|
|
301
|
+
|
|
302
|
+
All inference runs locally. Names are not transmitted to any external service.
|
|
303
|
+
Logging of names is disabled by default (`config.yaml`).
|
|
304
|
+
|
|
305
|
+
## Repository
|
|
306
|
+
|
|
307
|
+
```
|
|
308
|
+
genderfluid-tiny/
|
|
309
|
+
├── genderfluid/
|
|
310
|
+
│ ├── __init__.py
|
|
311
|
+
│ ├── __main__.py
|
|
312
|
+
│ ├── cli.py
|
|
313
|
+
│ ├── preprocessing.py
|
|
314
|
+
│ ├── features.py
|
|
315
|
+
│ ├── classifier.py
|
|
316
|
+
│ ├── calibration.py
|
|
317
|
+
│ ├── inference.py
|
|
318
|
+
│ └── model_io.py
|
|
319
|
+
├── data/
|
|
320
|
+
│ ├── names.jsonl
|
|
321
|
+
│ └── README.md
|
|
322
|
+
├── models/
|
|
323
|
+
│ └── genderfluid-tiny.bin
|
|
324
|
+
├── native/
|
|
325
|
+
│ ├── main.cpp
|
|
326
|
+
│ ├── model.cpp
|
|
327
|
+
│ └── model.h
|
|
328
|
+
├── tests/
|
|
329
|
+
│ └── test_all.py
|
|
330
|
+
├── train.py
|
|
331
|
+
├── predict.py
|
|
332
|
+
├── evaluate.py
|
|
333
|
+
├── benchmark.py
|
|
334
|
+
├── prepare_data.py
|
|
335
|
+
├── process_real_data.py
|
|
336
|
+
├── requirements.txt
|
|
337
|
+
├── pyproject.toml
|
|
338
|
+
├── config.yaml
|
|
339
|
+
├── .gitignore
|
|
340
|
+
└── README.md
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
## License
|
|
344
|
+
|
|
345
|
+
MIT
|