Warum müssen wir in PyTorch zero_grad () aufrufen?

Antworten:

134

In PyTorchmüssen wir die Gradienten auf Null setzen, bevor wir mit der Backpropragation beginnen, da PyTorch die Gradienten bei nachfolgenden Rückwärtsdurchläufen akkumuliert . Dies ist praktisch beim Training von RNNs. Die Standardaktion besteht also darin, die Farbverläufe bei jedem loss.backward()Anruf zu akkumulieren (dh zu summieren) .

Wenn Sie Ihre Trainingsschleife starten, sollten zero out the gradientsSie dies daher idealerweise so tun, dass Sie die Parameteraktualisierung korrekt durchführen. Andernfalls würde der Gradient in eine andere Richtung als die beabsichtigte Richtung zum Minimum (oder zum Maximum bei Maximierungszielen) zeigen.

Hier ist ein einfaches Beispiel:

import torch
from torch.autograd import Variable
import torch.optim as optim

def linear_model(x, W, b):
    return torch.matmul(x, W) + b

data, targets = ...

W = Variable(torch.randn(4, 3), requires_grad=True)
b = Variable(torch.randn(3), requires_grad=True)

optimizer = optim.Adam([W, b])

for sample, target in zip(data, targets):
    # clear out the gradients of all Variables 
    # in this optimizer (i.e. W, b)
    optimizer.zero_grad()
    output = linear_model(sample, W, b)
    loss = (output - target) ** 2
    loss.backward()
    optimizer.step()

Wenn Sie alternativ einen Vanille-Gefälle-Abstieg machen , dann:

W = Variable(torch.randn(4, 3), requires_grad=True)
b = Variable(torch.randn(3), requires_grad=True)

for sample, target in zip(data, targets):
    # clear out the gradients of Variables 
    # (i.e. W, b)
    W.grad.data.zero_()
    b.grad.data.zero_()

    output = linear_model(sample, W, b)
    loss = (output - target) ** 2
    loss.backward()

    W -= learning_rate * W.grad.data
    b -= learning_rate * b.grad.data

Hinweis : Die Akkumulation (dh Summe ) von Gradienten erfolgt, wenn .backward()der lossTensor aufgerufen wird .

kmario23
quelle
2
Vielen Dank, das ist wirklich hilfreich! Wissen Sie zufällig, ob der Tensorfluss das Verhalten hat?
Layser
Nur um sicher zu gehen ... wenn Sie dies nicht tun, werden Sie auf ein explodierendes Gradientenproblem stoßen, oder?
zwep
2
@zwep Wenn wir Farbverläufe akkumulieren, bedeutet dies nicht, dass ihre Größe zunimmt. Ein Beispiel wäre, wenn das Vorzeichen des Farbverlaufs immer wieder wechselt. Es würde also nicht garantieren, dass Sie auf das explodierende Gradientenproblem stoßen. Außerdem existieren explodierende Verläufe, selbst wenn Sie richtig auf Null setzen.
Tom Roth
Wenn Sie den Vanille-Gradientenabstieg ausführen, wird beim Versuch, die Gewichte zu aktualisieren, nicht die Fehlermeldung "Blattvariable, für die grad für einen direkten Betrieb verwendet werden muss" angezeigt.
MUAS
1

zero_grad () startet die Schleife ohne Verluste aus dem letzten Schritt neu, wenn Sie die Gradientenmethode zum Verringern des Fehlers (oder der Verluste) verwenden.

Wenn Sie zero_grad () nicht verwenden, wird der Verlust verringert und nicht nach Bedarf erhöht

Wenn Sie beispielsweise zero_grad () verwenden, finden Sie folgende Ausgabe:

model training loss is 1.5
model training loss is 1.4
model training loss is 1.3
model training loss is 1.2

Wenn Sie zero_grad () nicht verwenden, finden Sie folgende Ausgabe:

model training loss is 1.4
model training loss is 1.9
model training loss is 2
model training loss is 2.8
model training loss is 3.5
Youssri Abo Elseod
quelle