Навчання моделей розпізнавання облич: від набору даних до production

Навчання моделей розпізнавання облич: від набору даних до production

Напрямки AI-розробки

Часті запитання

Останні роботи

  • image_website-b2b-advance_0.webp
    Розробка сайту компанії B2B ADVANCE
    1441
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1302
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    998
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1267
  • image_logo-advance_0.webp
    Розробка логотипу компанії B2B Advance
    714
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    1006

Навчання моделей розпізнавання облич: від набору даних до production

Уявіть: ваша компанія зростає, щодня приходять нові співробітники, а система доступу за ключ-картами небезпечна. Ви вирішуєте впровадити розпізнавання облич. Але звичайний Softmax-класифікатор не справляється — він вимагає перенавчання на кожному новому співробітнику. Рішення — навчання кастомної моделі з ArcFace loss, яка вміє узагальнювати на незнайомі identity. Наша команда — AI-інженери з 5+ роками досвіду в computer vision, виконали 30+ проєктів з розпізнавання облич. Гарантуємо точність до 99.5% LFW.

ArcFace — стандарт індустрії: точність 99.5% на LFW, компактні ембендінги, стійкість до шуму. Але щоб отримати таку якість, потрібно правильно налаштувати навчання: вибрати backbone, підібрати margin, обробити набір даних. Нижче — як ми це робимо.

ArcFace loss: математика та реалізація

ArcFace додає адитивний кутовий margin m до кута між embedding та відповідним центром класу:

import torch import torch.nn as nn import torch.nn.functional as F import math class ArcFaceLoss(nn.Module): def __init__( self, embedding_size: int = 512, num_classes: int = 10000, margin: float = 0.5, # кутовий margin в радіанах (~28.6°) scale: float = 64.0 # масштаб логітів ): super().__init__() self.margin = margin self.scale = scale # Навчальні центри класів (нормалізовані) self.weight = nn.Parameter( torch.FloatTensor(num_classes, embedding_size) ) nn.init.xavier_uniform_(self.weight) self.cos_m = math.cos(margin) self.sin_m = math.sin(margin) self.th = math.cos(math.pi - margin) # поріг для числової стабільності self.mm = math.sin(math.pi - margin) * margin def forward( self, embeddings: torch.Tensor, # (B, embedding_size), L2-нормалізовані labels: torch.Tensor # (B,) ) -> torch.Tensor: # L2-нормалізація ваг W = F.normalize(self.weight, dim=1) # cos(θ) = emb · W^T cosine = F.linear(embeddings, W) # (B, num_classes) sine = torch.sqrt(1.0 - cosine.pow(2).clamp(0, 1)) # cos(θ + m) = cos(θ)cos(m) - sin(θ)sin(m) phi = cosine * self.cos_m - sine * self.sin_m # Числова стабільність: якщо θ > π - m, використовуємо косинусний penalty phi = torch.where(cosine > self.th, phi, cosine - self.mm) # One-hot target mask one_hot = torch.zeros_like(cosine) one_hot.scatter_(1, labels.view(-1, 1), 1) # Замінюємо logit лише для правильного класу output = one_hot * phi + (1.0 - one_hot) * cosine output *= self.scale return F.cross_entropy(output, labels) 

Backbone та embedding: який обрати?

InsightFace / ArcFace зазвичай використовує ResNet-50/100 або IResNet. Для production на мобільних пристроях — MobileFaceNet:

import timm def build_face_recognition_model( backbone: str = 'resnet50', # 'resnet100', 'mobilenetv3_small' embedding_size: int = 512, pretrained: bool = True ) -> nn.Module: class FaceEmbedder(nn.Module): def __init__(self): super().__init__() self.backbone = timm.create_model( backbone, pretrained=pretrained, num_classes=0, # прибираємо classifier head global_pool='avg' ) feat_dim = self.backbone.num_features self.bn = nn.BatchNorm1d(feat_dim) self.drop = nn.Dropout(p=0.4) self.fc = nn.Linear(feat_dim, embedding_size, bias=False) self.bn2 = nn.BatchNorm1d(embedding_size) def forward(self, x: torch.Tensor) -> torch.Tensor: feat = self.backbone(x) feat = self.bn(feat) feat = self.drop(feat) emb = self.fc(feat) emb = self.bn2(emb) return F.normalize(emb, dim=1) # L2-нормалізація return FaceEmbedder() 

Як вибрати threshold для open-set recognition?

У production система зустрічає нових людей, яких не було в train. Використовуємо cosine similarity threshold:

import numpy as np from scipy.spatial.distance import cosine class FaceRecognitionSystem: def __init__( self, model: nn.Module, threshold: float = 0.4 # cosine distance; підбирається за ROC ): self.model = model.eval() self.threshold = threshold self.gallery: dict[str, np.ndarray] = {} # id → embedding def enroll(self, person_id: str, face_image: torch.Tensor) -> None: """Реєстрація нового обличчя в галереї""" with torch.no_grad(): emb = self.model(face_image.unsqueeze(0)) self.gallery[person_id] = emb.cpu().numpy().squeeze() def identify( self, face_image: torch.Tensor, top_k: int = 1 ) -> list[dict]: """Пошук по галереї — 1:N ідентифікація""" with torch.no_grad(): query_emb = self.model(face_image.unsqueeze(0)) query_np = query_emb.cpu().numpy().squeeze() distances = { person_id: cosine(query_np, gallery_emb) for person_id, gallery_emb in self.gallery.items() } sorted_matches = sorted(distances.items(), key=lambda x: x[1]) results = [] for person_id, dist in sorted_matches[:top_k]: results.append({ 'identity': person_id if dist < self.threshold else 'unknown', 'distance': float(dist), 'confidence': float(1 - dist) }) return results 

Поріг cosine distance підбирається за ROC-кривою на вашому тесті. Оптимальний threshold — 0.35–0.45 для більшості корпоративних сценаріїв. Ми використовуємо метрику TAR@FAR=0.1% як цільову.

Чому ArcFace — стандарт індустрії?

ArcFace дає компактні кластери без складної добірки триплетів, як у FaceNet. Він стабільно тримає точність навіть на наборах даних із шумом. Детальніше про loss можна прочитати в статті.

Метрики та порівняння методів loss

Метрика Значення Застосування
TAR@FAR=0.1% 98.5%+ Розблокування телефону
TAR@FAR=0.01% 95%+ Фізичний доступ
TAR@FAR=0.001% 90%+ Криміналістика
1:1 Verification AUC > 0.998 Верифікація документів

Порівняння loss-функцій:

Loss LFW Acc IJB-C TAR@FAR=0.1% Складність Застосування
Softmax 98.8% 91.3% Низька Закрите множество
CosFace 99.3% 94.1% Низька Стандарт
ArcFace 99.5% 95.6% Низька Стандарт
AdaFace 99.6% 96.8% Середня Низька якість фото
ElasticFace 99.6% 96.4% Середня Загальний випадок

Процес роботи та терміни

Ми не просто тренуємо модель — ми будуємо завершене рішення. Процес включає етапи:

  1. Аналіз набору даних: оцінка якості, кількості, рекомендації.
  2. Підготовка даних: face alignment, аугментація (flip, rotation, blur), розбиття на train/val/test.
  3. Вибір backbone та loss: під ваш набір даних і залізо — від MobileNet до ResNet-100.
  4. Навчання: balance-семплінг, моніторинг через Weights & Biases.
  5. Валідація: TAR@FAR на вашому тесті, ROC-аналіз.
  6. Квантування та експорт: INT8/FP16 для edge, ONNX для CPU.
  7. Розгортання: Docker + Triton/ONNX, REST/gRPC API, документація.
Етап Результат
Аналіз набору даних Звіт: якість, кількість, рекомендації
Підготовка даних Face alignment, аугментація, спліт
Навчання моделі Вибір loss, backbone, hyperparams
Валідація TAR@FAR на вашому тесті
Розгортання Docker + Triton/ONNX, REST API
Документація API docs, інструкція з експлуатації
Підтримка 3 місяці гарантійного супроводу

Що входить у роботу?

У результат входить:

  • Навчена модель з обраним backbone та loss (ArcFace за замовчуванням).
  • Документація API, інструкція з розгортання.
  • Docker-образ з моделлю та скриптами тестування.
  • 3 місяці гарантійної підтримки та оновлень.

Терміни:

  • Fine-tuning ArcFace на корпоративні дані — 3–5 тижнів.
  • Повна система 1:N з галереєю — 5–8 тижнів.
  • Кастомний пайплайн (detection + alignment + recognition) — 8–14 тижнів.

Вартість навчання розраховується під ваш набір даних та вимоги. Замовте консультацію — ми оцінимо проєкт за 1 день. Зв'яжіться з нами, щоб обговорити деталі.

Типові помилки при навчанні моделей розпізнавання облич

  • Використовувати Softmax на open-set задачі — точність падає на 5–10%.
  • Не робити L2-нормалізацію embedding — metric learning не сходиться.
  • Забувати про face alignment — без нього точність падає на 3–5%.
  • Ставити надто низький threshold — лавина false positives.

Якщо хочете отримати консультацію по вашому набору даних, зв'яжіться з нами. Замовте навчання моделі розпізнавання облич — ми оцінимо проєкт за 1 день.