PyTorch-Verlustfunktionen

Einführung

Verlustfunktionen sind grundlegend für die Trainingsprozesse von maschinellen Lernmodellen und es gibt keinen Weg, um ein Modell dazu zu bringen, korrekte Voraussagen zu treffen, ohne Verlustfunktionen. In einfacheren Worten ist eine Verlustfunktion eine mathematische Funktion oder Ausdruck, der verwendet wird, um zu messen, wie gut ein Modell auf einem bestimmten Datensatz performt. Die Kenntnis der Leistung eines Modells auf einem bestimmten Datensatz gibt dem Entwickler Einblicke, um eine Vielzahl von Entscheidungen während des Trainings zu treffen, wie das Einsatz eines neuen, stärkeren Modells oder sogar die Änderung der Verlustfunktion selbst in eine andere Art. Sprechen wir von den verschiedenen Arten von Verlustfunktionen, so gibt es seit Jahren verschiedene Verlustfunktionen, die für eine bestimmte Trainingsaufgabe entwickelt wurden.

Voraussetzungen

Dieser Artikel erfordert eine Verständnis von neuronalen Netzen. In hoher Genauigkeit sind neuronale Netze aus interagierten Knoten („Neuronen“) organisiert in Schichten. Sie lernen und treffen Voraussagen durch einen Prozess namens „Trainieren“, der die Gewichte und Verzerrungen der Verbindungen zwischen Neuronen justiert. Ein Verständnis von neuronalen Netzen umfasst Kenntnisse ihrer verschiedenen Schichten (Eingabeschicht, versteckte Schichten, Ausgabeschicht), Aktivierungsfunktionen, Optimierungsalgorithmen (Varianten des Gradientenabstiegs) und Verlustfunktionen usw.

Zusätzlich ist die Vertrautheit mit der Python-Syntax und der Bibliothek PyTorch für das Verständnis der in diesem Artikel gezeigten Code-Snippets unerlässlich.

In diesem Artikel werden wir verschiedene Verlustfunktionen untersuchen, die Teil des PyTorch nn-Moduls sind. Wir werden uns darüber hinaus tief in die Arbeitsweise von Verlustfunktionen einarbeiten und eine benutzerdefinierte Verlustfunktion aufbauen, um die von PyTorch für die Verlustfunktionen im Rahmen seiner nn-Modul-API bereitgestellten Funktionalität zu erkunden.

Nun, da wir eine höhere Ebene des Verständnisses für Verlustfunktionen haben, lassen Sie uns in die technischen Details einsteigen, wie Verlustfunktionen funktionieren.

Was sind Verlustfunktionen?

Wir haben zuvor erwähnt, dass Verlustfunktionen uns zeigen, wie gut ein Modell auf einer bestimmten Datenmenge agiert. Technisch gesehen erfassen sie, wie nahe eine vorhergesagte Zahl der tatsächlichen Zahl ist. Wenn unser Modell bei der Vorhersage auf Trainings- und Testdaten sehr nahe an den tatsächlichen Werten liegt, bedeutet das, dass wir ein recht robustes Modell haben.

Obwohl Verlustfunktionen uns wichtige Informationen über das Ergebnis unseres Modells geben, ist dies nicht ihre Hauptfunktion, denn es gibt robustere Methoden, um unsere Modelle zu bewerten, wie z.B. die Genauigkeit und die F-Scores. Die Bedeutung von Verlustfunktionen wird hauptsächlich während des Trainings erkannt, wo wir die Gewichte unseres Modells in Richtung einer Minimierung des Verlustes verschieben. Indem wir dies tun, erhöhen wir die Wahrscheinlichkeit, dass unser Modell korrekte Vorhersagen trifft, was ohne Verlustfunktion wahrscheinlich nicht möglich gewesen wäre.

Unterschiedliche Verlustfunktionen passen zu verschiedenen Problemen, die jeweils von Forschern sorgfältig gestaltet werden, um eine stabile Gradientenflussverteilung während der Trainingsphase zu gewährleisten.

Manchmal kann die mathematische Ausdruck von Verlustfunktionen etwas beunruhigend sein, was dazu geführt hat, dass einige Entwickler sie als schwarze Kisten behandeln. Wir werden später einige der in PyTorch am meisten verwendeten Verlustfunktionen aufdecken, aber vorher lassen Sie uns mal kurz anschauen, wie wir Verlustfunktionen in der PyTorch-Welt verwenden.

Verlustfunktionen in PyTorch

PyTorch verfügt standardmäßig über eine Reihe kanonischer Verlustfunktionen mit einfahren Designmustern, die Entwicklern erlauben, diese verschiedenen Verlustfunktionen sehr schnell während der Trainingsphase zu iterieren. Alle Verlustfunktionen von PyTorch sind in dem nn-Modul verpackt, dem Basisklasse für alle neuronalen Netze in PyTorch. Dies macht es sehr einfach, eine Verlustfunktion in Ihr Projekt hinzuzufügen, indem Sie nur eine einfache Zeile Code hinzufügen. Schauen wir mal, wie man eine Mean Squared Error (MSE) Verlustfunktion in PyTorch hinzufügt.

import torch.nn as nn
MSE_loss_fn = nn.MSELoss()

Die Funktion, die aus dem obigen Code zurückgegeben wird, kann verwendet werden, um abzuschätzen, wie weit ein Vorhersage vom tatsächlichen Wert entfernt ist. Dies kann mit dem folgenden Format erfolgen.

#vorhersagter_wert ist die Vorhersage unseres neuronalen Netzes
#ziel ist der tatsächliche Wert in unserer Datenbank
#verlustwert ist der Verlust zwischen der vorhersagten Wert und dem tatsächlichen Wert
Loss_value = MSE_loss_fn(predicted_value, target)

Nun, da wir einen Überblick über die Nutzung von Verlustfunktionen in PyTorch haben, tauchen wir hierfür in die Hintergründe einiger der von PyTorch angebotenen Verlustfunktionen ein.

Welche Verlustfunktionen stehen in PyTorch zur Verfügung?

Die meisten der von PyTorch mitgelieferten Verlustfunktionen werden in drei Hauptgruppen kategorisiert – Regressionsverlust, Klassifikationsverlust und Rangierverlust.

Regressionsverluste betreffen meist Werte, die zwischen zwei Grenzen beliebige Werte annehmen können. Ein Beispiel hierfür wäre die Berechnung von Hauspreisen in einer Gemeinschaft.

Klassifikationsverlustfunktionen behandeln diskrete Werte, wie z.B. die Aufgabe, ein Objekt als Box, Füllstand oder Flasche zu klassifizieren.

Rangierverluste prognostizieren die relative Distanz zwischen Werten. Ein Beispiel hierfür wäre die Face-Verifikation, wo man erkennen möchte, welche Face-Bilder zu einer bestimmten Person gehören und das kann man durch Rangieren, wer zu und wer nicht zu der ursprünglichen Face-Besitzerin gehört, gemäß ihrer relativen Annäherung an das Ziel-Face-Scan, erkennen.

L1-Verlustfunktion / Mean Absolute Error

Die L1-Verlustfunktion berechnet den arithmetischen Mittelwert der absoluteren Fehler zwischen jedem Wert im vorhergesagten Tensor und dem des Zielwerts. Zuerst berechnet sie die absolute Differenz zwischen jedem Wert im vorhergesagten Tensor und dem des Zielwerts undcomputiert die Summe aller von dieser absoluteren Differenzberechnung zurückgegebenen Werten. Schließlich berechnet sie die Durchschnittsabweichung dieser Summenwerte, um den arithmetischen Mittelwert der absoluteren Fehler (MAE) zu erhalten. Die L1-Verlustfunktion ist sehr robust beim Umgang mit Rauschen.

import torch.nn as nn

#size_average und reduce sind veraltet

#reduction legt fest, wie auf die Ausgabe reduziert werden soll. Mögliche Werte sind 'mean' (Standard), bei dem wir den Durchschnitt der Ausgabe berechnen, 'sum', bei dem die Ausgabe summiert wird, und 'none', bei dem keine Reduzierung auf die Ausgabe angewendet wird

Loss_fn = nn.L1Loss(size_average=None, reduce=None, reduction='mean')

input = torch.randn(3, 5, requires_grad=True)
target = torch.randn(3, 5)
output = loss_fn(input, target)
print(output) #tensor(0.7772, grad_fn=<L1LossBackward>)

Der zurückgegebene Einzelwert ist der berechnete Verlust zwischen zwei Tensoren mit Dimension 3×5.

Quadrierter Fehler

Der Mean Squared Error (MSE) weist mit der Mean Absolute Error (MAE) einige beträchtliche Ähnlichkeiten auf. Im Gegensatz zur MAE, bei der die absolute Differenz zwischen Werten in der Vorhersagetensor und dem Zielwert berechnet wird, berechnet der MSE die quadrierte Differenz zwischen den Werten in der Vorhersagetensor und dem Zieltensor. Dadurch werden relativ große Differenzen stärker bestraft, während relativ kleine Differenzen weniger bestraft werden. Der MSE ist weniger robust gegen Ausreißer und Rauschen als die MAE, allerdings.

import torch.nn as nn

loss = nn.MSELoss(size_average=None, reduce=None, reduction='mean')
#L1 loss function parameters explanation applies here.

input = torch.randn(3, 5, requires_grad=True)
target = torch.randn(3, 5)
output = loss(input, target)
print(output) #tensor(0.9823, grad_fn=<MseLossBackward>)

Cross-Entropy Loss

Der Cross-Entropy Loss wird in Klassifikationsproblemen mit einer Anzahl diskreter Klassen verwendet. Er misst die Differenz zwischen zwei Wahrscheinlichkeitsverteilungen für eine gegebene Menge von zufälligen Variablen. Usualisiert wird der Cross-Entropy Loss verwendet, wenn die Ausgabe unserer Netze eine Softmax-Schicht ist, die sicherstellt, dass die Ausgabe des neuronalen Netzes einen Wert zwischen 0 und 1 hat (Wahrscheinlichkeitswert).

Die Softmax-Schicht besteht aus zwei Teilen – dem Exponenten der Vorhersage für eine bestimmte Klasse.

yi ist die Ausgabe des neuronalen Netzes für eine bestimmte Klasse. Der Ausdruck dieser Funktion ist eine Zahl, die nahe Null ist, aber niemals Null, wenn yi groß und negativ ist, und nahe 1, wenn yi positiv und sehr groß ist.

import numpy as np

np.exp(34) #583461742527454.9
np.exp(-34) #1.713908431542013e-15

Der zweite Teil ist ein Normalisierungswert und dient dazu, dass das Ergebnis der Softmax-Schicht immer eine Wahrscheinlichkeitsgröße ist.

Dies erreicht durch die Summe aller Exponenten für jeden Klassenvariablenwert. Die finale Gleichung der Softmax-Funktion sieht so aus:

]

In PyTorchs nn-Modul kombiniert die Kollaborationsverlustfunktion den Log-Softmax und den negativen Log-Likelihood-Verlust (NLL) in eine einzige Verlustfunktion.

Beachten Sie, wie die Gradientenfunktion in der ausgegebenen Ausgabe ein NLL-Verlust ist. Dies offenbart tatsächlich, dass der Kollaborationsverlust unter der Haube den NLL-Verlust mit einer Log-Softmax-Schicht kombiniert.

Negativer Log-Likelihood (NLL) Verlust

Die NLL-Verlustfunktion arbeitet sehr ähnlich zur Kollaborationsverlustfunktion. Der Kollaborationsverlust kombiniert eine Log-Softmax-Schicht und den NLL-Verlust, um den Wert des Kollaborationsverlustes zu erhalten. Dies bedeutet, dass der NLL-Verlust verwendet werden kann, um den Wert des Kollaborationsverlustes zu erhalten, indem die letzte Schicht des neuronalen Netzes eine Log-Softmax-Schicht anstelle einer normalen Softmax-Schicht ist.

m = nn.LogSoftmax(dim=1)
loss = nn.NLLLoss()
Der Eingabearray hat die Größe N x C = 3 x 5
input = torch.randn(3, 5, requires_grad=True)
Jeder Wert in der Zielmatrix muss zwischen 0 und C liegen
target = torch.tensor([1, 0, 4])
output = loss(m(input), target)
output.backward()
Beispiel für 2D-Verlust (z.B. bei Bildern verwendet)
N, C = 5, 4
loss = nn.NLLLoss()
Der Eingabearray hat die Größe N x C x Höhe x Breite
data = torch.randn(N, 16, 10, 10)
conv = nn.Conv2d(16, C, (3, 3))
m = nn.LogSoftmax(dim=1)
Jeder Wert in der Zielmatrix muss zwischen 0 und C liegen
target = torch.empty(N, 8, 8, dtype=torch.long).random_(0, C)
output = loss(m(conv(data)), target)
print(output) Tensor (1.4892, Gradfunktion=<NllLoss2DBackward>)

Quellcode für NLLLoss — PyTorch 1.9.0 Dokumentation

Binärer Cross-Entropieverlust

Der binäre Cross-Entropieverlust ist eine spezielle Klasse von Cross-Entropieverlusten, die für das spezielle Problem verwendet werden, Datenpunkte in nur zwei Klassen zu klassifizieren. Die Labels für dieses Problem sind normalerweise binär, und daher ist unser Ziel, das Modell zu drängen, eine Zahl nahe null für ein null-Label und eine Zahl nahe eins für ein eins-Label vorherzusagen. Normalerweise verwendet man den BCE-Verlust für binare Klassifizierungen mit einer Sigmoid-Schicht am Ende des neuronalen Netzwerks, um sicherzustellen, dass die Ausgabe entweder eine Zahl nahe null oder eine Zahl nahe eins ist.

import torch.nn as nn

m = nn.Sigmoid()
loss = nn.BCELoss()
input = torch.randn(3, requires_grad=True)
target = torch.empty(3).random_(2)
output = loss(m(input), target)
print(output) Tensor (0.4198, Gradfunktion=<BinaryCrossEntropyBackward>)

Binärer Cross-Entropieverlust mit Logits

Wir haben in der vorhergehenden Abschnitt erwähnt, dass ein binärer Cross-Entropieverlust normalerweise als Sigmoid-Schicht ausgegeben wird, um sicherzustellen, dass das Ergebnis zwischen 0 und 1 liegt. Ein binärer Cross-Entropieverlust mit Logits kombiniert diese beiden Schichten in eine einzige Schicht. Laut der PyTorch-Dokumentation ist dies eine numerisch stabilere Version, da sie die log-sum exp Trick nutzt.

import torch
import torch.nn as nn

target = torch.ones([10, 64], dtype=torch.float32)  # 64 Klassen, Batch-Größe = 10
output = torch.full([10, 64], 1.5)  # Eine Voraussage (Logit)
pos_weight = torch.ones([64])  # Alle Gewichte sind gleich 1
criterion = torch.nn.BCEWithLogitsLoss(pos_weight=pos_weight)
loss = criterion(output, target)  # -log(sigmoid(1.5))
print(loss) #tensor(0.2014)

Glatt L1-Verlust

Die glatte L1-Verlustfunktion kombiniert die Vorteile der MSE-Verlustfunktion und der MAE-Verlustfunktion mittels eines heuristischen Wertes beta. Dieser Kriterium wurde in dem Fast R-CNN-Papier eingeführt. Wenn die absolute Differenz zwischen der ground truth-Wertung und der vorhergesagten Wertung unter beta liegt, nutzt das Kriterium eine quadratische Differenz, was einer MSE-Verlustfunktion entspricht. Die Graphik der MSE-Verlustfunktion ist eine kontinuierliche Kurve, was bedeutet, dass der Gradient bei jedem Verlustwert unterschiedlich ist und überall differentierbar ist. Außerdem nimmt der Gradient mit sinkendem Verlustwert ab, was die Gradientenentwicklung während des Gradientenabstiegs erleichtert. Allerdings explodiert der Gradient bei sehr hohen Verlustwerten, weshalb das Kriterium auf MAE umschaltet, bei dem der Gradient für jeden Verlustwert fast konstant ist, wenn die absolute Differenz größer als beta wird und die potenzielle Gradientenexplosion eliminiert wird.

import torch.nn as nn

loss = nn.SmoothL1Loss()
input = torch.randn(3, 5, requires_grad=True)
target = torch.randn(3, 5)
output = loss(input, target)

print(output) #tensor(0.7838, grad_fn=<SmoothL1LossBackward>)

Hinge Embedding Verlust

Der Hinge-Embedding-Verlust wird hauptsächlich in semi-supervisierter Lernaufgaben zur Messung der Ähnlichkeit zwischen zwei Eingaben verwendet. Er wird verwendet, wenn es ein Eingabenvektor und ein Labelvektor gibt, der Wertungen von 1 oder -1 enthält. Er wird hauptsächlich in Problemen mit nichtlinearen Embeddings und semi-supervisierter Lernung verwendet.

import torch
import torch.nn as nn

input = torch.randn(3, 5, requires_grad=True)
target = torch.randn(3, 5)

hinge_loss = nn.HingeEmbeddingLoss()
output = hinge_loss(input, target)
output.backward()

print('input: ', input)
print('target: ', target)
print('output: ', output)

#input:  Tensor([[ 1.4668e+00,  2.9302e-01, -3.5806e-01,  1.8045e-01,  1.1793e+00],
#       [-6.9471e-05,  9.4336e-01,  8.8339e-01, -1.1010e+00,  1.5904e+00],
#       [-4.7971e-02, -2.7016e-01,  1.5292e+00, -6.0295e-01,  2.3883e+00]],
#       requires_grad=True)
#target:  Tensor([[-0.2386, -1.2860, -0.7707,  1.2827, -0.8612],
#        [ 0.6747,  0.1610,  0.5223, -0.8986,  0.8069],
#        [ 1.0354,  0.0253,  1.0896, -1.0791, -0.0834]])
#output:  Tensor(1.2103, grad_fn=<MeanBackward0>)

Margin Ranking Verlust

Der Margin Ranking Verlust gehört zu den Rangverlustfunktionen, deren Hauptziel es ist, die relative Distanz zwischen einer Sammlung von Eingaben in einer Datenmenge zu messen. Die Margin Ranking Verlustfunktion nimmt zwei Eingaben und ein Label auf, das nur 1 oder -1 enthält. Wenn das Label 1 ist, dann wird angenommen, dass die erste Eingabe eine höhere Rangposition als die zweite Eingabe haben sollte, und wenn das Label -1 ist, dann wird angenommen, dass die zweite Eingabe eine höhere Rangposition als die erste Eingabe haben sollte. Diese Beziehung wird durch die Gleichung und den Code unten dargestellt.

import torch.nn as nn

loss = nn.MarginRankingLoss()
input1 = torch.randn(3, requires_grad=True)
input2 = torch.randn(3, requires_grad=True)
target = torch.randn(3).sign()
output = loss(input1, input2, target)
print('input1: ', input1)
print('input2: ', input2)
print('output: ', output)

#Eingang1: Tensor([-1.1109,  0.1187,  0.9441], requires_grad=True)
#Eingang2: Tensor([ 0.9284, -0.3707, -0.7504], requires_grad=True)
#Ausgaben: Tensor(0.5648, grad_fn=<MeanBackward0>)

Tripel-Margin-Verlust

Dieser Kriterient misst die Ähnlichkeit zwischen Datenpunkten durch die Verwendung von Tripeln aus Trainingsdaten. Die beteiligten Tripel bestehen aus einem Anker-Exemplar, einem Positiv-Exemplar und einem Negativ-Exemplar. Das Ziel ist 1) die Distanz zwischen dem Positiv-Exemplar und dem Anker so minimal wie möglich zu machen und 2) die Distanz zwischen dem Anker und dem Negativ-Exemplar so groß zu machen, dass sie größer als der Marge-Wert plus die Distanz zwischen dem Positiv-Exemplar und dem Anker ist. Normalerweise gehört das Positiv-Exemplar derselben Klasse wie der Anker an, aber das Negativ-Exemplar nicht. Daher versuchen wir mit dieser Verlustfunktion, den Tripel-Margin-Verlust zu nutzen, um ein hohes Ähnlichkeitsverhalten zwischen dem Anker und dem Positiv-Exemplar und ein niedriges Ähnlichkeitsverhalten zwischen dem Anker und dem Negativ-Exemplar vorherzusagen.

import torch.nn as nn

triplet_loss = nn.TripletMarginLoss(margin=1.0, p=2)
anchor = torch.randn(100, 128, requires_grad=True)
positive = torch.randn(100, 128, requires_grad=True)
negative = torch.randn(100, 128, requires_grad=True)
output = triplet_loss(anchor, positive, negative)
print(output)  #Tensor(1.1151, grad_fn=<MeanBackward0>)

Kosinusschablone-Verlust

Winkel嵌入损失 (Cosine Embedding Loss) misst die Verlustfunktion anhand von Eingaben x1, x2 und einer Label-Tensor y, der Werten 1 oder -1 enthält. Es wird verwendet, um die Ähnlichkeit oder Unähnlichkeit zweier Eingaben zu messen.

Das Kriterium misst die Ähnlichkeit indem es den Kosinusschlüsselabstand zwischen den beiden Datenpunkten im Raum berechnet. Der Kosinusschlüsselabstand korreliert mit dem Winkel zwischen den beiden Punkten, was bedeutet, dass der kleinere der Winkel, desto näher sind die Eingaben und desto ähnlicher sind sie.

import torch.nn as nn

loss = nn.CosineEmbeddingLoss()
input1 = torch.randn(3, 6, requires_grad=True)
input2 = torch.randn(3, 6, requires_grad=True)
target = torch.randn(3).sign()
output = loss(input1, input2, target)
print('input1: ', input1)
print('input2: ', input2)
print('output: ', output)

#input1:  tensor([[ 1.2969e-01,  1.9397e+00, -1.7762e+00, -1.2793e-01, #-4.7004e-01,
#         -1.1736e+00],
#        [-3.7807e-02,  4.6385e-03, -9.5373e-01,  8.4614e-01, -1.1113e+00,
#          4.0305e-01],
#        [-1.7561e-01,  8.8705e-01, -5.9533e-02,  1.3153e-03, -6.0306e-01,
#          7.9162e-01]], requires_grad=True)
#input2:  tensor([[-0.6177, -0.0625, -0.7188,  0.0824,  0.3192,  1.0410],
#        [-0.5767,  0.0298, -0.0826,  0.5866,  1.1008,  1.6463],
#        [-0.9608, -0.6449,  1.4022,  1.2211,  0.8248, -1.9933]],
#       requires_grad=True)
#output:  tensor(0.0033, grad_fn=<MeanBackward0>)

Kullback-Leibler-Divergenz-Verlust

Gegeben zwei Verteilungen P und Q, misst die Kullback-Leibler-Divergenz (KL-Divergenz) den Verlust der Information, wenn P (als angenommene wahre Verteilung) durch Q ersetzt wird. Indem gemessen wird, wie viel Information beim Ersatz von P durch Q verloren geht, können wir die Ähnlichkeit zwischen P und Q bestimmen und somit unser Algorithmus lenken, um eine Verteilung sehr nahe der wahren Verteilung P zu erzeugen. Der Informationseinsatz, wenn Q verwendet wird, um P zu approximieren, ist unterschiedlich von dem, wenn P verwendet wird, um Q zu approximieren, weshalb die KL-Divergenz nicht symmetrisch ist.

import torch.nn as nn

loss = nn.KLDivLoss(size_average=None, reduce=None, reduction='mean', log_target=False)
input1 = torch.randn(3, 6, requires_grad=True)
input2 = torch.randn(3, 6, requires_grad=True)
output = loss(input1, input2)

print('output: ', output) #tensor(-0.0284, grad_fn=<KlDivBackward>)

Eine benutzerdefinierte Verlustfunktion erstellen

PyTorch stellt uns zwei populäre Möglichkeiten bereit, um eine benutzerdefinierte Verlustfunktion zu erstellen, die zu unserem Problem passt. Diese sind die Nutzung einer Klasse und die Nutzung einer Funktion. Lasse uns sehen, wie wir beide Methoden implementieren können, beginnend mit der Funktionsimplementierung.

Dies ist leichtester Weg, um selbst eine benutzerdefinierte Verlustfunktion zu schreiben. Es ist ebenso einfach, wie es sich um die Erstellung einer Funktion handelt, indem wir die erforderlichen Eingaben und andere Parameter in die Funktion einführen, eine Operation durchführen, die PyTorchs Kern-API oder die Functional-API verwendet und ein Wert zurückgeben. Sehen wir uns eine Demonstration mit einer benutzerdefinierten arithmetischen Mittelfehlerverlustfunktion an.

def custom_mean_square_error(y_predictions, target):
  square_difference = torch.square(y_predictions - target)
  loss_value = torch.mean(square_difference)
  return loss_value

In dem obenstehenden Code definieren wir eine benutzerdefinierte Verlustfunktion, um das arithmetische Mittel der quadratischen Abweichung zu berechnen, gegeben ein Vorhersagetensor und ein Zieltensor

y_predictions = torch.randn(3, 5, requires_grad=True);
target = torch.randn(3, 5)
pytorch_loss = nn.MSELoss();
p_loss = pytorch_loss(y_predictions, target)
loss = custom_mean_square_error(y_predictions, target)
print('custom loss: ', loss)
print('pytorch loss: ', p_loss)

#benutzerdefinierte Verlustfunktion:  tensor(2.3134, grad_fn=<MeanBackward0>)
#PyTorch-Verlustfunktion:  tensor(2.3134, grad_fn=<MseLossBackward>)

Wir können die Verlustfunktion mit unserer benutzerdefinierten Verlustfunktion und der PyTorch-MSE-Verlustfunktion berechnen, um zu beobachten, dass wir die gleichen Ergebnisse erhalten.

Benutzerdefinierte Verlustfunktion mit Python-Klassen

Dieser Ansatz ist wahrscheinlich die Standard- und empfohlene Methode der Definition von benutzerdefinierten Verlustfunktionen in PyTorch. Die Verlustfunktion wird als Knoten im neuronalen Netzwerkgraph durch Unterklassen des nn-Moduls erstellt. Dies bedeutet, dass unsere benutzerdefinierte Verlustfunktion genau wie eine Konvolutionsschicht eine PyTorch-Schicht ist. Sehen wir uns eine Demonstration an, wie dies mit einer benutzerdefinierten MSE-Verlustfunktion funktioniert.

class Custom_MSE(nn.Module):
  def __init__(self):
    super(Custom_MSE, self).__init__();

  def forward(self, predictions, target):
    square_difference = torch.square(predictions - target)
    loss_value = torch.mean(square_difference)
    return loss_value
  
  def __call__(self, predictions, target):
     square_difference = torch.square(y_predictions - target)
     loss_value = torch.mean(square_difference)
     return loss_value

Schlussbetrachtungen

Wir haben viel über Verlustfunktionen in PyTorch diskutiert und einen tieferen Blick auf die inneren Mechanismen der meisten dieser Verlustfunktionen genommen. Die Wahl der richtigen Verlustfunktion für ein bestimmtes Problem kann eine überwältigende Aufgabe sein. Hoffentlich dient dieses Tutorial zusammen mit der offiziellen PyTorch-Dokumentation als Leitfaden, wenn versucht wird zu verstehen, welche Verlustfunktion Ihrem Problem am besten entspricht.

Source:
https://www.digitalocean.com/community/tutorials/pytorch-loss-functions