Faza 03 · lecția 03
Retropropagarea de la zero
Scopul lecției: Retropropagarea este algoritmul care face posibilă învățarea. Fără ea, rețelele neurale sunt doar generatoare costisitoare de numere aleatoare.
Versiunea curentă AlexBred.com: primele 100 de lecții ale programului în limba română.
Cuprinsul lecției
- Obiective de învățare
- Problema
- Conceptul
- Regula lanțului aplicată rețelelor
- Grafuri computaționale
- Propagarea înainte și propagarea înapoi
- Fluxul gradientului printr-o rețea
- Gradienții care dispar
- Deducerea gradienților pentru o rețea cu două straturi
- Construiți
- Pasul 1: nodul Value
- Pasul 2: operații cu funcții de propagare înapoi
- Pasul 3: sigmoida și pierderea
- Pasul 4: propagarea înapoi
- Pasul 5: stratul și rețeaua
- Pasul 6: antrenarea pe XOR
- Pasul 7: clasificarea cercului
- Folosiți
- Livrați
- Exerciții
- Termeni-cheie
- Lecturi suplimentare
Retropropagarea este algoritmul care face posibilă învățarea. Fără ea, rețelele neurale sunt doar generatoare costisitoare de numere aleatoare.
Tip: Construire Limbaje: Python Cerințe preliminare: Lecția 03.02 — Rețele multistrat Durată: ~120 de minute
Obiective de învățare
- Să implementați un motor autograd bazat pe obiecte
Value, care construiește un graf computațional și calculează gradienții prin sortare topologică. - Să deduceți propagarea înapoi pentru adunare, înmulțire și sigmoidă folosind regula lanțului.
- Să antrenați o rețea multistrat pentru clasificarea XOR și a cercului folosind exclusiv motorul de retropropagare construit de la zero.
- Să identificați problema gradienților care dispar în rețele sigmoidale profunde și să explicați de ce aceștia se micșorează exponențial.
Problema
Rețeaua dumneavoastră are un singur strat ascuns, cu 768 de intrări și 3072 de ieșiri. Aceasta înseamnă 2.359.296 de ponderi. Rețeaua a făcut o predicție greșită. Care ponderi au provocat eroarea? Testarea individuală a fiecărei ponderi ar însemna 2,3 milioane de propagări înainte. Retropropagarea calculează toți cei 2,3 milioane de gradienți într-o singură propagare înapoi. Aceasta nu este doar o optimizare. Este diferența dintre ceva antrenabil și ceva imposibil de antrenat.
Abordarea naivă: luați o pondere, modificați-o cu o cantitate infimă, executați din nou propagarea înainte și măsurați dacă pierderea a crescut sau a scăzut. Astfel obțineți gradientul acelei ponderi. Acum faceți același lucru pentru fiecare pondere din rețea. Înmulțiți costul cu mii de pași de antrenare și milioane de puncte de date. Ați avea nevoie de intervale geologice pentru a antrena ceva util.
Retropropagarea rezolvă această problemă. O propagare înainte, o propagare înapoi, toți gradienții calculați. Trucul este regula lanțului din analiza matematică, aplicată sistematic unui graf computațional. Acesta este algoritmul care a făcut practică învățarea profundă. Fără el, am fi încă limitați la probleme demonstrative.
Notă tehnică a traducerii: Comparația cu câte o propagare înainte pentru fiecare parametru descrie diferențierea numerică prin perturbații, nu toate alternativele posibile. Pentru o pierdere scalară, retropropagarea este diferențiere automată în mod invers și calculează într-o singură traversare inversă gradienții tuturor parametrilor care contribuie la acea pierdere.
Conceptul
Regula lanțului aplicată rețelelor
Ați întâlnit regula lanțului în Faza 01, lecția 05. O recapitulare rapidă: dacă y = f(g(x)), atunci dy/dx = f'(g(x)) * g'(x). Înmulțiți derivatele de-a lungul lanțului.
Într-o rețea neurală, „lanțul” este succesiunea de operații de la intrare până la pierdere. Fiecare strat aplică ponderi, adaugă biasuri și trece rezultatul printr-o activare. Funcția de pierdere compară ieșirea finală cu ținta. Retropropagarea urmărește acest lanț în sens invers și calculează contribuția fiecărei operații la eroare.
Grafuri computaționale
Fiecare propagare înainte construiește un graf. Fiecare nod este o operație — înmulțire, adunare sau sigmoidă. Fiecare muchie transportă înainte o valoare și înapoi un gradient.
Propagarea înainte: valorile curg de la stânga la dreapta. x și w produc z1 = w*x. Adăugați b pentru a obține z2. Sigmoida furnizează activarea a. Comparați a cu ținta y prin funcția de pierdere.
Propagarea înapoi: gradienții curg de la dreapta la stânga. Începeți cu dL/da — felul în care se modifică pierderea odată cu activarea. Înmulțiți cu da/dz2, derivata sigmoidei. Obțineți astfel dL/dz2. Ramificați în dL/db, care este egal cu dL/dz2 deoarece z2 = z1 + b, și dL/dz1. Apoi dL/dw = dL/dz1 * x și dL/dx = dL/dz1 * w.
Fiecare nod din graf are o singură sarcină în timpul propagării înapoi: preia gradientul sosit din aval, îl înmulțește cu derivata sa locală și îl transmite mai departe spre intrări.
Propagarea înainte și propagarea înapoi
Propagarea înainte stochează valorile intermediare: z, a și intrările fiecărui strat. Propagarea înapoi are nevoie de asemenea valori salvate pentru a calcula gradienții. Acesta este compromisul memorie–calcul aflat în centrul retropropagării. Sacrificați memorie pentru stocarea activărilor în schimbul vitezei oferite de o singură traversare, în locul milioanelor de traversări.
Notă tehnică a traducerii: Implementările nu trebuie să păstreze literalmente fiecare valoare intermediară, ci numai valorile necesare regulilor de derivare. Checkpointing-ul activărilor reduce și mai mult memoria, recalculând în propagarea înapoi o parte dintre valorile produse înainte.
Fluxul gradientului printr-o rețea
Pentru o rețea cu trei straturi, gradienții se înlănțuie prin fiecare strat:
La fiecare strat, gradientul este înmulțit cu derivata sigmoidei. Derivata sigmoidei este a * (1 - a) și atinge cel mult 0,25, când a = 0,5. Dacă urmărim numai acești factori de activare, după trei straturi produsul este cel mult 0.25^3 = 0.0156. După zece straturi: 0.25^10 = 0.000001.
Notă tehnică a traducerii: Într-o rețea reală, gradientul este înmulțit și cu ponderile sau, în forma vectorială, cu Jacobienii straturilor. Prin urmare,
0.25^Ldescrie doar contribuția maximă a derivatelor sigmoidale, nu o limită universală pentru gradientul complet; ponderile îl pot atenua sau amplifica.
Gradienții care dispar
Aceasta este problema gradienților care dispar. Sigmoida comprimă ieșirea între 0 și 1. Derivata ei nu depășește niciodată 0,25. Suprapuneți suficiente straturi sigmoidale, iar contribuția acestor derivate face gradienții să se micșoreze drastic. Straturile timpurii abia învață, deoarece primesc gradienți aproape nuli.
sigmoid(z): Intervalul ieșirii [0, 1]
sigmoid'(z): Valoarea maximă 0,25 (la z = 0)
După 5 straturi: gradient * 0.25^5 = 0.001x valoarea inițială
După 10 straturi: gradient * 0.25^10 = 0.000001x valoarea inițială
Acesta este motivul pentru care rețelele sigmoidale profunde sunt foarte greu de antrenat. O soluție importantă — ReLU și variantele sale — este tema lecției 04. Pentru moment, rețineți că mecanismul retropropagării aplică exact regula lanțului; dificultatea provine din operațiile și parametrii prin care trebuie să se propage gradientul.
Notă tehnică a traducerii: Formularea originală conform căreia retropropagarea „funcționează perfect” este prea categorică. În practică, stabilitatea numerică, operațiile nediferențiabile, grafurile implementate greșit și gradienții care explodează pot produce dificultăți chiar dacă regula lanțului este corectă.
Deducerea gradienților pentru o rețea cu două straturi
Să scriem matematica în formă concretă pentru o rețea cu intrarea x, un strat ascuns cu sigmoidă, un strat de ieșire cu sigmoidă și pierdere MSE.
Propagarea înainte:
z1 = W1 * x + b1
a1 = sigmoid(z1)
z2 = W2 * a1 + b2
a2 = sigmoid(z2)
L = (a2 - y)^2
Propagarea înapoi, prin aplicarea pas cu pas a regulii lanțului:
dL/da2 = 2(a2 - y)
da2/dz2 = a2 * (1 - a2)
dL/dz2 = dL/da2 * da2/dz2 = 2(a2 - y) * a2 * (1 - a2)
dL/dW2 = dL/dz2 * a1
dL/db2 = dL/dz2
dL/da1 = dL/dz2 * W2
da1/dz1 = a1 * (1 - a1)
dL/dz1 = dL/da1 * da1/dz1
dL/dW1 = dL/dz1 * x
dL/db1 = dL/dz1
Fiecare gradient este produsul derivatelor locale urmărite înapoi de la pierdere. În esență, aceasta este retropropagarea.
Notă tehnică a traducerii: Relațiile de mai sus sunt scrise ca produse scalare simplificate. Pentru vectori și matrice, gradienții ponderilor includ produse exterioare și transpuneri compatibile cu formele tensorilor.
backprop-vanishing
Construiți
Pasul 1: nodul Value
Fiecare număr din calculul nostru devine un obiect Value. Acesta își stochează valoarea, gradientul și modul în care a fost creat, astfel încât să știe cum se calculează gradienții înapoi.
class Value:
def __init__(self, data, children=(), op=''):
self.data = data
self.grad = 0.0
self._backward = lambda: None
self._children = set(children)
self._op = op
def __repr__(self):
return f"Value(data={self.data:.4f}, grad={self.grad:.4f})"
Gradientul încă nu există, deci este 0.0. Funcția de propagare înapoi nu există încă, deci nu face nimic. Câmpul _children urmărește obiectele Value care l-au produs pe cel curent, pentru a putea sorta topologic graful mai târziu.
Pasul 2: operații cu funcții de propagare înapoi
Fiecare operație creează un obiect Value nou și definește modul în care gradienții curg înapoi prin ea.
def __add__(self, other):
other = other if isinstance(other, Value) else Value(other)
out = Value(self.data + other.data, (self, other), '+')
def _backward():
self.grad += out.grad
other.grad += out.grad
out._backward = _backward
return out
def __mul__(self, other):
other = other if isinstance(other, Value) else Value(other)
out = Value(self.data * other.data, (self, other), '*')
def _backward():
self.grad += other.data * out.grad
other.grad += self.data * out.grad
out._backward = _backward
return out
Pentru adunare: d(a+b)/da = 1, d(a+b)/db = 1. Prin urmare, ambele intrări primesc direct gradientul ieșirii.
Pentru înmulțire: d(a*b)/da = b, d(a*b)/db = a. Fiecare intrare primește valoarea celeilalte înmulțită cu gradientul ieșirii.
Operatorul += este esențial. Un obiect Value poate fi folosit în mai multe operații. Gradientul său este suma gradienților de pe toate căile.
Pasul 3: sigmoida și pierderea
import math
def sigmoid(self):
x = self.data
x = max(-500, min(500, x))
s = 1.0 / (1.0 + math.exp(-x))
out = Value(s, (self,), 'sigmoid')
def _backward():
self.grad += (s * (1 - s)) * out.grad
out._backward = _backward
return out
Derivata sigmoidei: sigmoid(x) * (1 - sigmoid(x)). Am calculat sigmoid(x) = s în timpul propagării înainte. Refolosiți valoarea. Nu este nevoie de muncă suplimentară.
Notă tehnică a traducerii: limitarea lui
xla intervalul[-500, 500]păstrează calculul finit, dar modifică funcția. În afara intervalului, derivata clamp-ului este zero (cu o convenție la frontieră); backward-ul didactic nu o aplică și este astfel inconsistent pentru intrări limitate. O implementare de producție trebuie să reprezinte clamp-ul în graful de diferențiere sau să utilizeze o sigmoidă stabilă furnizată de bibliotecă.
def mse_loss(predicted, target):
diff = predicted + Value(-target)
return diff * diff
MSE pentru o singură ieșire este (predicted - target)^2. Exprimăm scăderea ca adunare cu un obiect Value negat.
Pasul 4: propagarea înapoi
Sortarea topologică ne asigură că prelucrăm nodurile în ordinea corectă: gradientul unui nod este acumulat complet înainte de a-l propaga prin acel nod.
def backward(self):
topo = []
visited = set()
def build_topo(v):
if v not in visited:
visited.add(v)
for child in v._children:
build_topo(child)
topo.append(v)
build_topo(self)
self.grad = 1.0
for v in reversed(topo):
v._backward()
Începeți de la pierdere cu gradientul 1.0, deoarece dL/dL = 1. Parcurgeți în sens invers graful sortat. Funcția _backward a fiecărui nod împinge gradienții spre predecesorii săi.
Pasul 5: stratul și rețeaua
import random
class Neuron:
def __init__(self, n_inputs):
scale = (2.0 / n_inputs) ** 0.5
self.weights = [Value(random.uniform(-scale, scale)) for _ in range(n_inputs)]
self.bias = Value(0.0)
def __call__(self, x):
act = sum((wi * xi for wi, xi in zip(self.weights, x)), self.bias)
return act.sigmoid()
def parameters(self):
return self.weights + [self.bias]
class Layer:
def __init__(self, n_inputs, n_outputs):
self.neurons = [Neuron(n_inputs) for _ in range(n_outputs)]
def __call__(self, x):
out = [n(x) for n in self.neurons]
return out[0] if len(out) == 1 else out
def parameters(self):
params = []
for n in self.neurons:
params.extend(n.parameters())
return params
class Network:
def __init__(self, sizes):
self.layers = []
for i in range(len(sizes) - 1):
self.layers.append(Layer(sizes[i], sizes[i + 1]))
def __call__(self, x):
for layer in self.layers:
x = layer(x)
if not isinstance(x, list):
x = [x]
return x[0] if len(x) == 1 else x
def parameters(self):
params = []
for layer in self.layers:
params.extend(layer.parameters())
return params
def zero_grad(self):
for p in self.parameters():
p.grad = 0.0
Un obiect Neuron primește intrările, calculează suma ponderată plus biasul și aplică sigmoida. Inițializarea ponderilor folosește factorul sqrt(2/n_inputs), prezentat în original ca mijloc de a preveni saturarea sigmoidei în rețele mai profunde. Un obiect Layer este o listă de obiecte Neuron. Un obiect Network este o listă de obiecte Layer. Metoda parameters() colectează toate obiectele Value antrenabile, pentru a le putea actualiza.
Notă tehnică a traducerii: Factorul
sqrt(2/fan_in)este abaterea standard a inițializării He normale pentru activări rectificatoare precum ReLU, nu limita uniformă folosită de cod. Eșantionarea uniformă pe[-sqrt(2/fan_in), sqrt(2/fan_in)]are varianța2/(3*fan_in); inițializarea He uniformă pentru ReLU folosește limitasqrt(6/fan_in). Pentru sigmoide sautanhse folosește de regulă inițializarea Xavier/Glorot, care urmărește să păstreze variația activărilor și a gradienților între straturi. Codul original este păstrat neschimbat pentru continuitatea exercițiului.
Pasul 6: antrenarea pe XOR
random.seed(42)
net = Network([2, 4, 1])
xor_data = [
([0.0, 0.0], 0.0),
([0.0, 1.0], 1.0),
([1.0, 0.0], 1.0),
([1.0, 1.0], 0.0),
]
learning_rate = 1.0
for epoch in range(1000):
total_loss = Value(0.0)
for inputs, target in xor_data:
x = [Value(i) for i in inputs]
pred = net(x)
loss = mse_loss(pred, target)
total_loss = total_loss + loss
net.zero_grad()
total_loss.backward()
for p in net.parameters():
p.data -= learning_rate * p.grad
if epoch % 100 == 0:
print(f"Epoch {epoch:4d} | Loss: {total_loss.data:.6f}")
print("\nXOR Results:")
for inputs, target in xor_data:
x = [Value(i) for i in inputs]
pred = net(x)
print(f" {inputs} -> {pred.data:.4f} (expected {target})")
Urmăriți cum scade pierderea. De la predicții aleatoare la ieșiri XOR corecte, totul este determinat de retropropagarea care calculează gradienții și deplasează ponderile în direcția potrivită.
Pasul 7: clasificarea cercului
În lecția 02 ați folosit ponderi alese manual pentru XOR și ponderi aleatoare pentru exemplul de clasificare a cercului. Acum lăsați rețeaua să învețe ponderile cercului.
Notă tehnică a traducerii: Originalul afirmă că ponderile clasificatorului circular au fost reglate manual în lecția 02. În lecția precedentă, reglarea manuală este folosită pentru XOR, în timp ce exemplul cercului utilizează ponderi aleatoare; formularea de mai sus corectează trimiterea încrucișată.
random.seed(7)
def generate_circle_data(n=100):
data = []
for _ in range(n):
x1 = random.uniform(-1.5, 1.5)
x2 = random.uniform(-1.5, 1.5)
label = 1.0 if x1 * x1 + x2 * x2 < 1.0 else 0.0
data.append(([x1, x2], label))
return data
circle_data = generate_circle_data(80)
circle_net = Network([2, 8, 1])
learning_rate = 0.5
for epoch in range(2000):
random.shuffle(circle_data)
total_loss_val = 0.0
for inputs, target in circle_data:
x = [Value(i) for i in inputs]
pred = circle_net(x)
loss = mse_loss(pred, target)
circle_net.zero_grad()
loss.backward()
for p in circle_net.parameters():
p.data -= learning_rate * p.grad
total_loss_val += loss.data
if epoch % 200 == 0:
correct = 0
for inputs, target in circle_data:
x = [Value(i) for i in inputs]
pred = circle_net(x)
predicted_class = 1.0 if pred.data > 0.5 else 0.0
if predicted_class == target:
correct += 1
accuracy = correct / len(circle_data) * 100
print(f"Epoch {epoch:4d} | Loss: {total_loss_val:.4f} | Accuracy: {accuracy:.1f}%")
Aici folosim SGD online: actualizăm ponderile după fiecare exemplu, în loc să acumulăm întregul lot. Amestecarea datelor la fiecare epocă reduce efectele nedorite ale ordinii exemplelor și corelația dintre actualizări consecutive.
Notă tehnică a traducerii: Afirmațiile originale că SGD online „rupe simetria mai repede”, evită saturarea pe întregul peisaj al pierderii și că amestecarea împiedică memorarea ordinii nu sunt garanții generale. Simetria este ruptă în primul rând prin inițializarea diferită a parametrilor; amestecarea reduce părtinirea indusă de ordine, iar saturarea depinde de activări, ponderi, date și pașii de optimizare.
Fără reglare manuală, rețeaua ajustează o frontieră de decizie circulară pe datele de antrenare. Aceasta este puterea retropropagării: definiți arhitectura, funcția de pierdere și datele, iar algoritmul determină ponderile.
Notă tehnică a traducerii: Acuratețea afișată este măsurată pe aceleași 80 de exemple folosite la antrenare. Ea arată potrivirea datelor de antrenare, nu demonstrează generalizarea; aceasta ar necesita un set separat de validare sau testare.
Folosiți
PyTorch face tot ce am construit mai sus în câteva linii. Ideea de bază este aceeași: autograd construiește un graf computațional în timpul propagării înainte și îl urmărește în sens invers pentru a calcula gradienții.
import torch
import torch.nn as nn
model = nn.Sequential(
nn.Linear(2, 4),
nn.Sigmoid(),
nn.Linear(4, 1),
nn.Sigmoid(),
)
optimizer = torch.optim.SGD(model.parameters(), lr=1.0)
criterion = nn.MSELoss()
X = torch.tensor([[0,0],[0,1],[1,0],[1,1]], dtype=torch.float32)
y = torch.tensor([[0],[1],[1],[0]], dtype=torch.float32)
for epoch in range(1000):
pred = model(X)
loss = criterion(pred, y)
optimizer.zero_grad()
loss.backward()
optimizer.step()
print("PyTorch XOR Results:")
with torch.no_grad():
for i in range(4):
pred = model(X[i])
print(f" {X[i].tolist()} -> {pred.item():.4f} (expected {y[i].item()})")
loss.backward() corespunde metodei total_loss.backward() pe care ați construit-o. optimizer.step() corespunde actualizării manuale p.data -= lr * p.grad. optimizer.zero_grad() corespunde metodei net.zero_grad(). Este același algoritm, într-o implementare pregătită pentru uz industrial. PyTorch gestionează accelerarea pe GPU, precizia mixtă, checkpointing-ul gradienților și sute de tipuri de straturi. Propagarea înapoi rămâne aceeași aplicare a regulii lanțului pe graful computațional.
Antrenarea execută propagarea înainte, apoi propagarea înapoi și, în final, actualizează ponderile. Inferența obișnuită execută numai propagarea înainte: nu calculează gradienți și nu actualizează ponderi. Distincția contează deoarece inferența este operația predominantă în producție. Atunci când apelați un API pentru un model lingvistic, promptul curge înainte prin rețea, iar la celălalt capăt apar tokenuri; ponderile modelului nu se modifică în acel apel. Înțelegerea retropropagării este importantă deoarece ea a contribuit la formarea fiecărei ponderi din rețea în timpul antrenării.
Livrați
Această lecție produce:
outputs/prompt-gradient-debugger.md— un prompt reutilizabil pentru diagnosticarea problemelor de gradient — dispariție, explozie sauNaN— în orice rețea neurală.
Exerciții
-
Adăugați clasei
Valueo metodă__sub__, folosind relațiaa - b = a + (-1 * b). Apoi implementați o metodă__neg__. Verificați corectitudinea gradienților prin compararea cu un calcul manual pentru o expresie simplă precum(a - b)^2. -
Adăugați obiectului
Valueo metodărelu: ieșirea estemax(0, x), iar derivata este 1 dacăx > 0și 0 în caz contrar. Înlocuiți sigmoida cu ReLU în straturile ascunse și antrenați din nou pe XOR. Comparați viteza convergenței. Este posibil să observați o antrenare mai rapidă — o anticipare a lecției 04 — însă rezultatul depinde de inițializare și hiperparametri. -
Implementați în
Valueo metodă__pow__pentru puteri întregi. Folosiți-o pentru a înlocuimse_losscu expresia propriu-zisă(predicted - target) ** 2. Verificați dacă gradienții coincid cu cei ai implementării originale. -
Adăugați limitarea gradienților în bucla de antrenare: după apelarea metodei
backward(), limitați toți gradienții la intervalul[-1, 1]. Antrenați o rețea mai profundă — cel puțin patru straturi cu sigmoidă — și comparați curbele pierderii cu și fără limitare. Aceasta este prima dumneavoastră apărare împotriva gradienților care explodează. -
Construiți o vizualizare: după antrenarea pe XOR, afișați gradientul fiecărui parametru din rețea. Identificați stratul care are gradienții cei mai mici. Astfel demonstrați problema gradienților care dispar, prezentată în secțiunea Conceptul.
Termeni-cheie
| Termen | Ce spun oamenii | Ce înseamnă de fapt |
|---|---|---|
| Retropropagare | „Rețeaua învață” | Algoritm care calculează dL/dw pentru fiecare pondere, aplicând regula lanțului în sens invers prin graful computațional |
| Graf computațional | „Structura rețelei” | Graf orientat aciclic ale cărui noduri reprezintă operații și ale cărui muchii transportă valori înainte și gradienți înapoi |
| Regula lanțului | „Înmulțiți derivatele” | Dacă y = f(g(x)), atunci dy/dx = f'(g(x)) * g'(x) — fundamentul matematic al retropropagării |
| Gradient | „Direcția celei mai abrupte creșteri” | Vectorul derivatelor parțiale ale pierderii față de parametri; fiecare componentă indică sensibilitatea pierderii la parametrul corespunzător |
| Gradient care dispare | „Rețelele profunde nu învață” | Gradienții se micșorează puternic pe măsură ce se propagă prin multe straturi cu activări saturante precum sigmoida |
| Propagare înainte | „Rularea rețelei” | Calcularea ieșirii pornind de la intrări, prin aplicarea succesivă a operațiilor fiecărui strat și păstrarea valorilor intermediare necesare |
| Propagare înapoi | „Calcularea gradienților” | Parcurgerea inversă a grafului computațional și acumularea gradienților la fiecare nod folosind regula lanțului |
| Rată de învățare | „Cât de repede învață” | Scalar care controlează mărimea pasului la actualizarea ponderilor: w_nou = w_vechi - lr * gradient |
| Sortare topologică | „Ordinea corectă” | Ordonare a nodurilor grafului în care fiecare nod apare după toate nodurile de care depinde; parcurgerea inversă asigură acumularea gradienților înainte de propagare |
| Autograd | „Diferențiere automată” | Sistem care construiește grafuri computaționale în timpul calculului înainte și calculează automat gradienții, precum motorul din PyTorch |
Lecturi suplimentare
- Rumelhart, Hinton și Williams, „Learning representations by back-propagating errors” (1986) — lucrarea care a popularizat retropropagarea și a permis antrenarea rețelelor multistrat.
- 3Blue1Brown, seria „Neural Networks” — explicație vizuală excelentă a retropropagării și a fluxului gradientului prin rețele.
Sursă: Originalul în limba engleză
Navigare: ← Lecția 03.02 — Rețele multistrat și propagarea înainte · Faza 3 — Fundamentele învățării profunde · Catalog complet · Lecția 03.04 — Funcții de activare →