PyTorch-Beispiel - Bildklassifizierungsprojekt

Die Bildklassifizierung ist eine der grundlegendsten Aufgaben im Bereich Computer Vision. Ihr Ziel ist es, Computer in die Lage zu versetzen, den Hauptinhalt eines Bildes zu erkennen und ihn in vordefinierte Klassen einzuordnen. Zum Beispiel zu erkennen, ob ein Bild eine Katze oder einen Hund enthält.

Anwendung von Deep Learning bei der Bildklassifizierung

Deep-Learning-Modelle, insbesondere Convolutional Neural Networks (CNNs), sind zur Mainstream-Lösung für Bildklassifizierungsaufgaben geworden. Als Deep-Learning-Framework bietet PyTorch eine vollständige Toolchain zum Erstellen und Trainieren von CNN-Modellen.

Überblick über den Projektablauf

Ein vollständiges Bildklassifizierungsprojekt umfasst typischerweise die folgenden Schritte:

  1. Datenvorbereitung und Vorverarbeitung
  2. Modellerstellung
  3. Modelltraining
  4. Modellbewertung
  5. Modellanwendung

Vorbereitung der Umgebung und Laden der Daten

Erforderliche Bibliotheken installieren

# 安装PyTorch和torchvision
!pip install torch torchvision

Gängige Datensätze laden

PyTorchs torchvision bietet mehrere gängige Datensätze wie CIFAR-10, MNIST usw.

Beispiel

import torch
import torchvision
import torchvision.transforms as transforms

# Datentransformationen definieren
transform = transforms.Compose([
    transforms.ToTensor(),  # PIL-Bild in Tensor umwandeln
    transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))  # Normalisierung
])

# CIFAR-10-Trainingsdatensatz laden
trainset = torchvision.datasets.CIFAR10(root='./data', train=True,
                                       download=True, transform=transform)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=4,
                                         shuffle=True, num_workers=2)

# CIFAR-10-Testset laden
testset = torchvision.datasets.CIFAR10(root='./data', train=False,
                                      download=True, transform=transform)
testloader = torch.utils.data.DataLoader(testset, batch_size=4,
                                        shuffle=False, num_workers=2)

# Klassennamen definieren
classes = ('plane', 'car', 'bird', 'cat', 'deer',
           'Hund', 'Frosch', 'Pferd', 'Schiff', 'LKW')

Convolutional Neural Network-Modell erstellen

Grundlegende CNN-Struktur

Ein typisches CNN besteht aus Faltungsschichten, Pooling-Schichten und vollständig verbundenen Schichten.

Beispiel

import torch.nn as nn
import torch.nn.functional as F

class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        # Conv-Schicht 1: Eingabe 3 Kanäle (RGB), Ausgabe 6 Kanäle, 5x5-Kernel
        self.conv1 = nn.Conv2d(3, 6, 5)
        # Pooling-Schicht: 2x2-Fenster, Schrittweite 2
        self.pool = nn.MaxPool2d(2, 2)
        # Conv-Schicht 2: Eingabe 6 Kanäle, Ausgabe 16 Kanäle, 5x5-Kernel
        self.conv2 = nn.Conv2d(6, 16, 5)
        # Vollständig verbundene Schicht 1: Eingabe 16*5*5, Ausgabe 120
        self.fc1 = nn.Linear(16 * 5 * 5, 120)
        # Vollständig verbundene Schicht 2: Eingabe 120, Ausgabe 84
        self.fc2 = nn.Linear(120, 84)
        # Vollständig verbundene Schicht 3: Eingabe 84, Ausgabe 10 (entsprechend 10 Klassen)
        self.fc3 = nn.Linear(84, 10)

    def forward(self, x):
        # Erste Conv-Schicht + ReLU + Pooling
        x = self.pool(F.relu(self.conv1(x)))
        # Zweite Conv-Schicht + ReLU + Pooling
        x = self.pool(F.relu(self.conv2(x)))
        # Feature-Maps abflachen
        x = x.Ansicht(-1, 16 * 5 * 5)
        # Vollständig verbundene Schicht + ReLU
        x = F.relu(self.fc1(x))
        x = F.relu(self.fc2(x))
        # Ausgabeschicht
        x = self.fc3(x)
        return x

# Netzwerk instanziieren
net = Net()

Visualisierung der Modellstruktur


Modell trainieren

Verlustfunktion und Optimierer definieren

Beispiel

import torch.optim as optim

# Kreuzentropie-Verlustfunktion
criterion = nn.CrossEntropyLoss()
# Optimierer für stochastischen Gradientenabstieg
optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)

Trainingsschleife

Beispiel

for epoch in range(10):  # 10 Epochen trainieren
    running_loss = 0.0
    for i, data in enumerate(trainloader, 0):
        # Eingabedaten abrufen
        inputs, labels = data
       
        # Gradienten auf Null setzen
        optimizer.zero_grad()
       
        # Vorwärtspropagierung
        outputs = net(inputs)
        # Verlust berechnen
        loss = criterion(outputs, labels)
        # Backpropagation
        loss.backward()
        # Gewichte aktualisieren
        optimizer.step()
       
        # Statistiken ausgeben
        running_loss += loss.item()
        if i % 2000 == 1999:  # Alle 2000 Mini-Batches ausgeben
            print(f'[{epoch + 1}, {i + 1:5d}] loss: {running_loss / 2000:.3f}')
            running_loss = 0.0

print('Training abgeschlossen')

Modellbewertung

Berechnung der Testset-Genauigkeit

Beispiel

correct = 0
total = 0
with torch.no_grad():  # Keine Gradienten berechnen
    for data in testloader:
        images, labels = data
        outputs = net(images)
        _, predicted = torch.max(outputs.data, 1)
        total += labels.size(0)
        correct += (predicted == labels).sum().item()

print(f'Genauigkeit auf Testbildern: {100 * correct / total:.2f}%')

Genauigkeitsanalyse pro Klasse

Beispiel

class_correct = list(0. for i in range(10))
class_total = list(0. for i in range(10))
with torch.no_grad():
    for data in testloader:
        images, labels = data
        outputs = net(images)
        _, predicted = torch.max(outputs, 1)
        c = (predicted == labels).squeeze()
        for i in range(4):
            label = labels[i]
            class_correct[label] += c[i].item()
            class_total[label] += 1

for i in range(10):
    print(f'Genauigkeit von {classes[i]:5s}: {100 * class_correct[i] / class_total[i]:.2f}%')

Speichern und Laden von Modellen

Trainiertes Modell speichern

Beispiel

# Modellparameter speichern
PATH = './cifar_net.pth'
torch.save(net.state_dict(), PATH)

Modell für Vorhersage laden

Beispiel

# Modell laden
net = Net()
net.load_state_dict(torch.load(PATH))

# Verwende das Modell, um Vorhersagen zu treffen
outputs = net(images)
_, predicted = torch.max(outputs, 1)
print('Vorhergesagt: ', ' '.join(f'{classes[predicted[j]]:5s}' for j in range(4)))
Andere Erweiterungen