Комп'ютерний зір з PyTorch у 2026: CNN, Transfer Learning та питання для співбесід

Повний посібник з комп'ютерного зору на PyTorch. Вивчіть згорткові нейронні мережі CNN, технологію transfer learning та підготуйтеся до технічних співбесід.

Комп'ютерний зір з PyTorch - згорткові нейронні мережі та transfer learning

Комп'ютерний зір є одним з найбільш динамічно розвиваючихся напрямків машинного навчання. У 2026 році PyTorch залишається провідним фреймворком для побудови моделей обробки зображень, пропонуючи інтуїтивний API та потужні інструменти для тренування нейронних мереж.

Перед початком роботи з цим посібником корисно мати базові знання Python та концепцій глибокого навчання. Приклади коду протестовано з PyTorch 2.5 та torchvision 0.20.

Вступ до Згорткових Нейронних Мереж (CNN)

Згорткові нейронні мережі (Convolutional Neural Networks) становлять основу сучасного комп'ютерного зору. Архітектура CNN спеціально розроблена для обробки даних зі сітковою структурою, таких як зображення. Ключовим елементом є згортковий шар, який застосовує фільтри для виявлення локальних патернів.

Базова структура CNN складається з трьох основних типів шарів:

  • Згорткові шари - виявляють локальні ознаки шляхом переміщення фільтрів по зображенню
  • Шари пулінгу - зменшують розмірність, зберігаючи найважливішу інформацію
  • Повнозв'язні шари - виконують фінальну класифікацію на основі витягнутих ознак
python
import torch
import torch.nn as nn
import torch.nn.functional as F

class SimpleCNN(nn.Module):
    def __init__(self, num_classes=10):
        super(SimpleCNN, self).__init__()
        self.conv1 = nn.Conv2d(3, 32, kernel_size=3, padding=1)
        self.bn1 = nn.BatchNorm2d(32)
        self.conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
        self.bn2 = nn.BatchNorm2d(64)
        self.conv3 = nn.Conv2d(64, 128, kernel_size=3, padding=1)
        self.bn3 = nn.BatchNorm2d(128)
        self.pool = nn.MaxPool2d(2, 2)
        self.fc1 = nn.Linear(128 * 4 * 4, 512)
        self.fc2 = nn.Linear(512, num_classes)
        self.dropout = nn.Dropout(0.5)
    
    def forward(self, x):
        x = self.pool(F.relu(self.bn1(self.conv1(x))))
        x = self.pool(F.relu(self.bn2(self.conv2(x))))
        x = self.pool(F.relu(self.bn3(self.conv3(x))))
        x = x.view(-1, 128 * 4 * 4)
        x = self.dropout(F.relu(self.fc1(x)))
        x = self.fc2(x)
        return x

Наведений код визначає просту мережу CNN з трьома згортковими шарами, batch-нормалізацією та шарами пулінгу. Ця архітектура підходить для класифікації зображень розміром 32x32 пікселів.

Підготовка Даних з torchvision

Правильна підготовка даних має критичне значення для успіху моделі. Бібліотека torchvision надає інструменти для завантаження популярних наборів даних та виконання аугментації.

python
import torchvision
import torchvision.transforms as transforms
from torch.utils.data import DataLoader

# Визначення трансформацій для тренувальних даних
train_transform = transforms.Compose([
    transforms.RandomCrop(32, padding=4),
    transforms.RandomHorizontalFlip(),
    transforms.RandomRotation(15),
    transforms.ColorJitter(brightness=0.2, contrast=0.2, saturation=0.2),
    transforms.ToTensor(),
    transforms.Normalize((0.4914, 0.4822, 0.4465), (0.2023, 0.1994, 0.2010))
])

# Трансформації для тестових даних (без аугментації)
test_transform = transforms.Compose([
    transforms.ToTensor(),
    transforms.Normalize((0.4914, 0.4822, 0.4465), (0.2023, 0.1994, 0.2010))
])

# Завантаження набору даних CIFAR-10
train_dataset = torchvision.datasets.CIFAR10(
    root='./data', train=True, download=True, transform=train_transform
)
test_dataset = torchvision.datasets.CIFAR10(
    root='./data', train=False, download=True, transform=test_transform
)

train_loader = DataLoader(train_dataset, batch_size=128, shuffle=True, num_workers=4)
test_loader = DataLoader(test_dataset, batch_size=128, shuffle=False, num_workers=4)

Аугментація даних допомагає запобігти перенавчанню (overfitting) шляхом штучного збільшення різноманітності тренувального набору. Кожне зображення може бути випадково обрізане, повернуте або модифіковане за яскравістю.

Transfer Learning з Попередньо Навченими Моделями

Transfer learning дозволяє використовувати знання, отримані моделями, навченими на великих наборах даних, таких як ImageNet. Це особливо цінно при обмеженій кількості тренувальних даних.

python
import torchvision.models as models

def create_transfer_model(num_classes, freeze_backbone=True):
    # Завантаження попередньо навченого ResNet50
    model = models.resnet50(weights=models.ResNet50_Weights.IMAGENET1K_V2)
    
    # Заморожування шарів backbone (опціонально)
    if freeze_backbone:
        for param in model.parameters():
            param.requires_grad = False
    
    # Заміна класифікаційного шару
    num_features = model.fc.in_features
    model.fc = nn.Sequential(
        nn.Linear(num_features, 512),
        nn.ReLU(),
        nn.Dropout(0.3),
        nn.Linear(512, num_classes)
    )
    
    return model

# Створення моделі для 10 класів
model = create_transfer_model(num_classes=10, freeze_backbone=True)

Підхід із замороженим backbone корисний, коли набір даних малий. У цьому випадку тренуються лише нові класифікаційні шари, що прискорює процес та зменшує ризик перенавчання.

Цикл Тренування та Валідація

Реалізація ефективного циклу тренування вимагає врахування багатьох аспектів: оптимізатора, розкладу learning rate та моніторингу метрик.

python
import torch.optim as optim
from torch.optim.lr_scheduler import CosineAnnealingLR
from tqdm import tqdm

def train_model(model, train_loader, test_loader, epochs=50, device='cuda'):
    model = model.to(device)
    criterion = nn.CrossEntropyLoss()
    optimizer = optim.AdamW(model.parameters(), lr=0.001, weight_decay=0.01)
    scheduler = CosineAnnealingLR(optimizer, T_max=epochs)
    
    best_accuracy = 0.0
    
    for epoch in range(epochs):
        # Фаза тренування
        model.train()
        running_loss = 0.0
        correct = 0
        total = 0
        
        for images, labels in tqdm(train_loader, desc=f'Epoch {epoch+1}/{epochs}'):
            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()
        
        train_accuracy = 100. * correct / total
        
        # Фаза валідації
        model.eval()
        test_correct = 0
        test_total = 0
        
        with torch.no_grad():
            for images, labels in test_loader:
                images, labels = images.to(device), labels.to(device)
                outputs = model(images)
                _, predicted = outputs.max(1)
                test_total += labels.size(0)
                test_correct += predicted.eq(labels).sum().item()
        
        test_accuracy = 100. * test_correct / test_total
        scheduler.step()
        
        print(f'Epoch {epoch+1}: Train Acc: {train_accuracy:.2f}%, Test Acc: {test_accuracy:.2f}%')
        
        if test_accuracy > best_accuracy:
            best_accuracy = test_accuracy
            torch.save(model.state_dict(), 'best_model.pth')
    
    return best_accuracy

Розклад CosineAnnealingLR поступово зменшує learning rate, що допомагає досягти кращої збіжності. Збереження найкращої моделі гарантує збереження оптимальних ваг.

Просунуті Техніки: Attention та Feature Pyramid

Сучасні архітектури CNN часто використовують механізми attention та пірамідальні структури для кращого захоплення просторових залежностей.

python
class ChannelAttention(nn.Module):
    def __init__(self, channels, reduction=16):
        super(ChannelAttention, self).__init__()
        self.avg_pool = nn.AdaptiveAvgPool2d(1)
        self.max_pool = nn.AdaptiveMaxPool2d(1)
        self.fc = nn.Sequential(
            nn.Linear(channels, channels // reduction, bias=False),
            nn.ReLU(),
            nn.Linear(channels // reduction, channels, bias=False)
        )
        self.sigmoid = nn.Sigmoid()
    
    def forward(self, x):
        b, c, _, _ = x.size()
        avg_out = self.fc(self.avg_pool(x).view(b, c))
        max_out = self.fc(self.max_pool(x).view(b, c))
        attention = self.sigmoid(avg_out + max_out).view(b, c, 1, 1)
        return x * attention

class SpatialAttention(nn.Module):
    def __init__(self, kernel_size=7):
        super(SpatialAttention, self).__init__()
        self.conv = nn.Conv2d(2, 1, kernel_size, padding=kernel_size//2, bias=False)
        self.sigmoid = nn.Sigmoid()
    
    def forward(self, x):
        avg_out = torch.mean(x, dim=1, keepdim=True)
        max_out, _ = torch.max(x, dim=1, keepdim=True)
        attention = self.sigmoid(self.conv(torch.cat([avg_out, max_out], dim=1)))
        return x * attention

Механізми attention дозволяють мережі фокусуватися на найбільш релевантних регіонах зображення, що покращує точність класифікації при мінімальному збільшенні обчислювальної складності.

Оцінка та Візуалізація Результатів

Візуалізація результатів допомагає зрозуміти поведінку моделі та ідентифікувати потенційні проблеми.

python
import matplotlib.pyplot as plt
import numpy as np
from sklearn.metrics import confusion_matrix, classification_report
import seaborn as sns

def evaluate_model(model, test_loader, class_names, device='cuda'):
    model.eval()
    all_predictions = []
    all_labels = []
    
    with torch.no_grad():
        for images, labels in test_loader:
            images = images.to(device)
            outputs = model(images)
            _, predicted = outputs.max(1)
            all_predictions.extend(predicted.cpu().numpy())
            all_labels.extend(labels.numpy())
    
    # Матриця плутанини
    cm = confusion_matrix(all_labels, all_predictions)
    plt.figure(figsize=(10, 8))
    sns.heatmap(cm, annot=True, fmt='d', cmap='Blues',
                xticklabels=class_names, yticklabels=class_names)
    plt.xlabel('Передбачення')
    plt.ylabel('Справжня мітка')
    plt.title('Матриця плутанини')
    plt.tight_layout()
    plt.savefig('confusion_matrix.png', dpi=150)
    
    # Звіт класифікації
    print(classification_report(all_labels, all_predictions, target_names=class_names))

Готовий до співбесід з Data Science & ML?

Практикуйся з нашими інтерактивними симуляторами, flashcards та технічними тестами.

Питання для Співбесід з Комп'ютерного Зору

Під час технічних співбесід на позиції, пов'язані з машинним навчанням, часто виникають питання про комп'ютерний зір. Нижче представлено найважливіші теми з відповідями.

Питання 1: Чим відрізняється згортка від пулінгу?

Згортка застосовує навчені фільтри для виявлення ознак, тоді як пулінг зменшує розмірність шляхом агрегації значень (максимум або середнє) без параметрів для навчання. Згортка зберігає або збільшує кількість каналів, пулінг зменшує просторову роздільну здатність.

Питання 2: Навіщо використовується batch-нормалізація?

Batch-нормалізація стабілізує процес навчання шляхом нормалізації активацій кожного шару. Переваги включають: швидшу збіжність, можливість використання вищих learning rate, регуляризацію (зменшення перенавчання) та зниження чутливості до ініціалізації ваг.

Питання 3: Як працює transfer learning?

Transfer learning використовує знання з моделі, попередньо навченої на великому наборі даних (наприклад, ImageNet), для нового завдання. Нижні шари CNN виявляють універсальні ознаки (краї, текстури), корисні для різних завдань. Верхні шари адаптуються до специфіки нової проблеми.

Питання 4: Що таке receptive field?

Receptive field — це область вхідного зображення, яка впливає на значення одного нейрона в певному шарі. Глибші шари мають більший receptive field, що дозволяє їм виявляти більш глобальні патерни.

Питання 5: Як працювати з незбалансованими класами?

Стратегії включають: зважування функції втрат (weighted cross-entropy), oversampling міноритарного класу, undersampling мажоритарного класу, аугментацію даних для недопредставлених класів та техніки на кшталт focal loss.

python
# Приклад зваженої функції втрат
class_weights = torch.tensor([1.0, 2.5, 1.0, 3.0, 1.5, 1.0, 2.0, 1.0, 1.5, 1.0])
criterion = nn.CrossEntropyLoss(weight=class_weights.to(device))

Питання 6: Поясніть різницю між stride та padding

Stride визначає крок переміщення фільтра — більший stride зменшує вихідні розміри. Padding додає значення (зазвичай нулі) навколо зображення — дозволяє зберегти просторові розміри та краще обробляти крайові пікселі.

Питання 7: Що таке аугментація даних і чому вона важлива?

Аугментація даних — це техніка штучного збільшення тренувального набору шляхом застосування трансформацій (обертання, зсуви, зміни яскравості). Допомагає в узагальненні моделі та зменшує перенавчання, особливо при малих наборах даних.

Оптимізація Продуктивності та Розгортання

Підготовка моделі до продакшн-розгортання вимагає оптимізації як за швидкістю, так і за розміром.

python
import torch.quantization

def optimize_for_inference(model, example_input):
    model.eval()
    
    # Конвертація в TorchScript
    scripted_model = torch.jit.trace(model, example_input)
    scripted_model.save('model_scripted.pt')
    
    # Динамічна квантизація
    quantized_model = torch.quantization.quantize_dynamic(
        model, {nn.Linear}, dtype=torch.qint8
    )
    
    return scripted_model, quantized_model

# Приклад використання
example = torch.randn(1, 3, 224, 224)
scripted, quantized = optimize_for_inference(model.cpu(), example)

Квантизація може зменшити розмір моделі до чотирьох разів при мінімальній втраті точності. TorchScript дозволяє запускати моделі без інтерпретатора Python.

Висновок

Комп'ютерний зір з PyTorch у 2026 році пропонує потужні інструменти для побудови систем класифікації зображень. Ключові елементи успіху — розуміння архітектури CNN, ефективне використання transfer learning та правильна підготовка тренувальних даних.

Опанування представлених концепцій — від базових згорткових мереж до просунутих механізмів attention — становить міцну основу як для реалізації продакшн-проектів, так і для технічних співбесід у галузі машинного навчання.

Регулярна практика з різними наборами даних та експериментування з архітектурами допоможуть глибше зрозуміти ці теми та підготуватися до викликів комп'ютерного зору в реальних застосуваннях.

Anthony Fillion-Maillet

Автор:

Anthony Fillion-Maillet

Fullstack-розробник, засновник SharpSkill

Fullstack-розробник понад 10 років. Керує SharpSkill і відповідає за все, що тут публікується.

Оновлено 14 серпня 2026 р.

Теги

#pytorch
#computer-vision
#cnn
#transfer-learning
#deep-learning

Поділитися

Пов'язані статті