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:

  1. InsightFace buffalo_l β€” keep the largest face, det_score β‰₯ 0.10
  2. YOLOv11n-face fallback (imgsz=1280, conf β‰₯ 0.10)
  3. Expand the box by 0.35 Γ— box size on every side
  4. 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.

Built on UTKFace, FairFace and ConvNeXt.

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

Dataset used to train TimmaJ/age-gender-race-prediction