Instructions to use TimmaJ/age-gender-race-prediction with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use TimmaJ/age-gender-race-prediction with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("image-classification", model="TimmaJ/age-gender-race-prediction") pipe("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/hub/parrots.png")# Load model directly from transformers import AutoModel model = AutoModel.from_pretrained("TimmaJ/age-gender-race-prediction", device_map="auto") - Notebooks
- Google Colab
- Kaggle
Age, Gender and Race Prediction from Faces
Three ConvNeXt-base models predicting age, gender and race from a face image, trained on UTKFace + FairFace (116,504 images).
| Task | Output | Held-out accuracy |
|---|---|---|
| Age | continuous years | MAE 4.66 years |
| Gender | Male / Female | 97.3% |
| Race | 7 classes | 77.5% (macro-F1 76.2) |
Benchmarked head-to-head against FairFace, DeepFace, InsightFace, CLIP and MiVOLO v2 on two test sets β a standard face-dataset partition and 2,000 human-annotated photographs. It leads on age and race in both, and matches the best model on gender.
These models estimate how a face is perceived, not what a person is. Use them for aggregate measurement across image sets, not for decisions about individuals.
Quick start
pip install torch transformers huggingface_hub pillow insightface onnxruntime-gpu ultralytics
from predict import DemographicPredictor
p = DemographicPredictor()
p.predict("photo.jpg")
{'age': 34.2, 'gender': 'Female', 'race': 'Latino_Hispanic',
'race_four': 'Hispanic', 'face_found': True, 'detector': 'insightface'}
results = p.predict_batch(["a.jpg", "b.jpg", "c.jpg"])
predict.py handles face detection and cropping β see Preprocessing.
Loading a single model directly
from transformers import AutoImageProcessor, AutoModelForImageClassification
REPO = "Tijmen/age-gender-race-prediction"
proc = AutoImageProcessor.from_pretrained(REPO, subfolder="race")
model = AutoModelForImageClassification.from_pretrained(REPO, subfolder="race")
# subfolder: "age" (regression, 1 output) | "gender" (2 classes) | "race" (7 classes)
Performance
Held out from the UTKFace + FairFace training corpus. Age is evaluated on UTKFace, those being exact chronological ages rather than bands.
| Task | n | Metric | Value |
|---|---|---|---|
| Age | 3,762 | MAE | 4.66 years |
| RMSE | 6.59 | ||
| within Β±5 years | 65.2% | ||
| within Β±10 years | 88.8% | ||
| Gender | 3,802 | accuracy | 97.32% |
| macro-F1 | 97.30% | ||
| Race | 23,301 | accuracy | 77.50% |
| macro-F1 | 76.24% |
Race is strongest on Black (F1 89.7) and White (85.2), weakest on Latino_Hispanic (61.0) and Southeast Asian (66.5). Age error concentrates between 35 and 64; the extremes are accurate.
Race classes
White Β· Black Β· Indian Β· East Asian Β· Southeast Asian Β· Middle Eastern Β· Latino_Hispanic
predict.py also returns race_four, a census-comparable collapse (Middle Eastern β White, matching the US Census RACHSING recode; Indian and both Asian classes β Asian). The 7-class output is the model; the collapse is a convenience you can ignore or redefine.
Comparison with other models
1. Face-dataset partition β UTKFace test split
Every model applied out of the box to the same held-out images.
| Model | Age MAE β | within Β±5 yr | Gender acc β |
|---|---|---|---|
| This model | 4.66 | 65.2% | 97.32% |
| MiVOLO v2 | 5.84 | 57.4% | β |
| CLIP (zero-shot) | 8.86 | 41.6% | 97.32% |
| InsightFace | 10.05 | 36.7% | 91.51% |
| FairFace (ResNet-34) | 12.37 | 32.5% | 78.38% |
| DeepFace | 13.30 | 29.7% | 69.94% |
n = 3,762 (age) / 3,802 (gender). Gender is an exact tie with CLIP; every other gap is reliable under paired testing (tests and confidence intervals in benchmark/).
Two caveats, stated plainly. These models were fine-tuned on the UTKFace train split, so they have an in-domain advantage on this partition β the ordinary consequence of fine-tuning, but worth knowing. And the off-the-shelf models are applied to UTKFace as distributed, without their own alignment step: FairFace expects dlib-aligned crops and reports ~59.7% band accuracy on its own validation data against 28.2% here, so some of that gap is framing rather than model quality. The comparison below removes both effects.
2. Out-of-domain β 2,000 annotated photographs
1,000 real and 1,000 AI-generated advertising images, each labelled by three human annotators. No model was trained on any of them, and all receive an identical detected face crop. This is the fair head-to-head.
| Model | Race acc β | Race macro-F1 β | Gender acc β | Age MAE β |
|---|---|---|---|---|
| This model | 0.810 | 0.690 | 0.962 | 4.98 |
| MiVOLO v2 | β | β | 0.972 | 5.63 |
| DeepFace | 0.744 | 0.566 | 0.888 | 6.42 |
| InsightFace | β | β | 0.912 | 7.23 |
| FairFace | 0.669 | 0.573 | 0.912 | 7.55 |
| CLIP (zero-shot) | 0.556 | 0.580 | 0.972 | 9.36 |
Race is 4-class here because the annotators used four categories.
- Race β leads by a wide margin on real photographs (0.805 vs 0.666 for DeepFace); on AI-generated images DeepFace is marginally ahead.
- Age β leads, including over MiVOLO v2, the current state of the art for age estimation, which was given its own detector and its face+body dual input.
- Gender β CLIP zero-shot is ahead here, by about one point.
Both tables are measurements taken under controlled conditions across models. Numbers other models report on their own splits are not comparable to these β for instance abhilash88/age-gender-prediction reports MAE 4.5 on UTKFace without specifying the split or preprocessing, so treat age as comparable there and gender as clearly ahead (97.3% vs 94.3%).
Preprocessing
The models expect padded face crops in the UTKFace / FairFace convention. predict.py reproduces it:
- InsightFace
buffalo_lβ keep the largest face,det_score β₯ 0.10 - YOLOv11n-face fallback (
imgsz=1280,conf β₯ 0.10) - Expand the box by 0.35 Γ box size on every side
- No face found β pass the whole image
Framing matters: tightening the margin from 0.35 to 0.25 costs 2.8 points of race accuracy. If you crop faces yourself, use 0.35.
Correcting group counts for classifier error
If you classify a set of images and report group shares, those shares are biased by classifier error β most where accuracy is lowest. benchmark/ ships the confusion matrices to undo it.
import numpy as np, pandas as pd
from huggingface_hub import hf_hub_download
from correction import correct_proportions
M = pd.read_csv(hf_hub_download("Tijmen/age-gender-race-prediction",
"benchmark/confusion_race_real_ipw.csv"), index_col=0).values
p_obs = np.array([0.6494, 0.1889, 0.1552, 0.0065]) # white, black, asian, hispanic
correct_proportions(p_obs, M)
# array([0.6157, 0.2112, 0.1475, 0.0256])
On our corpus this moved the White share of real advertisements from 64.9% to 61.6%, against a census reference of 60.9% β turning an apparent 4-point over-representation into essentially none.
benchmark/ also holds the human labels, per-model metrics and confidence intervals behind every number on this page.
Training
facebook/convnext-base-384-22k-1k fine-tuned on UTKFace in-the-wild (18,806, filtered to White/Black/Indian) plus FairFace 1.25Γ (97,698) β 116,504 images, 80/20 split.
Age uses a regression head with a weighted MSE that trusts UTKFace's exact ages 3Γ over FairFace's bands (each FairFace image was assigned a random age within its band, to stop the head collapsing onto nine values). Race uses class-weighted cross-entropy with moderate augmentation. Learning rate 1e-5, weight decay 0.01, fp16, seed 42, early stopping.
Limitations
- Latino_Hispanic is unreliable β F1 0.61, and worse in every model tested (DeepFace 0.19, CLIP 0.34, FairFace 0.07). Human annotators identified 10.6% Hispanic in advertisements where this model detects 0.65%. Treat Hispanic as a lower bound, or apply the correction above.
- Perceived, not self-identified. Three strangers' judgement of how a face reads.
- Gender is binary, inherited from the training data.
- No separate validation split β checkpoints were selected by early stopping on the reported test split, so these figures are mildly optimistic.
- Identity leakage cannot be excluded β neither source dataset ships identity labels, a limitation shared with all published numbers on them.
- Validated on US imagery; other regions untested.
Licence
Code MIT Β· weights non-commercial research use only (inherited from UTKFace) Β· benchmark labels CC BY 4.0.
Citation
@article{jansen2026demographics,
title = {Census-grounded prompt augmentation reduces demographic
misrepresentation in AI-generated advertising},
author = {Jansen, Tijmen},
year = {2026},
note = {Manuscript in preparation}
}
Related: promptdiv β census-grounded prompt augmentation for text-to-image models.