Ein einfaches Netzwerk trainieren - Musterlösung

  1import torch
  2import torch.nn as nn
  3
  4LR = 0.04  # Lernrate
  5DEVICE = torch.device("cuda" if torch.cuda.is_available() else "cpu")
  6
  7# TODO:
  8# Legen Sie die Trainingsdaten und Labels fest.
  9# Die Trainingsdaten repräsentieren die Eingaben für ein XOR-Problem.
 10# Die Labels repräsentieren die erwarteten Ausgaben für diese Eingaben.
 11# Die Eingaben sind 2D-Punkte, und die Labels sind die erwarteten Klassifikationen.
 12# Die Daten und Labels sollten auf das Gerät `DEVICE` verschoben werden.
 13# Achten Sie darauf, dass die Daten als `torch.float32` und die Labels als `torch.long` definiert sind.
 14training_data = torch.tensor(
 15    [[0.0, 0.0], [0.0, 1.0], [1.0, 0.0], [1.0, 1.0]], dtype=torch.float32, device=DEVICE
 16)
 17labels = torch.tensor([0, 1, 1, 0], dtype=torch.long, device=DEVICE)
 18
 19
 20class SimpleNetwork(nn.Module):
 21    """Ein einfaches neuronales Netzwerk mit einer versteckten Schicht."""
 22
 23    def __init__(self):
 24        """Initialisiert das Netzwerk mit einer versteckten Schicht.
 25
 26        **TODO**:
 27
 28        - Rufen Sie die Methode `super().__init__()` auf, um die Basisklasse zu initialisieren.
 29
 30        - Definieren Sie die erste voll verbundene Schicht `fc1` mit 2 Eingängen und 8 Ausgängen.
 31
 32        - Definieren Sie die zweite voll verbundene Schicht `fc2` mit 8 Eingängen und 2 Ausgängen.
 33        """
 34        # Initialisierung der Basisklasse
 35        super().__init__()
 36
 37        # Definition der voll verbundenen Schichten
 38        # Die erste Schicht hat 2 Eingänge und 8 Ausgänge
 39        self.fc1 = nn.Linear(2, 8)
 40
 41        # Die zweite Schicht hat 8 Eingänge und 2 Ausgänge
 42        # Diese Schicht wird verwendet, um die Klassifikationsergebnisse zu erzeugen
 43        self.fc2 = nn.Linear(8, 2)
 44
 45    def forward(self, x):
 46        """Führt den Vorwärtsdurchlauf des Netzwerks aus.
 47
 48        **TODO**:
 49
 50        - Wenden Sie die erste voll verbundene Schicht `fc1` auf die Eingabe `x` an.
 51
 52        - Wenden Sie die ReLU-Aktivierungsfunktion (`torch.relu <https://docs.pytorch.org/docs/stable/generated/torch.nn.ReLU.html>`_) auf die Ausgabe der ersten Schicht `fc1` an.
 53
 54        - Wenden Sie die zweite voll verbundene Schicht `fc2` auf die Ausgabe der ReLU-Aktivierung an.
 55
 56        - Geben Sie die Ausgabe der zweiten Schicht `fc2` zurück.
 57        """
 58
 59        # Vorwärtsdurchlauf durch die erste Schicht
 60        x = self.fc1(x)
 61
 62        # Aktivierungsfunktion ReLU anwenden
 63        x = torch.relu(x)
 64
 65        # Vorwärtsdurchlauf durch die zweite Schicht
 66        x = self.fc2(x)
 67
 68        # Ausgabe zurückgeben
 69        return x
 70
 71
 72def train_model(model, data, labels, criterion, optimizer, epochs=8000):
 73    """Trainiert das Modell mit den gegebenen Daten und Labels.
 74
 75    Diese Funktion führt das Training des Modells durch, indem sie die Eingabedaten und Labels verwendet,
 76    um die Gewichte des Modells zu aktualisieren. Der Verlust wird in jeder 1000. Epoche ausgegeben.
 77
 78    Parameter:
 79    ----------
 80
 81    model : nn.Module
 82        Das zu trainierende neuronale Netzwerk.
 83
 84    data : torch.Tensor
 85        Die Eingabedaten für das Training.
 86
 87    labels : torch.Tensor
 88        Die zugehörigen Labels für die Eingabedaten.
 89
 90    criterion : nn.Module
 91        Das Kriterium zur Berechnung des Verlusts (z.B. CrossEntropyLoss).
 92
 93    optimizer : torch.optim.Optimizer
 94        Der Optimierer, der verwendet wird, um die Gewichte des Modells zu aktualisieren
 95
 96    epochs : int, optional
 97        Die Anzahl der Epochen, die das Modell trainiert werden soll (Standard: 8000).
 98
 99    **TODO**:
100
101    Iterieren Sie über die Anzahl der Epochen und führen Sie in jeder Epoche die folgenden Schritte aus:
102
103    - Setzen Sie die Gradienten des Optimierers zurück. (`optimizer.zero_grad() <https://pytorch.org/docs/stable/generated/torch.optim.Optimizer.zero_grad.html>`_)
104
105    - Führen Sie einen Vorwärtsdurchlauf des Modells mit den Eingabedaten `data` durch.
106
107    - Berechnen Sie den Verlust zwischen den Modell-Ausgaben und den Labels mit dem Kriterium `criterion`.
108
109    - Führen Sie den Rückwärtsdurchlauf durch, um die Gradienten zu berechnen. (`loss.backward() <https://pytorch.org/docs/stable/generated/torch.Tensor.backward.html>`_)
110
111    - Geben Sie den Verlust alle 1000 Epochen aus.
112
113    - Führen Sie den Optimierungsschritt durch, um die Gewichte des Modells zu aktualisieren. (`optimizer.step() <https://pytorch.org/docs/stable/generated/torch.optim.Optimizer.step.html>`_)
114    """
115    # Training des Modells
116    for epoch in range(epochs):
117        # Gradienten zurücksetzen
118        optimizer.zero_grad()
119
120        # Vorwärtsdurchlauf
121        outputs = model(data)
122
123        # Verlust berechnen und Rückwärtsdurchlauf
124        loss = criterion(outputs, labels)
125
126        # Gradienten berechnen
127        loss.backward()
128
129        # Ausgabe des Verlusts alle 1000 Epochen
130        if epoch % 1000 == 999:
131            print(f"Epoch {epoch+1}, Loss: {loss.item()}")
132
133        # Optimierungsschritt
134        optimizer.step()
135
136
137if __name__ == "__main__":
138    # Initialisierung des Modells, Loss-Kriteriums und Optimierers
139    model = SimpleNetwork().to(DEVICE)
140    criterion = nn.CrossEntropyLoss()
141    optimizer = torch.optim.SGD(model.parameters(), lr=LR)
142
143    # Das Modell trainieren
144    model.train()
145    train_model(model, training_data, labels, criterion, optimizer)
146
147    # Nach dem Training das Modell verwenden
148    model.eval()
149    with torch.no_grad():
150        outputs = model(training_data)
151
152    print("Training complete.")
153    print(outputs)