Wizja Komputerowa z PyTorch w 2026: CNN, Transfer Learning i Pytania Rekrutacyjne

Kompleksowy przewodnik po wizji komputerowej z wykorzystaniem PyTorch. Poznaj sieci konwolucyjne CNN, transfer learning oraz przygotuj się do rozmów kwalifikacyjnych z tego zakresu.

Wizja komputerowa z PyTorch - sieci konwolucyjne i transfer learning

Wizja komputerowa stanowi jeden z najbardziej dynamicznie rozwijających się obszarów uczenia maszynowego. W 2026 roku PyTorch pozostaje wiodącym frameworkiem do budowania modeli przetwarzania obrazów, oferując intuicyjne API i potężne narzędzia do trenowania sieci neuronowych.

Przed przystąpieniem do tego przewodnika warto posiadać podstawową znajomość Pythona oraz koncepcji głębokiego uczenia. Przykłady kodu zostały przetestowane z PyTorch 2.5 i torchvision 0.20.

Wprowadzenie do Sieci Konwolucyjnych (CNN)

Sieci konwolucyjne (Convolutional Neural Networks) stanowią fundament nowoczesnej wizji komputerowej. Architektura CNN została zaprojektowana specjalnie do przetwarzania danych o strukturze siatkowej, takich jak obrazy. Kluczowym elementem jest warstwa konwolucyjna, która stosuje filtry do wykrywania wzorców lokalnych.

Podstawowa struktura CNN składa się z trzech głównych typów warstw:

  • Warstwy konwolucyjne - wykrywają cechy lokalne poprzez przesuwanie filtrów po obrazie
  • Warstwy poolingowe - redukują wymiarowość zachowując najważniejsze informacje
  • Warstwy w pełni połączone - wykonują końcową klasyfikację na podstawie wyekstrahowanych cech
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

Powyższy kod definiuje prostą sieć CNN z trzema warstwami konwolucyjnymi, normalizacją batch oraz warstwami poolingowymi. Architektura ta jest odpowiednia do klasyfikacji obrazów o rozmiarze 32x32 pikseli.

Przygotowanie Danych z torchvision

Prawidłowe przygotowanie danych ma kluczowe znaczenie dla sukcesu modelu. Biblioteka torchvision dostarcza narzędzia do ładowania popularnych zbiorów danych oraz wykonywania augmentacji.

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

# Definicja transformacji dla danych treningowych
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))
])

# Transformacje dla danych testowych (bez augmentacji)
test_transform = transforms.Compose([
    transforms.ToTensor(),
    transforms.Normalize((0.4914, 0.4822, 0.4465), (0.2023, 0.1994, 0.2010))
])

# Ładowanie zbioru 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)

Augmentacja danych pomaga w zapobieganiu overfittingowi poprzez sztuczne zwiększanie różnorodności zbioru treningowego. Każdy obraz może być losowo przycinany, obracany czy modyfikowany pod względem jasności.

Transfer Learning z Pretrenowanymi Modelami

Transfer learning pozwala wykorzystać wiedzę zdobytą przez modele trenowane na ogromnych zbiorach danych, takich jak ImageNet. Jest to szczególnie wartościowe, gdy dysponuje się ograniczoną ilością danych treningowych.

python
import torchvision.models as models

def create_transfer_model(num_classes, freeze_backbone=True):
    # Ładowanie pretrenowanego ResNet50
    model = models.resnet50(weights=models.ResNet50_Weights.IMAGENET1K_V2)
    
    # Zamrożenie warstw backbone (opcjonalne)
    if freeze_backbone:
        for param in model.parameters():
            param.requires_grad = False
    
    # Zastąpienie warstwy klasyfikującej
    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

# Utworzenie modelu dla 10 klas
model = create_transfer_model(num_classes=10, freeze_backbone=True)

Podejście z zamrożonym backbone jest przydatne, gdy zbiór danych jest mały. Trenowane są wtedy tylko nowe warstwy klasyfikujące, co przyspiesza proces i zmniejsza ryzyko overfittingu.

Pętla Treningowa i Walidacja

Implementacja efektywnej pętli treningowej wymaga uwzględnienia wielu aspektów: optymalizatora, harmonogramu learning rate oraz monitorowania metryk.

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):
        # Faza treningowa
        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
        
        # Faza walidacyjna
        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

Harmonogram CosineAnnealingLR stopniowo zmniejsza learning rate, co pomaga w osiągnięciu lepszej konwergencji. Zapisywanie najlepszego modelu zapewnia zachowanie optymalnych wag.

Zaawansowane Techniki: Attention i Feature Pyramid

Nowoczesne architektury CNN często wykorzystują mechanizmy attention oraz struktury piramidalne do lepszego wychwytywania zależności przestrzennych.

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

Mechanizmy attention pozwalają sieci skupić się na najbardziej istotnych regionach obrazu, co poprawia dokładność klasyfikacji przy minimalnym wzroście złożoności obliczeniowej.

Ewaluacja i Wizualizacja Wyników

Wizualizacja wyników pomaga w zrozumieniu zachowania modelu i identyfikacji potencjalnych problemów.

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())
    
    # Macierz pomyłek
    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('Predykcja')
    plt.ylabel('Prawdziwa etykieta')
    plt.title('Macierz pomyłek')
    plt.tight_layout()
    plt.savefig('confusion_matrix.png', dpi=150)
    
    # Raport klasyfikacji
    print(classification_report(all_labels, all_predictions, target_names=class_names))

Gotowy na rozmowy o Data Science & ML?

Ćwicz z naszymi interaktywnymi symulatorami, flashcards i testami technicznymi.

Pytania Rekrutacyjne z Wizji Komputerowej

Podczas rozmów kwalifikacyjnych na stanowiska związane z machine learning często pojawiają się pytania dotyczące wizji komputerowej. Poniżej przedstawiono najważniejsze zagadnienia wraz z odpowiedziami.

Pytanie 1: Czym różni się konwolucja od poolingu?

Konwolucja stosuje wyuczalne filtry do wykrywania cech, podczas gdy pooling redukuje wymiarowość poprzez agregację wartości (max lub średnia) bez parametrów do nauki. Konwolucja zachowuje lub zwiększa liczbę kanałów, pooling zmniejsza rozdzielczość przestrzenną.

Pytanie 2: Dlaczego stosuje się normalizację batch?

Normalizacja batch stabilizuje proces uczenia poprzez normalizację aktywacji każdej warstwy. Korzyści obejmują: szybszą konwergencję, możliwość stosowania wyższych learning rate, regularyzację (zmniejszenie overfittingu) oraz redukcję wrażliwości na inicjalizację wag.

Pytanie 3: Jak działa transfer learning?

Transfer learning wykorzystuje wiedzę z modelu pretrenowanego na dużym zbiorze (np. ImageNet) do nowego zadania. Niższe warstwy CNN wykrywają uniwersalne cechy (krawędzie, tekstury), które są przydatne dla różnych zadań. Wyższe warstwy są dostosowywane do specyfiki nowego problemu.

Pytanie 4: Co to jest receptive field?

Receptive field to obszar obrazu wejściowego, który wpływa na wartość pojedynczego neuronu w danej warstwie. Głębsze warstwy mają większe receptive field, co pozwala im wykrywać bardziej globalne wzorce.

Pytanie 5: Jak radzić sobie z niezbalansowanymi klasami?

Strategie obejmują: ważenie funkcji straty (weighted cross-entropy), oversampling klasy mniejszościowej, undersampling klasy większościowej, augmentację danych dla klas niedoreprezentowanych oraz techniki jak focal loss.

python
# Przykład ważonej funkcji straty
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))

Pytanie 6: Wyjaśnij różnicę między stride a padding

Stride określa krok przesunięcia filtra - większy stride zmniejsza wymiary wyjściowe. Padding dodaje wartości (zazwyczaj zera) wokół obrazu - pozwala zachować wymiary przestrzenne i lepiej przetwarzać piksele brzegowe.

Pytanie 7: Co to jest data augmentation i dlaczego jest ważna?

Augmentacja danych to technika sztucznego zwiększania zbioru treningowego poprzez stosowanie transformacji (obroty, przesunięcia, zmiany jasności). Pomaga w generalizacji modelu i zmniejsza overfitting, szczególnie przy małych zbiorach danych.

Optymalizacja Wydajności i Wdrożenie

Przygotowanie modelu do wdrożenia produkcyjnego wymaga optymalizacji zarówno pod kątem szybkości, jak i rozmiaru.

python
import torch.quantization

def optimize_for_inference(model, example_input):
    model.eval()
    
    # Konwersja do TorchScript
    scripted_model = torch.jit.trace(model, example_input)
    scripted_model.save('model_scripted.pt')
    
    # Kwantyzacja dynamiczna
    quantized_model = torch.quantization.quantize_dynamic(
        model, {nn.Linear}, dtype=torch.qint8
    )
    
    return scripted_model, quantized_model

# Przykład użycia
example = torch.randn(1, 3, 224, 224)
scripted, quantized = optimize_for_inference(model.cpu(), example)

Kwantyzacja może zmniejszyć rozmiar modelu nawet czterokrotnie przy minimalnej utracie dokładności. TorchScript pozwala na uruchamianie modeli bez interpretera Pythona.

Podsumowanie

Wizja komputerowa z PyTorch w 2026 roku oferuje potężne narzędzia do budowania systemów klasyfikacji obrazów. Kluczowe elementy sukcesu to zrozumienie architektury CNN, efektywne wykorzystanie transfer learningu oraz właściwe przygotowanie danych treningowych.

Opanowanie przedstawionych koncepcji - od podstawowych sieci konwolucyjnych po zaawansowane mechanizmy attention - stanowi solidną podstawę zarówno do realizacji projektów produkcyjnych, jak i do rozmów rekrutacyjnych w dziedzinie uczenia maszynowego.

Regularna praktyka z różnymi zbiorami danych oraz eksperymentowanie z architekturami pomoże w głębszym zrozumieniu tych zagadnień i przygotowaniu do wyzwań związanych z wizją komputerową w rzeczywistych zastosowaniach.

Anthony Fillion-Maillet

Autor:

Anthony Fillion-Maillet

Programista fullstack, założyciel SharpSkill

Programista fullstack od ponad 10 lat. Prowadzi SharpSkill i odpowiada za wszystko, co się tu ukazuje.

Zaktualizowano 14 sierpnia 2026

Tagi

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

Udostępnij

Powiązane artykuły