Autograd: Automatisk differentiation til backpropagation
De lærende definerer en skalar beregningsgraf, kalder .backward() og undersøger .grad på leaf-tensorer for at forstå, hvordan gradienter flyder gennem netværket.
Autograd: Automatisk differentiation til backpropagation er en gratis Machine Learning Academy-lektion på CoddyKit. Dette er lektion 2 af 4. Du kan læse hele lektionen gratis nedenfor — og derefter øve dig praktisk i browseren med en indbygget kodeeditor og en AI-vejleder, der er tilgængelig døgnet rundt. Den er en del af læringsforløbet i Machine Learning Academy, og dine fremskridt synkroniseres på tværs af nettet og CoddyKit-appen. Machine Learning Academy-kurset indeholder 4 lektioner i alt.
Hvad er automatisk differentiation
Automatisk differentiation (autograd) er den motor, der beregner gradienter i PyTorch, uden at programmøren behøver at udlede dem i hånden. I modsætning til numerisk differentiation (endelige differenser) eller symbolsk differentiation (algebra) fungerer autograd ved at registrere operationer på tensorer under kørsel og afspille dem baglæns. Det gør det muligt at træne modeller med enhver arkitektur effektivt og korrekt.
import torch
# A simple differentiable computation
x = torch.tensor(3.0, requires_grad=True)
y = x ** 2 + 2 * x + 1 # y = (x+1)^2
# Compute gradient dy/dx
y.backward()
print(x.grad) # tensor(8.) because dy/dx = 2x+2 = 2*3+2 = 8requires_grad: Aktivering af gradientregistrering
Gradientsporing er deaktiveret som standard. Når du angiver requires_grad=True, fortæller du PyTorch, at alle operationer på den tensor skal registreres, så gradienter kan beregnes senere. Bladtensorer (parametre) kræver gradienter, og mellemliggende tensorer arver automatisk gradientsporing fra deres forældre. Modelparametre, der oprettes af nn.Module, får automatisk indstillet requires_grad=True.
import torch
# Leaf tensor with gradient tracking
w = torch.tensor(2.0, requires_grad=True)
b = torch.tensor(0.5, requires_grad=True)
# Forward pass
x = torch.tensor(3.0) # input, no grad needed
y_pred = w * x + b # y = wx + b = 6.5
print(y_pred.requires_grad) # True (inherited)
print(w.is_leaf) # True
print(y_pred.is_leaf) # FalseBeregningsgrafen
Når du udfører operationer på tensorer med requires_grad=True, opbygger PyTorch en dynamisk beregningsgraf (en rettet acyklisk graf over operationer). Hver node gemmer operationen og referencer til dens input. Når .backward() kaldes, gennemløber PyTorch denne graf baglæns (fra output til input) ved hjælp af kædereglen for at beregne partielle afledte for hver bladtensor. Grafen opbygges på ny ved hvert fremadrettet gennemløb, hvilket gør dynamiske arkitekturer mulige.
import torch
a = torch.tensor(2.0, requires_grad=True)
b = torch.tensor(3.0, requires_grad=True)
# Build computation graph
c = a * b # c = 6
d = c + a # d = 8
e = d ** 2 # e = 64
# Inspect graph node
print(e.grad_fn) # <PowBackward0 object>
print(e.grad_fn.next_functions) # parents in the graphKald af .backward(): Beregning af gradienter
Når du kalder .backward() på en skalar tensor, udløser det bagudpropagering gennem hele beregningsgrafen, og gradienterne placeres i attributten .grad for hver bladtensor. Hvis outputtet ikke er en skalar, skal du angive en gradienttensor med samme form (den overordnede gradient). Gradienter akkumuleres som standard — kald altid optimizer.zero_grad() (eller tensor.grad.zero_()) før det næste bagudgående gennemløb for at undgå forkerte opdateringer.
import torch
x = torch.tensor(4.0, requires_grad=True)
loss = (x - 1) ** 2 # minimum at x=1
loss.backward()
print(x.grad) # tensor(6.) = 2*(x-1) = 2*3 = 6
# Gradients accumulate! Reset before next pass
x.grad.zero_()
new_loss = (x - 2) ** 2
new_loss.backward()
print(x.grad) # tensor(4.) = 2*(x-2) = 2*2 = 4Gradientflow gennem flere operationer
Kædereglen siger, at den afledte af en sammensætning af funktioner er produktet af de afledte. Autograd anvender dette mekanisk gennem hver operation i grafen. Hvis du forstår, hvordan gradienter flyder, kan du fejlfinde problemer som forsvindende gradienter (produkter tæt på nul) og eksploderende gradienter (produkter større end 1, der gentages mange gange). Valget af aktiveringsfunktion (ReLU kontra sigmoid) påvirker gradienternes størrelser direkte.
import torch
# Chain: z = sigmoid(wx + b), loss = (z - y_true)^2
def sigmoid(x):
return 1 / (1 + torch.exp(-x))
w = torch.tensor(0.5, requires_grad=True)
b = torch.tensor(0.0, requires_grad=True)
x = torch.tensor(2.0)
y_true = torch.tensor(1.0)
z = sigmoid(w * x + b)
loss = (z - y_true) ** 2
loss.backward()
print(f'dL/dw = {w.grad:.4f}') # gradient w.r.t. weight
print(f'dL/db = {b.grad:.4f}') # gradient w.r.t. biastorch.no_grad(): Deaktivering af gradientsporing
Under inferens (forudsigelse på nye data) har du ikke brug for gradienter — beregningen af dem spilder tid og hukommelse. Hvis du omslutter inferenskoden med torch.no_grad(), deaktiveres beregningsgrafen helt, hvilket gør fremadgående gennemløb hurtigere og reducerer hukommelsesforbruget med op til 50 %. Dette bruges også i evalueringsløkker for at få valideringsmålinger uden at påvirke træningen.
import torch
x = torch.randn(100, requires_grad=True)
# With gradient tracking (training)
out = x ** 2
print(out.requires_grad) # True
# Without gradient tracking (inference)
with torch.no_grad():
out_no_grad = x ** 2
print(out_no_grad.requires_grad) # False
# Also used as a decorator
@torch.no_grad()
def predict(model, data):
return model(data)Problem med gradientakkumulering og zero_grad
PyTorch akkumulerer (adder) gradienter i .grad, hver gang .backward() kaldes. Det er tilsigtet ved nogle avancerede teknikker, men under normal træning betyder det, at du skal nulstille gradienterne før hvert bagudgående gennemløb. Den normale fremgangsmåde bruger optimeringsprogrammets zero_grad()-metode, som rydder gradienterne for alle parametre, optimeringsprogrammet administrerer. Hvis du glemmer dette trin, vokser gradienterne uden grænse, og opdateringerne bliver forkerte.
import torch
import torch.nn as nn
import torch.optim as optim
model = nn.Linear(2, 1)
optimizer = optim.SGD(model.parameters(), lr=0.01)
for epoch in range(3):
optimizer.zero_grad() # clear old gradients
x = torch.randn(4, 2)
y_pred = model(x)
loss = y_pred.sum()
loss.backward() # compute new gradients
optimizer.step() # update weights
print(f'Epoch {epoch}: loss={loss.item():.3f}')Inspektion af gradientværdier til fejlfinding
Det er afgørende at inspicere gradientværdier for at diagnosticere træningsproblemer. Du kan få adgang til dem via tensor.grad efter kald af backward. Hvis du afbilder gradientnormen på tværs af lagene, kan du se, om gradienterne forsvinder (er tæt på nul) eller eksploderer (er meget store) i dybe netværk. En almindelig fejlfindingskrog er at udskrive gradientstatistik efter hver N. batch for tidligt at opdage ustabilitet under træningen.
import torch
import torch.nn as nn
model = nn.Sequential(
nn.Linear(4, 8),
nn.ReLU(),
nn.Linear(8, 1)
)
x = torch.randn(16, 4)
y_pred = model(x)
loss = y_pred.mean()
loss.backward()
# Inspect gradients of each parameter
for name, param in model.named_parameters():
if param.grad is not None:
norm = param.grad.norm().item()
print(f'{name}: grad_norm={norm:.4f}')Frakobling af tensorer fra grafen
Nogle gange vil du bruge en beregnet tensor som et konstant input til en anden beregning — uden at lade gradienter flyde gennem den. .detach() returnerer en ny tensor, der deler data, men er fjernet fra beregningsgrafen. Dette bruges i målnetværk (forstærkningslæring), til at stoppe gradientflow i bestemte grene af et netværk og til at konvertere tensorer til NumPy-arrays med henblik på afbildning.
import torch
a = torch.tensor(3.0, requires_grad=True)
b = a * 2 # b depends on a
c = b.detach() # c is a constant copy of b's value
d = c * 5 # gradient does NOT flow back to a
d.backward()
# a.grad is None because c severed the graph
print(a.grad) # None
# Detach before converting to NumPy
np_val = b.detach().numpy()
print(np_val) # [6.0] (as NumPy array)Andenordens gradienter med create_graph
PyTorch understøtter differentiation af højere orden. Når du sender create_graph=True til .backward(), bevares beregningsgrafen for selve gradientberegningen, så du kan differentiere gennem gradienter. Dette bruges i meta-læring (MAML), regularisering med gradientstraf (Wasserstein GAN) og enhver teknik, der optimerer med hensyn til gradienter.
import torch
x = torch.tensor(2.0, requires_grad=True)
y = x ** 3 # y = x^3
# First derivative dy/dx = 3x^2
dy = torch.autograd.grad(y, x, create_graph=True)[0]
print(dy) # tensor(12., grad_fn=...)
# Second derivative d^2y/dx^2 = 6x
d2y = torch.autograd.grad(dy, x)[0]
print(d2y) # tensor(6.)Autograd i træningsforløbet
Autograd er grundlaget for enhver træningsløkke til neurale netværk. Det normale mønster består af fire trin: (1) nulstil gradienterne med optimizer.zero_grad(), (2) fremadgående gennemløb for at beregne forudsigelser og tab, (3) bagudgående gennemløb med loss.backward() for at beregne gradienter og (4) optimeringstrin med optimizer.step() for at opdatere parametre. Når du forstår, at autograd udfører det tunge differentialregningsarbejde, kan du fokusere på modelarkitektur og hyperparametre.
import torch
import torch.nn as nn
import torch.optim as optim
model = nn.Linear(1, 1)
optimizer = optim.SGD(model.parameters(), lr=0.1)
criterion = nn.MSELoss()
# Synthetic data: y = 3x + 1
X = torch.randn(20, 1)
y = 3 * X + 1 + 0.1 * torch.randn(20, 1)
for epoch in range(5):
optimizer.zero_grad() # (1) zero grads
y_pred = model(X) # (2) forward
loss = criterion(y_pred, y) # (2) loss
loss.backward() # (3) backward
optimizer.step() # (4) update
print(f'Epoch {epoch}: loss={loss.item():.4f}')Hurtigt tjek
Test din forståelse af begreberne inden for maskinlæring med Python fra denne lektion.
Opsummering af lektionen
I denne lektion lærte du, at autograd opbygger en dynamisk beregningsgraf, som registrerer hver operation på tensorer med requires_grad=True, at .backward() beregner gradienter via kædereglen og placerer dem i .grad, og at gradienter akkumuleres, så du skal nulstille dem før hvert træningstrin. Dernæst undersøger vi, hvordan du opbygger et fremadrettet netværk med nn.Module.
Lær Python med en AI-underviser — gratis
Skriv og kør rigtig kode i din browser, få øjeblikkelig hjælp fra en AI-underviser døgnet rundt, og fortsæt, hvor du slap, på web eller i appen.
- Kurser
- 30
- Lektioner
- 120
Ofte stillede spørgsmål
Er lektionen “Autograd: Automatisk differentiation til backpropagation” gratis?
Ja — hele teksten til “Autograd: Automatisk differentiation til backpropagation” kan læses gratis her på nettet. Hvis du vil øve dig interaktivt med en indbygget kodeeditor og en AI-vejleder døgnet rundt og få adgang til resten af Machine Learning Academy-kurset, skal du opgradere til CoddyKit PRO. Machine Learning Academy-kurset indeholder 4 lektioner i alt.
Hvad lærer jeg i “Autograd: Automatisk differentiation til backpropagation”?
De lærende definerer en skalar beregningsgraf, kalder .backward() og undersøger .grad på leaf-tensorer for at forstå, hvordan gradienter flyder gennem netværket. Du øver dig i Machine Learning Academy med praktisk kode, som du kører direkte i browseren, og en AI-vejleder døgnet rundt besvarer dine spørgsmål, mens du arbejder dig gennem lektionen.
Skal jeg have erfaring for at begynde på Machine Learning Academy?
Der kræves ingen tidligere erfaring. Machine Learning Academy på CoddyKit er tilrettelagt for både begyndere og øvede, så du kan starte her eller fra begyndelsen og lære i dit eget tempo. Dette er lektion 2 af 4.
Hvor lang tid tager lektionen “Autograd: Automatisk differentiation til backpropagation”?
De fleste CoddyKit-lektioner tager cirka 5–10 minutter. Hver lektion er kort og interaktiv, så du gør løbende fremskridt og kan fortsætte, hvor du slap – på både web og app.
Kan jeg skrive og køre kode i denne Machine Learning Academy-lektion?
Ja. Alle Machine Learning Academy-lektioner har en indbygget kodeeditor, så du kan skrive og køre rigtig kode direkte i din browser og få øjeblikkelig feedback fra AI – uden lokal opsætning.
Alle lektioner i dette kursus
- PyTorch-tensorer: Oprettelse, operationer og GPU-overførsel
- Autograd: Automatisk differentiation til backpropagation
- Opbygning af et feedforward-netværk med nn.Module
- Træningsløkke: Loss, optimizer og epoker