23  Perceptron

23.1 Motivace: Inspirace mozkem

Lidský mozek obsahuje přibližně 86 miliard neuronů, propojených biliony synapsí. Každý neuron přijímá signály od ostatních neuronů, zpracovává je a pokud je celkový signál dostatečně silný, “vystřelí” a pošle signál dál.

V roce 1958 Frank Rosenblatt navrhl perceptron - zjednodušený matematický model neuronu. I když je perceptron velmi jednoduchý, je základním stavebním kamenem všech moderních neuronových sítí.

import numpy as np
import matplotlib.pyplot as plt

# Vizualizace biologického vs umělého neuronu
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(14, 5))

# Biologický neuron (schéma)
ax1.set_xlim(0, 10)
ax1.set_ylim(0, 10)

# Tělo neuronu
circle = plt.Circle((5, 5), 1.5, color='#3498db', ec='black', lw=2)
ax1.add_patch(circle)
ax1.text(5, 5, 'Soma\n(tělo)', ha='center', va='center', fontsize=10)

# Dendrity (vstupy)
for i, y in enumerate([7, 5, 3]):
    ax1.arrow(1, y, 2, 5-y if y != 5 else 0, head_width=0.2, head_length=0.1, fc='green', ec='green')
    ax1.text(0.5, y, f'x{i+1}', fontsize=12, va='center')

# Axon (výstup)
ax1.arrow(6.5, 5, 2, 0, head_width=0.3, head_length=0.2, fc='red', ec='red')
ax1.text(9.5, 5, 'y', fontsize=12, va='center')

ax1.set_title('Biologický neuron', fontsize=14)
ax1.axis('off')

# Umělý neuron (perceptron)
ax2.set_xlim(0, 10)
ax2.set_ylim(0, 10)

# Vstupní uzly
for i, y in enumerate([8, 5, 2]):
    circle = plt.Circle((1, y), 0.4, color='#2ecc71', ec='black', lw=2)
    ax2.add_patch(circle)
    ax2.text(1, y, f'x{i+1}', ha='center', va='center', fontsize=10)
    # Váhy
    ax2.annotate('', xy=(4.5, 5), xytext=(1.5, y),
                arrowprops=dict(arrowstyle='->', color='gray', lw=1.5))
    ax2.text(2.5, (y + 5)/2 + 0.3, f'w{i+1}', fontsize=9, color='blue')

# Suma a aktivace
circle = plt.Circle((5, 5), 0.8, color='#3498db', ec='black', lw=2)
ax2.add_patch(circle)
ax2.text(5, 5, 'Σ', ha='center', va='center', fontsize=16)

# Aktivační funkce
rect = plt.Rectangle((6.5, 4.2), 1.2, 1.6, color='#e74c3c', ec='black', lw=2)
ax2.add_patch(rect)
ax2.text(7.1, 5, 'σ', ha='center', va='center', fontsize=14, color='white')

ax2.annotate('', xy=(6.5, 5), xytext=(5.8, 5),
            arrowprops=dict(arrowstyle='->', color='gray', lw=2))
ax2.annotate('', xy=(9, 5), xytext=(7.7, 5),
            arrowprops=dict(arrowstyle='->', color='gray', lw=2))

ax2.text(9.3, 5, 'y', fontsize=12, va='center')

ax2.set_title('Umělý neuron (perceptron)', fontsize=14)
ax2.axis('off')

plt.tight_layout()
plt.show()

23.2 Matematický model perceptronu

PoznámkaDefinice: Perceptron

Perceptron počítá vážený součet vstupů a aplikuje aktivační funkci:

\[y = \sigma\left(\sum_{i=1}^n w_i x_i + b\right) = \sigma(\mathbf{w}^T \mathbf{x} + b)\]

kde: - \(\mathbf{x} = (x_1, \ldots, x_n)\) jsou vstupy - \(\mathbf{w} = (w_1, \ldots, w_n)\) jsou váhy - \(b\) je bias (práh) - \(\sigma\) je aktivační funkce

import numpy as np

def perceptron(x, w, b, activation='step'):
    """
    Výpočet perceptronu.

    Args:
        x: Vstupní vektor
        w: Vektor vah
        b: Bias
        activation: Aktivační funkce ('step', 'sigmoid', 'relu')
    """
    # Vážený součet
    z = np.dot(w, x) + b

    # Aktivační funkce
    if activation == 'step':
        return 1 if z >= 0 else 0
    elif activation == 'sigmoid':
        return 1 / (1 + np.exp(-z))
    elif activation == 'relu':
        return max(0, z)

# Příklad
x = np.array([1.0, 0.5])
w = np.array([0.5, -0.3])
b = 0.1

print(f"Vstup: x = {x}")
print(f"Váhy: w = {w}")
print(f"Bias: b = {b}")
print(f"\nVážený součet: z = {np.dot(w, x) + b:.3f}")
print(f"Výstup (step): {perceptron(x, w, b, 'step')}")
print(f"Výstup (sigmoid): {perceptron(x, w, b, 'sigmoid'):.4f}")
print(f"Výstup (relu): {perceptron(x, w, b, 'relu'):.4f}")
Vstup: x = [1.  0.5]
Váhy: w = [ 0.5 -0.3]
Bias: b = 0.1

Vážený součet: z = 0.450
Výstup (step): 1
Výstup (sigmoid): 0.6106
Výstup (relu): 0.4500

23.3 Aktivační funkce

Aktivační funkce vnáší do sítě nelinearitu - bez ní by celá síť byla jen lineární transformace.

23.3.1 Skoková funkce (Step)

Původní aktivační funkce perceptronu:

\[\sigma(z) = \begin{cases} 1 & \text{pokud } z \geq 0 \\ 0 & \text{pokud } z < 0 \end{cases}\]

import numpy as np
import matplotlib.pyplot as plt

z = np.linspace(-5, 5, 1000)

fig, axes = plt.subplots(2, 3, figsize=(15, 8))

# Step funkce
ax = axes[0, 0]
step = np.where(z >= 0, 1, 0)
ax.plot(z, step, 'b-', lw=2)
ax.set_title('Step (Heaviside)')
ax.set_xlabel('z')
ax.set_ylabel('σ(z)')
ax.grid(True, alpha=0.3)
ax.set_ylim(-0.1, 1.1)

# Sigmoid
ax = axes[0, 1]
sigmoid = 1 / (1 + np.exp(-z))
ax.plot(z, sigmoid, 'b-', lw=2)
ax.axhline(y=0.5, color='gray', linestyle='--', alpha=0.5)
ax.set_title('Sigmoid')
ax.set_xlabel('z')
ax.set_ylabel('σ(z)')
ax.grid(True, alpha=0.3)

# Tanh
ax = axes[0, 2]
tanh = np.tanh(z)
ax.plot(z, tanh, 'b-', lw=2)
ax.axhline(y=0, color='gray', linestyle='--', alpha=0.5)
ax.set_title('Tanh')
ax.set_xlabel('z')
ax.set_ylabel('σ(z)')
ax.grid(True, alpha=0.3)

# ReLU
ax = axes[1, 0]
relu = np.maximum(0, z)
ax.plot(z, relu, 'b-', lw=2)
ax.set_title('ReLU')
ax.set_xlabel('z')
ax.set_ylabel('σ(z)')
ax.grid(True, alpha=0.3)

# Leaky ReLU
ax = axes[1, 1]
leaky_relu = np.where(z >= 0, z, 0.1 * z)
ax.plot(z, leaky_relu, 'b-', lw=2)
ax.set_title('Leaky ReLU (α=0.1)')
ax.set_xlabel('z')
ax.set_ylabel('σ(z)')
ax.grid(True, alpha=0.3)

# GELU (používá se v transformerech)
ax = axes[1, 2]
from math import erf as math_erf
gelu = 0.5 * z * (1 + np.array([math_erf(zi / np.sqrt(2)) for zi in z]))
ax.plot(z, gelu, 'b-', lw=2)
ax.set_title('GELU (transformery)')
ax.set_xlabel('z')
ax.set_ylabel('σ(z)')
ax.grid(True, alpha=0.3)

plt.suptitle('Aktivační funkce', fontsize=14)
plt.tight_layout()
plt.show()

23.3.2 Porovnání aktivačních funkcí

aktivace = {
    'Step': ('Původní, nediferencovatelná', 'Historická'),
    'Sigmoid': ('Výstup v (0,1), hladká', 'Výstupní vrstva, binární klasifikace'),
    'Tanh': ('Výstup v (-1,1), zero-centered', 'RNN, skryté vrstvy'),
    'ReLU': ('Rychlá, řeší vanishing gradient', 'Default pro skryté vrstvy'),
    'Leaky ReLU': ('Řeší "dying ReLU"', 'Alternativa k ReLU'),
    'GELU': ('Hladká aproximace ReLU', 'Transformery (BERT, GPT)')
}

print("Přehled aktivačních funkcí:")
print("=" * 70)
for name, (vlastnosti, pouziti) in aktivace.items():
    print(f"\n{name}:")
    print(f"  Vlastnosti: {vlastnosti}")
    print(f"  Použití: {pouziti}")
Přehled aktivačních funkcí:
======================================================================

Step:
  Vlastnosti: Původní, nediferencovatelná
  Použití: Historická

Sigmoid:
  Vlastnosti: Výstup v (0,1), hladká
  Použití: Výstupní vrstva, binární klasifikace

Tanh:
  Vlastnosti: Výstup v (-1,1), zero-centered
  Použití: RNN, skryté vrstvy

ReLU:
  Vlastnosti: Rychlá, řeší vanishing gradient
  Použití: Default pro skryté vrstvy

Leaky ReLU:
  Vlastnosti: Řeší "dying ReLU"
  Použití: Alternativa k ReLU

GELU:
  Vlastnosti: Hladká aproximace ReLU
  Použití: Transformery (BERT, GPT)

23.4 Perceptron jako lineární klasifikátor

Perceptron rozděluje prostor nadrovinou (v 2D přímkou):

# Perceptron se naučí rozhodovací hranici
import numpy as np
import matplotlib.pyplot as plt

np.random.seed(42)

# Generování dat - dvě lineárně oddělitelné třídy
n_samples = 100
X_class0 = np.random.randn(n_samples, 2) + np.array([2, 2])
X_class1 = np.random.randn(n_samples, 2) + np.array([-2, -2])

X = np.vstack([X_class0, X_class1])
y = np.array([0] * n_samples + [1] * n_samples)

# Vizualizace
plt.figure(figsize=(10, 8))
plt.scatter(X_class0[:, 0], X_class0[:, 1], c='blue', label='Třída 0', alpha=0.6)
plt.scatter(X_class1[:, 0], X_class1[:, 1], c='red', label='Třída 1', alpha=0.6)

# Nakreslíme možnou rozhodovací hranici
x_line = np.linspace(-5, 5, 100)
# w1*x + w2*y + b = 0 => y = -(w1*x + b)/w2
w = np.array([1, 1])
b = 0
y_line = -(w[0] * x_line + b) / w[1]
plt.plot(x_line, y_line, 'g-', lw=2, label='Rozhodovací hranice')

plt.xlabel('x₁')
plt.ylabel('x₂')
plt.title('Perceptron jako lineární klasifikátor')
plt.legend()
plt.axis('equal')
plt.xlim(-5, 5)
plt.ylim(-5, 5)
plt.grid(True, alpha=0.3)
plt.show()

23.4.1 Trénování perceptronu

import numpy as np
import matplotlib.pyplot as plt

def train_perceptron(X, y, lr=0.1, n_epochs=100):
    """
    Trénování perceptronu pomocí perceptron learning rule.
    """
    n_samples, n_features = X.shape
    w = np.zeros(n_features)
    b = 0

    history = {'weights': [w.copy()], 'bias': [b], 'errors': []}

    for epoch in range(n_epochs):
        errors = 0
        for xi, yi in zip(X, y):
            # Predikce
            z = np.dot(w, xi) + b
            y_pred = 1 if z >= 0 else 0

            # Update při chybě
            if y_pred != yi:
                errors += 1
                update = lr * (yi - y_pred)
                w += update * xi
                b += update

        history['weights'].append(w.copy())
        history['bias'].append(b)
        history['errors'].append(errors)

        if errors == 0:
            print(f"Konvergence po {epoch + 1} epochách!")
            break

    return w, b, history

# Trénování
w_final, b_final, history = train_perceptron(X, y, lr=0.1, n_epochs=100)

print(f"Naučené váhy: w = {w_final}")
print(f"Naučený bias: b = {b_final:.4f}")

# Vizualizace tréninku
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(14, 5))

# Data a finální hranice
ax1.scatter(X_class0[:, 0], X_class0[:, 1], c='blue', label='Třída 0', alpha=0.6)
ax1.scatter(X_class1[:, 0], X_class1[:, 1], c='red', label='Třída 1', alpha=0.6)

x_line = np.linspace(-5, 5, 100)
y_line = -(w_final[0] * x_line + b_final) / w_final[1]
ax1.plot(x_line, y_line, 'g-', lw=2, label='Naučená hranice')

ax1.set_xlabel('x₁')
ax1.set_ylabel('x₂')
ax1.set_title('Výsledek trénování')
ax1.legend()
ax1.set_xlim(-5, 5)
ax1.set_ylim(-5, 5)
ax1.grid(True, alpha=0.3)

# Chyby v čase
ax2.plot(history['errors'], 'b.-', markersize=8)
ax2.set_xlabel('Epocha')
ax2.set_ylabel('Počet chyb')
ax2.set_title('Konvergence perceptronu')
ax2.grid(True, alpha=0.3)

plt.tight_layout()
plt.show()
Konvergence po 3 epochách!
Naučené váhy: w = [-0.51519602 -0.20235379]
Naučený bias: b = 0.2000

23.5 Limity perceptronu: Problém XOR

Perceptron může naučit jen lineárně separabilní problémy. Slavný příklad problému, který perceptron nezvládne, je XOR:

# XOR problém
import numpy as np
import matplotlib.pyplot as plt

X_xor = np.array([[0, 0], [0, 1], [1, 0], [1, 1]])
y_xor = np.array([0, 1, 1, 0])  # XOR výstup

fig, axes = plt.subplots(1, 3, figsize=(15, 4))

# AND - lineárně separabilní
ax = axes[0]
X_and = X_xor
y_and = np.array([0, 0, 0, 1])
ax.scatter(X_and[y_and==0, 0], X_and[y_and==0, 1], c='blue', s=200, label='0')
ax.scatter(X_and[y_and==1, 0], X_and[y_and==1, 1], c='red', s=200, label='1')
# Rozhodovací hranice
x_line = np.linspace(-0.5, 1.5, 100)
ax.plot(x_line, 1.5 - x_line, 'g-', lw=2)
ax.fill_between(x_line, 1.5 - x_line, 2, alpha=0.2, color='red')
ax.fill_between(x_line, -0.5, 1.5 - x_line, alpha=0.2, color='blue')
ax.set_title('AND (lineárně separabilní)')
ax.set_xlabel('x₁')
ax.set_ylabel('x₂')
ax.set_xlim(-0.5, 1.5)
ax.set_ylim(-0.5, 1.5)
ax.legend()
ax.grid(True, alpha=0.3)

# OR - lineárně separabilní
ax = axes[1]
y_or = np.array([0, 1, 1, 1])
ax.scatter(X_xor[y_or==0, 0], X_xor[y_or==0, 1], c='blue', s=200, label='0')
ax.scatter(X_xor[y_or==1, 0], X_xor[y_or==1, 1], c='red', s=200, label='1')
ax.plot(x_line, 0.5 - x_line, 'g-', lw=2)
ax.fill_between(x_line, 0.5 - x_line, 2, alpha=0.2, color='red')
ax.fill_between(x_line, -0.5, 0.5 - x_line, alpha=0.2, color='blue')
ax.set_title('OR (lineárně separabilní)')
ax.set_xlabel('x₁')
ax.set_ylabel('x₂')
ax.set_xlim(-0.5, 1.5)
ax.set_ylim(-0.5, 1.5)
ax.legend()
ax.grid(True, alpha=0.3)

# XOR - NENÍ lineárně separabilní
ax = axes[2]
ax.scatter(X_xor[y_xor==0, 0], X_xor[y_xor==0, 1], c='blue', s=200, label='0')
ax.scatter(X_xor[y_xor==1, 0], X_xor[y_xor==1, 1], c='red', s=200, label='1')
ax.set_title('XOR (NENÍ lineárně separabilní!)')
ax.set_xlabel('x₁')
ax.set_ylabel('x₂')
ax.set_xlim(-0.5, 1.5)
ax.set_ylim(-0.5, 1.5)
ax.legend()
ax.grid(True, alpha=0.3)
ax.text(0.5, -0.3, 'Neexistuje žádná přímka!', ha='center', fontsize=10, color='red')

plt.tight_layout()
plt.show()

print("XOR problém ukázal limity perceptronu.")
print("Řešení: Více vrstev (multi-layer perceptron)!")

XOR problém ukázal limity perceptronu.
Řešení: Více vrstev (multi-layer perceptron)!

23.6 Perceptron v PyTorch

import torch
import torch.nn as nn

# Definice perceptronu jako PyTorch modul
class Perceptron(nn.Module):
    def __init__(self, input_size):
        super().__init__()
        self.linear = nn.Linear(input_size, 1)
        self.activation = nn.Sigmoid()

    def forward(self, x):
        z = self.linear(x)
        return self.activation(z)

# Vytvoření a test
torch.manual_seed(42)
model = Perceptron(input_size=2)

# Test
x_test = torch.tensor([[1.0, 0.5]])
output = model(x_test)

print("Perceptron v PyTorch:")
print(f"Vstup: {x_test.numpy()}")
print(f"Váhy: {model.linear.weight.data.numpy()}")
print(f"Bias: {model.linear.bias.data.numpy()}")
print(f"Výstup: {output.item():.4f}")
Perceptron v PyTorch:
Vstup: [[1.  0.5]]
Váhy: [[0.5406104 0.5869042]]
Bias: [-0.16565566]
Výstup: 0.6611

23.6.1 Trénování perceptronu v PyTorch

# Data
import numpy as np
import matplotlib.pyplot as plt

X_tensor = torch.FloatTensor(X)
y_tensor = torch.FloatTensor(y).unsqueeze(1)

# Model, loss, optimizer
model = Perceptron(input_size=2)
criterion = nn.BCELoss()  # Binary Cross-Entropy
optimizer = torch.optim.SGD(model.parameters(), lr=0.1)

# Trénink
losses = []
for epoch in range(100):
    # Forward
    y_pred = model(X_tensor)
    loss = criterion(y_pred, y_tensor)

    # Backward
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()

    losses.append(loss.item())

# Výsledky
with torch.no_grad():
    predictions = (model(X_tensor) > 0.5).float()
    accuracy = (predictions == y_tensor).float().mean()

print(f"Přesnost: {accuracy.item():.2%}")

# Vizualizace
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 5))

ax1.plot(losses, 'b-', lw=2)
ax1.set_xlabel('Epocha')
ax1.set_ylabel('Loss')
ax1.set_title('Trénink perceptronu v PyTorch')
ax1.grid(True, alpha=0.3)

# Rozhodovací hranice
w = model.linear.weight.data.numpy()[0]
b = model.linear.bias.data.numpy()[0]

ax2.scatter(X_class0[:, 0], X_class0[:, 1], c='blue', label='Třída 0', alpha=0.6)
ax2.scatter(X_class1[:, 0], X_class1[:, 1], c='red', label='Třída 1', alpha=0.6)

x_line = np.linspace(-5, 5, 100)
# sigmoid(wx + b) = 0.5 => wx + b = 0
y_line = -(w[0] * x_line + b) / w[1]
ax2.plot(x_line, y_line, 'g-', lw=2, label='Rozhodovací hranice')

ax2.set_xlabel('x₁')
ax2.set_ylabel('x₂')
ax2.set_title(f'Naučená hranice (accuracy: {accuracy.item():.0%})')
ax2.legend()
ax2.set_xlim(-5, 5)
ax2.set_ylim(-5, 5)
ax2.grid(True, alpha=0.3)

plt.tight_layout()
plt.show()
Přesnost: 99.50%

23.7 Řešené příklady

23.7.1 Příklad 1: Ruční výpočet perceptronu

Zadání: Pro perceptron s \(w = [0.5, -0.2]\) a \(b = 0.1\) spočítejte výstup pro \(x = [1, 2]\) s sigmoid aktivací.

Řešení:

import numpy as np

w = np.array([0.5, -0.2])
b = 0.1
x = np.array([1, 2])

# Krok 1: Vážený součet
z = np.dot(w, x) + b
print(f"Krok 1: z = w·x + b = {w[0]}×{x[0]} + {w[1]}×{x[1]} + {b}")
print(f"        z = {w[0]*x[0]} + {w[1]*x[1]} + {b} = {z}")

# Krok 2: Aktivace
sigmoid = 1 / (1 + np.exp(-z))
print(f"\nKrok 2: σ(z) = 1/(1 + e^(-{z:.1f})) = {sigmoid:.4f}")

print(f"\nVýstup perceptronu: {sigmoid:.4f}")
print(f"Klasifikace (práh 0.5): třída {1 if sigmoid >= 0.5 else 0}")
Krok 1: z = w·x + b = 0.5×1 + -0.2×2 + 0.1
        z = 0.5 + -0.4 + 0.1 = 0.19999999999999998

Krok 2: σ(z) = 1/(1 + e^(-0.2)) = 0.5498

Výstup perceptronu: 0.5498
Klasifikace (práh 0.5): třída 1

23.7.2 Příklad 2: Logické hradlo AND

Zadání: Najděte váhy perceptronu, který implementuje logické AND.

Řešení:

# AND: (0,0)->0, (0,1)->0, (1,0)->0, (1,1)->1
import numpy as np

X_and = np.array([[0, 0], [0, 1], [1, 0], [1, 1]])
y_and = np.array([0, 0, 0, 1])

# Trénování
w, b, _ = train_perceptron(X_and, y_and, lr=0.1, n_epochs=100)

print(f"AND hradlo:")
print(f"Váhy: w = {w}")
print(f"Bias: b = {b}")

# Test
print("\nTest:")
for xi, yi in zip(X_and, y_and):
    z = np.dot(w, xi) + b
    pred = 1 if z >= 0 else 0
    print(f"  {xi[0]} AND {xi[1]} = {pred} (očekáváno: {yi})")
Konvergence po 4 epochách!
AND hradlo:
Váhy: w = [0.2 0.1]
Bias: b = -0.20000000000000004

Test:
  0 AND 0 = 0 (očekáváno: 0)
  0 AND 1 = 0 (očekáváno: 0)
  1 AND 0 = 0 (očekáváno: 0)
  1 AND 1 = 1 (očekáváno: 1)

23.7.3 Příklad 3: Rozhodovací hranice

Zadání: Pro perceptron s \(w = [2, -1]\) a \(b = 1\) nakreslete rozhodovací hranici.

Řešení:

import numpy as np
import matplotlib.pyplot as plt

w = np.array([2, -1])
b = 1

# Rozhodovací hranice: w·x + b = 0
# 2*x1 - x2 + 1 = 0
# x2 = 2*x1 + 1

x1 = np.linspace(-3, 3, 100)
x2 = 2 * x1 + 1

plt.figure(figsize=(8, 8))
plt.plot(x1, x2, 'g-', lw=2, label='Rozhodovací hranice: 2x₁ - x₂ + 1 = 0')

# Oblasti
plt.fill_between(x1, x2, 10, alpha=0.3, color='red', label='Třída 1 (z ≥ 0)')
plt.fill_between(x1, -10, x2, alpha=0.3, color='blue', label='Třída 0 (z < 0)')

# Testovací body
test_points = [(0, 0), (1, 1), (-1, 0), (2, 3)]
for px, py in test_points:
    z = w[0]*px + w[1]*py + b
    color = 'red' if z >= 0 else 'blue'
    plt.scatter([px], [py], c=color, s=100, edgecolors='black', zorder=5)
    plt.annotate(f'({px},{py})\nz={z}', (px, py), textcoords="offset points",
                 xytext=(10, 10), fontsize=9)

plt.xlabel('x₁')
plt.ylabel('x₂')
plt.title('Rozhodovací hranice perceptronu')
plt.legend()
plt.xlim(-3, 3)
plt.ylim(-3, 5)
plt.grid(True, alpha=0.3)
plt.show()

23.7.4 Příklad 4: Vliv learning rate

Zadání: Ukažte vliv learning rate na konvergenci perceptronu.

Řešení:

import matplotlib.pyplot as plt

learning_rates = [0.01, 0.1, 0.5, 1.0]
results = {}

for lr in learning_rates:
    _, _, history = train_perceptron(X, y, lr=lr, n_epochs=50)
    results[lr] = history['errors']

plt.figure(figsize=(10, 5))
for lr, errors in results.items():
    plt.plot(errors, label=f'lr = {lr}', lw=2)

plt.xlabel('Epocha')
plt.ylabel('Počet chyb')
plt.title('Vliv learning rate na konvergenci')
plt.legend()
plt.grid(True, alpha=0.3)
plt.show()
Konvergence po 3 epochách!
Konvergence po 3 epochách!
Konvergence po 3 epochách!
Konvergence po 3 epochách!

23.8 Cvičení

PoznámkaCvičení 1: Logické hradlo OR

Natrénujte perceptron pro logické hradlo OR. Jaké jsou naučené váhy?

PoznámkaCvičení 2: Logické hradlo NAND

Natrénujte perceptron pro NAND (NOT AND). Jak se liší od AND?

PoznámkaCvičení 3: XOR pomocí více perceptronů

XOR nelze řešit jedním perceptronem, ale lze ho rozložit: XOR = (A OR B) AND NOT(A AND B). Implementujte XOR jako kombinaci tří perceptronů.

PoznámkaCvičení 4: Klasifikace IRIS

Použijte perceptron pro binární klasifikaci na datasetu Iris (jen dvě třídy). Jaká je dosažená přesnost?

PoznámkaCvičení 5: Vizualizace učení

Vytvořte animaci, která ukáže, jak se rozhodovací hranice perceptronu mění během tréninku.

23.9 Shrnutí

TipCo jsme se naučili
  1. Perceptron je základní stavební blok neuronových sítí
  2. Vážený součet: \(z = \mathbf{w}^T \mathbf{x} + b\)
  3. Aktivační funkce vnáší nelinearitu (sigmoid, ReLU, …)
  4. Perceptron implementuje lineární klasifikátor
  5. Perceptron learning rule konverguje pro lineárně separabilní data
  6. Limit: Perceptron nezvládne XOR a jiné nelineární problémy
  7. Řešení: Více vrstev → Multi-Layer Perceptron
DůležitéKlíčové vzorce
  • Perceptron: \(y = \sigma(\mathbf{w}^T \mathbf{x} + b)\)
  • Sigmoid: \(\sigma(z) = \frac{1}{1 + e^{-z}}\)
  • ReLU: \(\sigma(z) = \max(0, z)\)
  • Update: \(w \leftarrow w + \eta (y - \hat{y}) x\)

V další kapitole se podíváme na vícevrstvé sítě (Multi-Layer Perceptrons), které překonávají limity jednoduchého perceptronu a dokážou aproximovat libovolnou funkci.