Přeskočit na obsah
AI Základy

Backpropagation — jak se neuronové sítě učí

8 min čtení
BackpropagationGradient DescentDeep Learning

Backpropagation je srdcem každé neuronové sítě - elegantní algoritmus, který umožňuje strojům učit se z vlastních chyb. Pochopíte, jak tento matematický princip řídí proces učení od rozpoznávání obrázků až po jazykové modely.

Jak funguje backpropagation v neuronových sítích

Backpropagation je algoritmus, který umožňuje neuronovým sítím učit se z chyb postupným šířením gradientů zpět přes síť. Bez tohoto mechanismu by deep learning neexistoval v dnešní podobě. Podívejme se, jak přesně funguje a proč je tak důležitý.

Základní princip forward a backward pass

Učení neuronové sítě probíhá ve dvou fázích. Nejdříve forward pass — data projdou sítí směrem dopředu a vytvoří se predikce. Pak následuje backward pass — chyba se šíří zpět a aktualizují se váhy.

# Forward pass - jednoduchá síť s jednou skrytou vrstvou
import numpy as np

def sigmoid(x):
    return 1 / (1 + np.exp(-x))

def forward_pass(X, W1, b1, W2, b2):
    # Skrytá vrstva
    z1 = X.dot(W1) + b1
    a1 = sigmoid(z1)
    
    # Výstupní vrstva
    z2 = a1.dot(W2) + b2
    a2 = sigmoid(z2)
    
    return z1, a1, z2, a2

Výpočet chyby a gradientů

Klíčové je pochopení, jak se počítají gradienty. Použijeme chain rule z matematické analýzy — derivaci složené funkce rozložíme na součin derivací jednotlivých částí.

Pro mean squared error a sigmoid aktivaci vypadá gradient takto:

def compute_gradients(X, y, z1, a1, z2, a2, W1, W2):
    m = X.shape[0]  # počet vzorků
    
    # Gradient pro výstupní vrstvu
    dz2 = a2 - y  # derivace MSE loss
    dW2 = (1/m) * a1.T.dot(dz2)
    db2 = (1/m) * np.sum(dz2, axis=0)
    
    # Gradient pro skrytou vrstvu (chain rule)
    da1 = dz2.dot(W2.T)
    dz1 = da1 * a1 * (1 - a1)  # derivace sigmoidu
    dW1 = (1/m) * X.T.dot(dz1)
    db1 = (1/m) * np.sum(dz1, axis=0)
    
    return dW1, db1, dW2, db2

Aktualizace vah pomocí gradient descent

Jakmile máme gradienty, můžeme aktualizovat váhy. Gradient descent upraví každou váhu v opačném směru, než ukazuje gradient — tím se postupně dostáváme k minimu loss funkce.

def update_weights(W1, b1, W2, b2, dW1, db1, dW2, db2, learning_rate):
    W1 -= learning_rate * dW1
    b1 -= learning_rate * db1
    W2 -= learning_rate * dW2
    b2 -= learning_rate * db2
    
    return W1, b1, W2, b2

# Kompletní tréninkový cyklus
def train_step(X, y, W1, b1, W2, b2, learning_rate=0.01):
    # Forward pass
    z1, a1, z2, a2 = forward_pass(X, W1, b1, W2, b2)
    
    # Compute loss
    loss = np.mean((a2 - y)**2)
    
    # Backward pass
    dW1, db1, dW2, db2 = compute_gradients(X, y, z1, a1, z2, a2, W1, W2)
    
    # Update weights
    W1, b1, W2, b2 = update_weights(W1, b1, W2, b2, 
                                    dW1, db1, dW2, db2, learning_rate)
    
    return W1, b1, W2, b2, loss

Problémy s vanishing a exploding gradients

V hlubokých sítích může docházet k vanishing gradients — gradienty se během backpropagation zmenšují exponenciálně. Opačný problém jsou exploding gradients, kdy gradienty rostou nekonečně.

Řešení zahrnují:

  • Gradient clipping — omezení maximální velikosti gradientu
  • Lepší aktivační funkce — ReLU místo sigmoidu
  • Batch normalization — normalizace vstupů do každé vrstvy
  • Residual connections — přímé spojení mezi vzdálenými vrstvami
# Gradient clipping v praxi
def clip_gradients(gradients, max_norm=1.0):
    total_norm = 0
    for grad in gradients:
        total_norm += np.sum(grad**2)
    total_norm = np.sqrt(total_norm)
    
    clip_coef = max_norm / (total_norm + 1e-6)
    if clip_coef < 1:
        for i, grad in enumerate(gradients):
            gradients[i] = grad * clip_coef
    
    return gradients

Optimalizace backpropagation

Moderní implementace používají pokročilé optimalizéry, které upravují learning rate nebo přidávají momentum:

class AdamOptimizer:
    def __init__(self, learning_rate=0.001, beta1=0.9, beta2=0.999):
        self.lr = learning_rate
        self.beta1 = beta1
        self.beta2 = beta2
        self.m = {}  # first moment
        self.v = {}  # second moment
        self.t = 0   # time step
    
    def update(self, params, gradients):
        self.t += 1
        
        for key in params:
            if key not in self.m:
                self.m[key] = np.zeros_like(params[key])
                self.v[key] = np.zeros_like(params[key])
            
            # Update biased first/second moment estimates
            self.m[key] = self.beta1 * self.m[key] + (1 - self.beta1) * gradients[key]
            self.v[key] = self.beta2 * self.v[key] + (1 - self.beta2) * gradients[key]**2
            
            # Bias correction
            m_hat = self.m[key] / (1 - self.beta1**self.t)
            v_hat = self.v[key] / (1 - self.beta2**self.t)
            
            # Update parameters
            params[key] -= self.lr * m_hat / (np.sqrt(v_hat) + 1e-8)

Backpropagation v praxi s PyTorch

V reálných projektech používáme frameworky, které backpropagation implementují automaticky:

import torch
import torch.nn as nn

# Definice sítě
class SimpleNet(nn.Module):
    def __init__(self, input_size, hidden_size, output_size):
        super().__init__()
        self.hidden = nn.Linear(input_size, hidden_size)
        self.output = nn.Linear(hidden_size, output_size)
        self.sigmoid = nn.Sigmoid()
    
    def forward(self, x):
        x = self.sigmoid(self.hidden(x))
        x = self.sigmoid(self.output(x))
        return x

# Trénink s automatickým backpropagation
model = SimpleNet(10, 20, 1)
criterion = nn.MSELoss()
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)

for epoch in range(1000):
    # Forward pass
    outputs = model(X)
    loss = criterion(outputs, y)
    
    # Backward pass - automaticky!
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()

Shrnutí

Backpropagation je algoritmus, který umožňuje neuronové síti učit se minimalizací chyby prostřednictvím gradient descent. Klíčové jsou tři kroky: forward pass pro výpočet predikce, backward pass pro šíření gradientů a update vah. V praxi používáme optimalizéry jako Adam a frameworky jako PyTorch, které celý proces automatizují. Pochopení principů backpropagation je ale zásadní pro ladění a optimalizaci deep learning modelů.

CORE SYSTEMS tým

Enterprise architekti a AI inženýři. Stavíme systémy, které fungují.