29 Řešení cvičení
Tato příloha obsahuje řešení vybraných cvičení z jednotlivých kapitol.
29.1 Část 0: Začínáme s Pythonem
29.1.1 Kapitola 0.1: Instalace a první kroky
Cvičení 1: Převod teplot
def celsius_to_fahrenheit(c):
return c * 9/5 + 32
# Test
print(celsius_to_fahrenheit(0)) # 32
print(celsius_to_fahrenheit(100)) # 212
print(celsius_to_fahrenheit(37)) # 98.6Cvičení 2: BMI kalkulačka
def bmi(vaha_kg, vyska_m):
return vaha_kg / (vyska_m ** 2)
# Test
print(f"BMI: {bmi(70, 1.75):.1f}") # BMI: 22.929.1.2 Kapitola 0.2: Základy programování
Cvičení 1: Součet sudých čísel
def suma_sudych(n):
return sum(x for x in range(1, n+1) if x % 2 == 0)
# Alternativně
def suma_sudych_v2(n):
return sum(range(2, n+1, 2))
print(suma_sudych(10)) # 30 (2+4+6+8+10)Cvičení 2: Nalezení maxima
def najdi_max(seznam):
if not seznam:
return None
maximum = seznam[0]
for x in seznam:
if x > maximum:
maximum = x
return maximum
print(najdi_max([3, 1, 4, 1, 5, 9, 2, 6])) # 929.2 Část I: Funkce a grafy
29.2.1 Kapitola 1: Souřadnicový systém
Cvičení 1: Vzdálenost bodů
import numpy as np
def vzdalenost(A, B):
"""Euklidovská vzdálenost mezi body A a B."""
return np.sqrt((B[0] - A[0])**2 + (B[1] - A[1])**2)
A = (1, 2)
B = (4, 6)
print(f"Vzdálenost: {vzdalenost(A, B)}") # 5.0Cvičení 2: Střed úsečky
def stred(A, B):
"""Střed úsečky AB."""
return ((A[0] + B[0]) / 2, (A[1] + B[1]) / 2)
print(stred((0, 0), (4, 6))) # (2.0, 3.0)29.2.2 Kapitola 2: Co je funkce
Cvičení 1: Tabulka hodnot funkce
def tabulka(f, a, b, n=10):
"""Vytvoří tabulku hodnot funkce f na intervalu [a, b]."""
x = np.linspace(a, b, n)
for xi in x:
print(f"f({xi:.2f}) = {f(xi):.4f}")
# Příklad použití
tabulka(lambda x: x**2, 0, 5)Cvičení 2: Inverzní funkce
# f(x) = 2x + 3
# y = 2x + 3
# x = (y - 3) / 2
# f^(-1)(y) = (y - 3) / 2
def f(x):
return 2*x + 3
def f_inv(y):
return (y - 3) / 2
# Ověření: f(f_inv(y)) = y
y = 10
print(f"f(f_inv({y})) = {f(f_inv(y))}") # 10.029.2.3 Kapitola 3: Lineární funkce
Cvičení 1: Rovnice přímky ze dvou bodů
def primka_z_bodu(A, B):
"""Vrátí koeficienty a, b přímky y = ax + b procházející body A, B."""
x1, y1 = A
x2, y2 = B
a = (y2 - y1) / (x2 - x1)
b = y1 - a * x1
return a, b
A = (1, 2)
B = (3, 6)
a, b = primka_z_bodu(A, B)
print(f"y = {a}x + {b}") # y = 2.0x + 0.0Cvičení 2: Průsečík přímek
def prusecik(a1, b1, a2, b2):
"""Průsečík přímek y = a1*x + b1 a y = a2*x + b2."""
if a1 == a2:
return None # Rovnoběžné
x = (b2 - b1) / (a1 - a2)
y = a1 * x + b1
return (x, y)
# y = 2x + 1 a y = -x + 4
print(prusecik(2, 1, -1, 4)) # (1.0, 3.0)29.2.4 Kapitola 4: Nelineární funkce
Cvičení 1: Vrchol paraboly
def vrchol_paraboly(a, b, c):
"""Vrchol paraboly y = ax^2 + bx + c."""
x_v = -b / (2*a)
y_v = a * x_v**2 + b * x_v + c
return (x_v, y_v)
# y = x^2 - 4x + 3
print(vrchol_paraboly(1, -4, 3)) # (2.0, -1.0)Cvičení 2: Zdvojovací čas
# Exponenciální růst: y = y0 * 2^(t/T)
# kde T je zdvojovací čas
# Pro y = y0 * e^(kt), zdvojovací čas je T = ln(2) / k
import numpy as np
def zdvojovaci_cas(k):
"""Zdvojovací čas pro exponenciální růst e^(kt)."""
return np.log(2) / k
# Příklad: růst 5% ročně = e^(0.05*t)
print(f"Zdvojovací čas: {zdvojovaci_cas(0.05):.2f} let") # ~13.86 let29.3 Část II: Vektory a matice
29.3.1 Kapitola 5: Vektory
Cvičení 1: Délka vektoru
import numpy as np
def delka(v):
"""Euklidovská délka (L2 norma) vektoru."""
return np.sqrt(np.sum(v**2))
v = np.array([3, 4])
print(f"Délka: {delka(v)}") # 5.0Cvičení 2: Jednotkový vektor
def jednotkovy(v):
"""Normalizace vektoru na délku 1."""
return v / np.linalg.norm(v)
v = np.array([3, 4])
u = jednotkovy(v)
print(f"Jednotkový: {u}") # [0.6, 0.8]
print(f"Délka: {np.linalg.norm(u)}") # 1.029.3.2 Kapitola 6: Operace s vektory
Cvičení 1: Úhel mezi vektory
def uhel(u, v):
"""Úhel mezi vektory ve stupních."""
cos_theta = np.dot(u, v) / (np.linalg.norm(u) * np.linalg.norm(v))
return np.degrees(np.arccos(np.clip(cos_theta, -1, 1)))
u = np.array([1, 0])
v = np.array([1, 1])
print(f"Úhel: {uhel(u, v):.1f}°") # 45.0°Cvičení 2: Kosínová podobnost
def kosinova_podobnost(u, v):
"""Kosínová podobnost mezi vektory."""
return np.dot(u, v) / (np.linalg.norm(u) * np.linalg.norm(v))
# Podobné vektory
a = np.array([1, 2, 3])
b = np.array([2, 4, 6])
print(f"Podobnost: {kosinova_podobnost(a, b):.4f}") # 1.0
# Kolmé vektory
c = np.array([1, 0])
d = np.array([0, 1])
print(f"Podobnost: {kosinova_podobnost(c, d):.4f}") # 0.029.3.3 Kapitola 7: Matice
Cvičení 1: Součet řádků a sloupců
A = np.array([
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
])
print("Součet řádků:", np.sum(A, axis=1)) # [6, 15, 24]
print("Součet sloupců:", np.sum(A, axis=0)) # [12, 15, 18]Cvičení 2: Diagonální prvky
A = np.array([
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
])
print("Hlavní diagonála:", np.diag(A)) # [1, 5, 9]
print("Vedlejší diagonála:", np.diag(np.fliplr(A))) # [3, 5, 7]
print("Stopa matice:", np.trace(A)) # 1529.3.4 Kapitola 8: Násobení matic
Cvičení 1: Ruční násobení
A = np.array([[1, 2], [3, 4]])
B = np.array([[5, 6], [7, 8]])
# Ruční výpočet
C = np.zeros((2, 2))
for i in range(2):
for j in range(2):
for k in range(2):
C[i, j] += A[i, k] * B[k, j]
print("Ruční výpočet:")
print(C)
# Ověření
print("NumPy:")
print(A @ B)Cvičení 2: Asociativita
A = np.random.randn(3, 4)
B = np.random.randn(4, 2)
C = np.random.randn(2, 5)
# (AB)C = A(BC)
vysledek1 = (A @ B) @ C
vysledek2 = A @ (B @ C)
print("Rozdíl:", np.max(np.abs(vysledek1 - vysledek2))) # ~0 (numerická chyba)29.3.5 Kapitola 9: Lineární transformace
Cvičení 1: Rotační matice
def rotace_matice(uhel_stupne):
"""Matice rotace o daný úhel."""
theta = np.radians(uhel_stupne)
return np.array([
[np.cos(theta), -np.sin(theta)],
[np.sin(theta), np.cos(theta)]
])
# Rotace o 90°
R = rotace_matice(90)
v = np.array([1, 0])
print(f"Rotovaný vektor: {R @ v}") # [0, 1]Cvičení 2: Škálování
def skalovani_matice(sx, sy):
"""Matice škálování."""
return np.array([
[sx, 0],
[0, sy]
])
S = skalovani_matice(2, 3)
v = np.array([1, 1])
print(f"Škálovaný vektor: {S @ v}") # [2, 3]29.4 Část III: Derivace a gradient
29.4.1 Kapitola 10: Změna a rychlost změny
Cvičení 1: Numerická derivace
def numericka_derivace(f, x, h=1e-5):
"""Centrální diference."""
return (f(x + h) - f(x - h)) / (2 * h)
# f(x) = x^2, f'(x) = 2x
f = lambda x: x**2
x = 3
print(f"Numerická derivace: {numericka_derivace(f, x):.6f}") # ~6.0
print(f"Analytická derivace: {2*x}") # 6Cvičení 2: Průměrná rychlost
def prumerna_rychlost(f, a, b):
"""Průměrná rychlost změny funkce f na intervalu [a, b]."""
return (f(b) - f(a)) / (b - a)
# Příklad: dráha s(t) = t^2, průměrná rychlost na [0, 2]
s = lambda t: t**2
print(f"Průměrná rychlost: {prumerna_rychlost(s, 0, 2)} m/s") # 2.029.4.2 Kapitola 11: Pravidla derivování
Cvičení 1: Derivace polynomu
def derivace_polynomu(koeficienty):
"""Derivace polynomu zadaného koeficienty [a_0, a_1, ..., a_n]."""
n = len(koeficienty)
return [i * koeficienty[i] for i in range(1, n)]
# f(x) = 3 + 2x + x^2 = [3, 2, 1]
# f'(x) = 2 + 2x = [2, 2]
print(derivace_polynomu([3, 2, 1])) # [2, 2]Cvičení 2: Řetízkové pravidlo
# f(x) = sin(x^2)
# f'(x) = cos(x^2) * 2x
import numpy as np
def f(x):
return np.sin(x**2)
def f_derivace(x):
return np.cos(x**2) * 2*x
x = 1
print(f"Analytická: {f_derivace(x):.6f}")
print(f"Numerická: {numericka_derivace(f, x):.6f}")29.4.3 Kapitola 12: Funkce více proměnných
Cvičení 1: Parciální derivace
# f(x, y) = x^2 + xy + y^2
# ∂f/∂x = 2x + y
# ∂f/∂y = x + 2y
def f(x, y):
return x**2 + x*y + y**2
def grad_f(x, y):
return np.array([2*x + y, x + 2*y])
x, y = 1, 2
print(f"Gradient: {grad_f(x, y)}") # [4, 5]Cvičení 2: Numerický gradient
def numerick_gradient(f, point, h=1e-5):
"""Numerický gradient pomocí centrálních diferencí."""
grad = np.zeros_like(point)
for i in range(len(point)):
point_plus = point.copy()
point_minus = point.copy()
point_plus[i] += h
point_minus[i] -= h
grad[i] = (f(point_plus) - f(point_minus)) / (2 * h)
return grad
f = lambda p: p[0]**2 + p[1]**2
point = np.array([3.0, 4.0])
print(f"Gradient: {numerick_gradient(f, point)}") # [6, 8]29.4.4 Kapitola 13: Automatická derivace
Cvičení 1: PyTorch autograd
import torch
x = torch.tensor([2.0], requires_grad=True)
y = torch.tensor([3.0], requires_grad=True)
# f(x, y) = x^2 * y + y^3
z = x**2 * y + y**3
z.backward()
print(f"∂z/∂x = {x.grad.item()}") # 2*x*y = 12
print(f"∂z/∂y = {y.grad.item()}") # x^2 + 3*y^2 = 4 + 27 = 3129.5 Část IV: Pravděpodobnost a statistika
29.5.1 Kapitola 14: Náhoda a pravděpodobnost
Cvičení 1: Bayesova věta
# P(nemoc) = 0.01
# P(pozitivní|nemoc) = 0.99
# P(pozitivní|zdravý) = 0.05
# P(nemoc|pozitivní) = ?
P_nemoc = 0.01
P_zdravy = 1 - P_nemoc
P_poz_nemoc = 0.99
P_poz_zdravy = 0.05
P_poz = P_poz_nemoc * P_nemoc + P_poz_zdravy * P_zdravy
P_nemoc_poz = (P_poz_nemoc * P_nemoc) / P_poz
print(f"P(nemoc|pozitivní) = {P_nemoc_poz:.4f}") # ~0.167Cvičení 2: Monte Carlo simulace
import numpy as np
def odhadni_pi(n_vzorku):
"""Odhad π pomocí Monte Carlo."""
x = np.random.uniform(-1, 1, n_vzorku)
y = np.random.uniform(-1, 1, n_vzorku)
uvnitr = np.sum(x**2 + y**2 <= 1)
return 4 * uvnitr / n_vzorku
np.random.seed(42)
print(f"Odhad π: {odhadni_pi(100000):.4f}") # ~3.1429.5.2 Kapitola 15: Náhodné veličiny
Cvičení 1: Střední hodnota a rozptyl
import numpy as np
data = [2, 4, 4, 4, 5, 5, 7, 9]
stredni = np.mean(data)
rozptyl = np.var(data)
smerodatna = np.std(data)
print(f"Střední hodnota: {stredni}") # 5.0
print(f"Rozptyl: {rozptyl}") # 4.0
print(f"Směrodatná odchylka: {smerodatna}") # 2.0Cvičení 2: Softmax
def softmax(x):
"""Softmax funkce."""
exp_x = np.exp(x - np.max(x)) # Numerická stabilita
return exp_x / np.sum(exp_x)
logits = np.array([2.0, 1.0, 0.1])
probs = softmax(logits)
print(f"Pravděpodobnosti: {probs}")
print(f"Součet: {np.sum(probs)}") # 1.029.5.3 Kapitola 16: Normální rozdělení
Cvičení 1: Z-skóre
def z_skore(x, mu, sigma):
"""Převod na z-skóre."""
return (x - mu) / sigma
# IQ má N(100, 15^2)
mu, sigma = 100, 15
iq = 130
z = z_skore(iq, mu, sigma)
print(f"Z-skóre pro IQ {iq}: {z:.2f}") # 2.0Cvičení 2: Xavier inicializace
import numpy as np
def xavier_init(n_in, n_out):
"""Xavier inicializace vah."""
std = np.sqrt(2.0 / (n_in + n_out))
return np.random.randn(n_in, n_out) * std
W = xavier_init(784, 128)
print(f"Střední hodnota: {np.mean(W):.6f}") # ~0
print(f"Směrodatná odchylka: {np.std(W):.6f}") # ~0.04729.5.4 Kapitola 17: Informace a entropie
Cvičení 1: Entropie
def entropie(p):
"""Entropie diskrétního rozdělení."""
p = np.array(p)
p = p[p > 0] # Odstranění nul
return -np.sum(p * np.log2(p))
# Férová mince
print(f"Entropie mince: {entropie([0.5, 0.5]):.4f} bit") # 1.0
# Nefér mince
print(f"Entropie nefér: {entropie([0.9, 0.1]):.4f} bit") # ~0.47Cvičení 2: Cross-entropy loss
def cross_entropy(y_true, y_pred):
"""Cross-entropy loss."""
y_pred = np.clip(y_pred, 1e-15, 1 - 1e-15)
return -np.sum(y_true * np.log(y_pred))
# One-hot encoded: třída 2 (index 1)
y_true = np.array([0, 1, 0])
y_pred = np.array([0.1, 0.8, 0.1])
print(f"Cross-entropy: {cross_entropy(y_true, y_pred):.4f}") # ~0.22329.6 Část V: Optimalizace
29.6.1 Kapitola 18: Hledání minima
Cvičení 1: Nalezení minima paraboly
# f(x) = x^2 - 4x + 3
# f'(x) = 2x - 4 = 0 => x = 2
def f(x):
return x**2 - 4*x + 3
x_min = 2
print(f"Minimum v x = {x_min}")
print(f"f({x_min}) = {f(x_min)}") # -1Cvičení 2: Konvexnost
# Funkce f(x) = x^4 - 2x^2
# f''(x) = 12x^2 - 4
# f''(x) < 0 pro |x| < 1/√3, tedy není globálně konvexní
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(-2, 2, 100)
f = x**4 - 2*x**2
f_druhá = 12*x**2 - 4
plt.figure(figsize=(10, 4))
plt.subplot(1, 2, 1)
plt.plot(x, f)
plt.title('f(x) = x^4 - 2x^2')
plt.grid(True)
plt.subplot(1, 2, 2)
plt.plot(x, f_druhá)
plt.axhline(y=0, color='r', linestyle='--')
plt.title("f''(x) = 12x^2 - 4")
plt.grid(True)
plt.tight_layout()
plt.show()29.6.2 Kapitola 19: Gradient descent
Cvičení 1: Implementace GD
def gradient_descent(f, grad_f, x0, lr=0.1, n_iter=100):
"""Gradient descent."""
x = x0
history = [x]
for _ in range(n_iter):
x = x - lr * grad_f(x)
history.append(x)
return x, history
# f(x) = x^2, grad = 2x
f = lambda x: x**2
grad_f = lambda x: 2*x
x_min, history = gradient_descent(f, grad_f, x0=5.0, lr=0.1)
print(f"Minimum: {x_min:.6f}") # ~0Cvičení 2: Vliv learning rate
for lr in [0.01, 0.1, 0.5, 0.9]:
x_min, history = gradient_descent(f, grad_f, x0=5.0, lr=lr, n_iter=20)
print(f"LR={lr}: x={x_min:.6f}, kroků={len(history)}")29.6.3 Kapitola 20: Pokročilé optimalizátory
Cvičení 1: Momentum
def gd_momentum(grad_f, x0, lr=0.1, momentum=0.9, n_iter=100):
"""GD s momentum."""
x = x0
v = 0 # Rychlost
for _ in range(n_iter):
v = momentum * v - lr * grad_f(x)
x = x + v
return x
x_min = gd_momentum(lambda x: 2*x, x0=5.0)
print(f"Minimum s momentum: {x_min:.6f}")Cvičení 2: Adam
def adam(grad_f, x0, lr=0.001, beta1=0.9, beta2=0.999, eps=1e-8, n_iter=1000):
"""Adam optimizer."""
x = x0
m = 0 # První moment
v = 0 # Druhý moment
for t in range(1, n_iter + 1):
g = grad_f(x)
m = beta1 * m + (1 - beta1) * g
v = beta2 * v + (1 - beta2) * g**2
m_hat = m / (1 - beta1**t)
v_hat = v / (1 - beta2**t)
x = x - lr * m_hat / (np.sqrt(v_hat) + eps)
return x
x_min = adam(lambda x: 2*x, x0=5.0)
print(f"Minimum s Adam: {x_min:.6f}")29.7 Část VI: Neuronové sítě
29.7.1 Kapitola 21: Perceptron
Cvičení 1: Aktivační funkce
import numpy as np
def sigmoid(x):
return 1 / (1 + np.exp(-x))
def relu(x):
return np.maximum(0, x)
def tanh(x):
return np.tanh(x)
x = np.linspace(-5, 5, 100)
print(f"sigmoid(0) = {sigmoid(0)}") # 0.5
print(f"relu(-1) = {relu(-1)}") # 0
print(f"tanh(0) = {tanh(0)}") # 0Cvičení 2: Rozhodovací hranice
# Perceptron: y = sign(w1*x1 + w2*x2 + b)
# Rozhodovací hranice: w1*x1 + w2*x2 + b = 0
# x2 = -(w1*x1 + b) / w2
w1, w2, b = 2, -1, 1
x1 = np.linspace(-3, 3, 100)
x2 = -(w1*x1 + b) / w2
# Hranice je přímka29.7.2 Kapitola 22: Vícevrstvé sítě
Cvičení 1: Forward pass
import numpy as np
def forward(x, W1, b1, W2, b2):
"""Forward pass pro 2-vrstvou síť."""
z1 = x @ W1 + b1
h = np.maximum(0, z1) # ReLU
z2 = h @ W2 + b2
return z2
# Příklad
np.random.seed(42)
x = np.random.randn(1, 4)
W1 = np.random.randn(4, 8)
b1 = np.zeros(8)
W2 = np.random.randn(8, 2)
b2 = np.zeros(2)
output = forward(x, W1, b1, W2, b2)
print(f"Výstup: {output}")Cvičení 2: Počet parametrů
def pocet_parametru(vrstvy):
"""Spočítá počet parametrů sítě."""
total = 0
for i in range(len(vrstvy) - 1):
n_in, n_out = vrstvy[i], vrstvy[i+1]
total += n_in * n_out + n_out # váhy + bias
return total
# Síť: 784 -> 256 -> 128 -> 10
vrstvy = [784, 256, 128, 10]
print(f"Počet parametrů: {pocet_parametru(vrstvy):,}")
# 784*256 + 256 + 256*128 + 128 + 128*10 + 10 = 235,14629.7.3 Kapitola 23: Backpropagation
Cvičení 1: Gradient pro MSE
# MSE = (1/n) * sum((y - y_pred)^2)
# d(MSE)/d(y_pred) = -(2/n) * (y - y_pred)
def mse_gradient(y_true, y_pred):
n = len(y_true)
return -2/n * (y_true - y_pred)
y_true = np.array([1, 0, 1])
y_pred = np.array([0.9, 0.1, 0.8])
grad = mse_gradient(y_true, y_pred)
print(f"Gradient: {grad}")Cvičení 2: Backprop pro ReLU
def relu(x):
return np.maximum(0, x)
def relu_grad(x):
return (x > 0).astype(float)
# Příklad
x = np.array([-2, -1, 0, 1, 2])
print(f"ReLU({x}) = {relu(x)}")
print(f"ReLU'({x}) = {relu_grad(x)}")29.7.4 Kapitola 24: Úvod do transformerů
Cvičení 1: Attention
def scaled_dot_attention(Q, K, V):
"""Scaled dot-product attention."""
d_k = Q.shape[-1]
scores = Q @ K.T / np.sqrt(d_k)
weights = np.exp(scores - np.max(scores, axis=-1, keepdims=True))
weights = weights / weights.sum(axis=-1, keepdims=True)
return weights @ V
Q = np.array([[1, 0, 1]])
K = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]])
V = np.array([[1], [2], [3]])
output = scaled_dot_attention(Q, K, V)
print(f"Attention output: {output}")Cvičení 2: Pozicové kódování
def positional_encoding(seq_len, d_model):
"""Sinusoidální pozicové kódování."""
PE = np.zeros((seq_len, d_model))
position = np.arange(seq_len)[:, np.newaxis]
div_term = np.exp(np.arange(0, d_model, 2) * (-np.log(10000.0) / d_model))
PE[:, 0::2] = np.sin(position * div_term)
PE[:, 1::2] = np.cos(position * div_term)
return PE
PE = positional_encoding(10, 64)
print(f"PE shape: {PE.shape}")
print(f"PE[0, :4]: {PE[0, :4]}")29.8 Tipy pro řešení cvičení
Začněte jednoduše: Nejprve vyřešte úlohu na papíře nebo pro malý příklad.
Testujte průběžně: Ověřujte řešení na známých případech.
Vizualizujte: Kreslení grafů pomáhá pochopit problém.
Používejte NumPy: Vektorové operace jsou rychlejší a čitelnější.
Čtěte chybové hlášky: Python obvykle říká, co je špatně.
Experimentujte: Měňte parametry a pozorujte změny.