Головна▸Статті▸Комп'ютерний зір

Класифікація зображень

Продакшн класифікація зображень - CNN архітектури, transfer learning, data augmentation та патерни деплойменту для візуального розпізнавання.

mysimulator teamОновлено 2026-01≈ 6 хв читання▶ Open the simulation

Класифікація зображень присвоює мітки зображенням - це кіт чи собака, дефект чи ні, пухлина чи здорова тканина. Deep learning революціонізував цю сферу, а transfer learning робить її доступною без масивних датасетів. Продакшн-системи мають обробляти реальну варіативність зображень, ефективно масштабуватись та gracefully обробляти помилки.

Де це використовується

Класифікація зображень забезпечує візуальне розпізнавання в різних галузях:

Продукти: Google Photos, Pinterest Lens, медичні діагностичні інструменти, промислові інспекційні системи.

Типові дані

Аспект Типові значення
Тренувальні зображення 1K-10M
Розмір зображення 224x224 - 512x512
Класи 2-1000+
Class imbalance Часто 10:1 - 100:1
Якість міток Варіативна, часто шумна

Джерела даних: - Розмічені датасети зображень - Web-scraped зображення - Production дані з мітками - Синтетичні дані та аугментація - Pre-labeled датасети (ImageNet, COCO)

Що ви робите на практиці

  1. Визначте класи - Які категорії потрібно розрізняти?
  2. Зберіть та розмітьте дані - Якісні мітки критичні
  3. Preprocessing зображень - Resize, normalize, обробка форматів
  4. Застосуйте аугментацію - Збільшіть ефективний розмір датасету
  5. Оберіть архітектуру - Transfer learning vs кастомна
  6. Натренуйте модель - Fine-tune або з нуля
  7. Ретельно оцініть - Per-class метрики, error analysis
  8. Оптимізуйте для деплою - Quantization, pruning, ONNX
  9. Деплойте з моніторингом - Latency, розподіл confidence
  10. Обробіть edge cases - Out-of-distribution, adversarial

Спочатку бейзлайн

Почніть з pre-trained моделі та простого fine-tuning:

import torch
import torchvision.models as models
from torchvision import transforms

# Завантажити pre-trained ResNet
model = models.resnet50(weights='IMAGENET1K_V2')

# Замінити фінальний шар для ваших класів
num_classes = 10
model.fc = torch.nn.Linear(model.fc.in_features, num_classes)

# Заморозити ранні шари для швидшого тренування
for param in model.parameters():
    param.requires_grad = False
for param in model.fc.parameters():
    param.requires_grad = True

# Стандартний preprocessing
preprocess = transforms.Compose([
    transforms.Resize(256),
    transforms.CenterCrop(224),
    transforms.ToTensor(),
    transforms.Normalize(
        mean=[0.485, 0.456, 0.406],
        std=[0.229, 0.224, 0.225]
    )
])

Чому transfer learning бейзлайн: - Працює добре з обмеженими даними (сотні зображень) - Швидко тренувати (хвилини-години) - State-of-the-art фічі з ImageNet - Легко ітерувати та покращувати

Вибір архітектури

Архітектура Розмір Точність Швидкість Use Case
MobileNetV3 5-20MB Добра Дуже швидка Mobile, edge
EfficientNet-B0 20MB Дуже добра Швидка Збалансований
ResNet-50 98MB Добра Середня Загального призначення
ConvNeXt 350MB Відмінна Повільна Максимальна точність
ViT 300MB+ Відмінна Повільна Великі датасети

Критерії вибору: - Ціль деплою (сервер, mobile, edge) - Вимоги до latency - Розмір датасету - Вимоги до точності

Приклад з EfficientNet:

from torchvision.models import efficientnet_b0, EfficientNet_B0_Weights

# Завантажити з останніми вагами
weights = EfficientNet_B0_Weights.IMAGENET1K_V1
model = efficientnet_b0(weights=weights)

# Модифікувати classifier
model.classifier[1] = torch.nn.Linear(1280, num_classes)

Data Augmentation

Аугментація критична для генералізації:

from torchvision import transforms
import albumentations as A

# Базова аугментація
train_transform = transforms.Compose([
    transforms.RandomResizedCrop(224, scale=(0.8, 1.0)),
    transforms.RandomHorizontalFlip(),
    transforms.ColorJitter(brightness=0.2, contrast=0.2, saturation=0.2),
    transforms.RandomRotation(15),
    transforms.ToTensor(),
    transforms.Normalize(mean=[0.485, 0.456, 0.406],
                         std=[0.229, 0.224, 0.225])
])

# Просунута аугментація з Albumentations
train_transform_albu = A.Compose([
    A.RandomResizedCrop(224, 224, scale=(0.8, 1.0)),
    A.HorizontalFlip(p=0.5),
    A.ShiftScaleRotate(shift_limit=0.1, scale_limit=0.1, rotate_limit=15),
    A.OneOf([
        A.GaussNoise(var_limit=(10, 50)),
        A.GaussianBlur(blur_limit=3),
        A.MotionBlur(blur_limit=3),
    ], p=0.3),
    A.ColorJitter(brightness=0.2, contrast=0.2, saturation=0.2, hue=0.1),
    A.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),
    A.pytorch.ToTensorV2()
])

Стратегії аугментації по доменах:

Домен Корисні аугментації
Природні зображення Flip, crop, color jitter, rotation
Медичні Rotation, elastic deform, intensity shift
Виробництво Зміни освітлення, перспектива, шум
Документи Легка ротація, blur, контраст

Training Pipeline

import torch
from torch.utils.data import DataLoader
from tqdm import tqdm

def train_epoch(model, dataloader, criterion, optimizer, device):
    model.train()
    running_loss = 0.0
    correct = 0
    total = 0

    for images, labels in tqdm(dataloader):
        images, labels = images.to(device), labels.to(device)

        optimizer.zero_grad()
        outputs = model(images)
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()

        running_loss += loss.item()
        _, predicted = outputs.max(1)
        total += labels.size(0)
        correct += predicted.eq(labels).sum().item()

    return running_loss / len(dataloader), correct / total

# Training loop зі scheduler
optimizer = torch.optim.AdamW(model.parameters(), lr=1e-4, weight_decay=0.01)
scheduler = torch.optim.lr_scheduler.CosineAnnealingLR(optimizer, T_max=epochs)
criterion = torch.nn.CrossEntropyLoss(label_smoothing=0.1)

for epoch in range(epochs):
    train_loss, train_acc = train_epoch(model, train_loader, 
                                         criterion, optimizer, device)
    val_loss, val_acc = evaluate(model, val_loader, criterion, device)
    scheduler.step()

    print(f"Epoch {epoch}: Train {train_acc:.3f}, Val {val_acc:.3f}")

Оцінка та метрики

Метрика Що вимірює Коли використовувати
Accuracy Загальна коректність Збалансовані класи
Per-class Accuracy Продуктивність по класах Imbalanced дані
Confusion Matrix Патерни помилок Розуміння failures
Top-5 Accuracy Правильно в топ 5 передбаченнях Багато класів
AUC-ROC Якість ранжування Бінарні проблеми

Комплексна оцінка:

from sklearn.metrics import classification_report, confusion_matrix
import seaborn as sns

def evaluate_model(model, dataloader, class_names, device):
    model.eval()
    all_preds = []
    all_labels = []
    all_probs = []

    with torch.no_grad():
        for images, labels in dataloader:
            images = images.to(device)
            outputs = model(images)
            probs = torch.softmax(outputs, dim=1)
            _, preds = outputs.max(1)

            all_preds.extend(preds.cpu().numpy())
            all_labels.extend(labels.numpy())
            all_probs.extend(probs.cpu().numpy())

    # Classification report
    print(classification_report(all_labels, all_preds, 
                                target_names=class_names))

    # Confusion matrix
    cm = confusion_matrix(all_labels, all_preds)
    plt.figure(figsize=(10, 8))
    sns.heatmap(cm, annot=True, fmt='d', 
                xticklabels=class_names, yticklabels=class_names)
    plt.xlabel('Predicted')
    plt.ylabel('True')

    return all_preds, all_labels, all_probs

Режими відмов та чеклист налагодження

Чеклист для продакшну

Перед деплоєм: - [ ] Модель протестована на held-out даних що відповідають production - [ ] Per-class performance прийнятний - [ ] Розмір моделі підходить для deployment target - [ ] Latency відповідає вимогам - [ ] Калібрація confidence перевірена - [ ] Edge cases задокументовані

Після деплою: - [ ] Prediction latency моніториться - [ ] Розподіл confidence відстежується - [ ] Low-confidence predictions флагуються - [ ] Періодична валідація accuracy - [ ] Model versioning на місці

Оптимізація для деплою:

import torch
import onnx

# Export в ONNX
dummy_input = torch.randn(1, 3, 224, 224)
torch.onnx.export(
    model, dummy_input, "model.onnx",
    input_names=['image'],
    output_names=['predictions'],
    dynamic_axes={'image': {0: 'batch'}}
)

# Quantization для швидшого inference
model_quantized = torch.quantization.quantize_dynamic(
    model, {torch.nn.Linear}, dtype=torch.qint8
)

Обробка Edge Cases

Thresholding по confidence:

def predict_with_threshold(model, image, threshold=0.8):
    """Передбачення з порогом confidence."""
    model.eval()
    with torch.no_grad():
        output = model(image.unsqueeze(0))
        probs = torch.softmax(output, dim=1)
        max_prob, pred_class = probs.max(1)

        if max_prob.item() < threshold:
            return None, max_prob.item()  # Невпевнений
        return pred_class.item(), max_prob.item()

Out-of-distribution detection: - Моніторити entropy передбачень - Відстежувати відстань від training distribution - Використовувати ensemble disagreement - Реалізувати human review pipeline

Інструменти та стек

Категорія Інструменти
Фреймворки PyTorch, TensorFlow, Keras
Pretrained моделі torchvision, timm, HuggingFace
Аугментація Albumentations, torchvision, imgaug
Розмітка Label Studio, CVAT, Labelbox
Деплоймент ONNX, TensorRT, TorchServe, Triton
Edge TFLite, CoreML, ONNX Runtime

Приклад міні-кейсу

Сценарій: Виробнича компанія потребує виявлення дефектів у зображеннях продуктів (подряпина, вм'ятина, зміна кольору, добре).

Підхід: 1. Дані: 10K розмічених зображень (7K добре, 1K кожного типу дефекту) 2. Бейзлайн: ResNet-50 pretrained, fine-tuned - Accuracy: 89% 3. Аугментація: Ротація, яскравість, шум - Accuracy: 93% 4. Class weights: Обробка imbalance - Recall покращився на 15% 5. Деплоймент: ONNX + TensorRT на edge device

Результати: - Загальна accuracy: 94% - Defect recall: 97% (пріоритет над precision) - Latency: 15ms на edge GPU - False positive rate: 3%

Ключові уроки: - Хороше освітлення критичне - тренували з lighting augmentation - Edge cases потребували перегляду розмітки людиною - Confidence threshold зменшив false alarms у production

Пов'язані сторінки

Додаткове читання

Спробуйте наживо

Дослідіть пов'язану модель на практиці: відкрийте Convolutional Neural Network Simulator і змінюйте параметри під час роботи. Усе лишається у вашому браузері.

▶ Відкрити симуляцію Convolutional Neural Network Simulator

Що ви знайшли?

Додати кроки відтворення (опційно)