Разработка системы определения возраста и пола по лицу
Определение возраста и пола по изображению лица — задача computer vision с применением в retail аналитике (демографический профиль посетителей), системах адаптивного контента, медицинских исследованиях, проверке возраста (age gate). Обе задачи часто реализуются единой мультизадачной моделью.
Мультизадачная архитектура
import torch
import torch.nn as nn
import timm
class AgeGenderModel(nn.Module):
"""Единая модель для одновременного предсказания возраста и пола"""
def __init__(self, pretrained_backbone: str = 'efficientnet_b2'):
super().__init__()
backbone = timm.create_model(pretrained_backbone, pretrained=True, num_classes=0)
self.backbone = backbone
feat_dim = backbone.num_features # 1408 для B2
# Shared representation
self.shared = nn.Sequential(
nn.Linear(feat_dim, 512),
nn.GELU(),
nn.Dropout(0.3)
)
# Отдельные головы для каждой задачи
self.age_head = nn.Linear(512, 1) # регрессия (MAE)
self.gender_head = nn.Linear(512, 2) # классификация (CE)
def forward(self, x):
features = self.backbone(x)
shared = self.shared(features)
age = self.age_head(shared).squeeze()
gender_logits = self.gender_head(shared)
return age, gender_logits
Возраст как регрессия vs классификация: regression даёт непрерывный результат (32.4 года), classification по диапазонам (30–35 лет) менее точна но удобнее для некоторых применений. Распределённая регрессия (DLDL — Distribution Learning) — лучший подход: возраст моделируется как вероятностное распределение, а не точечное значение.
Датасеты
| Датасет | Кол-во фото | Диапазон возраста | Метки |
|---|---|---|---|
| IMDB-Wiki | 524k | 0–100 | Возраст, пол |
| UTKFace | 23k | 0–116 | Возраст, пол, этничность |
| APPA-REAL | 7.6k | 7–77 | Реальный и воспринимаемый возраст |
| FairFace | 108k | 0–70+ | Пол, раса, 9 диапазонов возраста |
| AgeDB | 16k | 0–101 | Возраст, пол |
Предобработка и аугментация
import albumentations as A
from albumentations.pytorch import ToTensorV2
train_transform = A.Compose([
A.Resize(224, 224),
A.HorizontalFlip(p=0.5),
A.RandomBrightnessContrast(brightness_limit=0.3, contrast_limit=0.3, p=0.5),
A.GaussianBlur(blur_limit=(3, 7), p=0.2),
A.CoarseDropout(max_holes=4, max_height=30, max_width=30, p=0.3),
A.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),
ToTensorV2()
])
Функции потерь для мультизадачного обучения
def multitask_loss(age_pred, age_true, gender_logits, gender_true,
age_weight=1.0, gender_weight=0.5):
# MAE для возраста + CE для пола
age_loss = nn.L1Loss()(age_pred, age_true.float())
gender_loss = nn.CrossEntropyLoss()(gender_logits, gender_true)
# Uncertainty weighting (Kendall et al.)
return age_weight * age_loss + gender_weight * gender_loss
Метрики производительности
| Модель | MAE (возраст) | Accuracy (пол) | Скорость |
|---|---|---|---|
| EfficientNet-B2 (IMDB-Wiki FT) | 4.8 лет | 96.3% | 8 ms |
| MobileNetV3 (UTKFace FT) | 5.2 лет | 95.8% | 3 ms |
| ViT-B/16 (IMDB-Wiki FT) | 4.3 лет | 97.1% | 12 ms |
MAE 4–6 лет — типичный результат для «дикой природы» (selfies, фото разного качества). В контролируемых условиях (фронтальный портрет, хорошее освещение) — 3–4 года.
Этика и bias
Модели, обученные на IMDB-Wiki, имеют недопредставление пожилых людей и некоторых этнических групп. FairFace датасет специально сбалансирован для снижения bias. При использовании для принятия решений (age gate) — обязательно тестирование на fairness across demographic groups.
| Задача | Срок |
|---|---|
| Интеграция готовой модели (InsightFace) | 1 неделя |
| Кастомная модель на корпоративных данных | 3–5 недель |
| Система с аналитикой и отчётами | 4–7 недель |







