📖 একটি ছোট গল্প
১৯৮৬ — Rumelhart, Hinton, Williams একটি পেপারে দেখালেন কীভাবে error-কে network-এর শেষ থেকে শুরু পর্যন্ত "উল্টোপথে" পাঠানো যায়। এক রাতের মধ্যে neural network জেগে উঠল। সেটাই Backpropagation।
মূল আইডিয়া
Chain Rule প্রয়োগ করে loss-এর gradient সব weight-এ পৌঁছানো। শেষ layer থেকে শুরু করে পেছনে এক step করে যাই।
Four Equations
δ⁽ᴸ⁾ = ∇_a L ⊙ σ'(z⁽ᴸ⁾)
δ⁽ℓ⁾ = (W⁽ℓ⁺¹⁾ᵀ δ⁽ℓ⁺¹⁾) ⊙ σ'(z⁽ℓ⁾)
∂L/∂W⁽ℓ⁾ = a⁽ℓ⁻¹⁾ δ⁽ℓ⁾ᵀ
∂L/∂b⁽ℓ⁾ = δ⁽ℓ⁾
এই চারটি সমীকরণই Deep Learning-এর হৃদয়।
Softmax + CrossEntropy Shortcut
সবচেয়ে সুন্দর simplification:
δ⁽ᴸ⁾ = ŷ − y
এই trick-এর জন্যই classification networks-এ Softmax+CE pair করে ব্যবহার হয়।
Python Implementation
pythonPython · NumPy
import numpy as np
def relu(z): return np.maximum(0, z)
def relu_grad(z): return (z > 0).astype(z.dtype)
def softmax(z):
e = np.exp(z - z.max(-1, keepdims=True))
return e / e.sum(-1, keepdims=True)
np.random.seed(1)
X = np.random.randn(64, 20)
y = np.random.randint(0, 5, 64)
Y = np.eye(5)[y]
W1 = np.random.randn(20, 16) * 0.1; b1 = np.zeros((1,16))
W2 = np.random.randn(16, 5) * 0.1; b2 = np.zeros((1, 5))
for step in range(2000):
# forward
Z1 = X @ W1 + b1; A1 = relu(Z1)
Z2 = A1 @ W2 + b2; A2 = softmax(Z2)
loss = -np.log(A2[np.arange(64), y] + 1e-12).mean()
# backward
dZ2 = (A2 - Y) / 64 # softmax+CE shortcut
dW2 = A1.T @ dZ2; db2 = dZ2.sum(0, keepdims=True)
dA1 = dZ2 @ W2.T
dZ1 = dA1 * relu_grad(Z1)
dW1 = X.T @ dZ1; db1 = dZ1.sum(0, keepdims=True)
# SGD update
for p, g in [(W1,dW1),(b1,db1),(W2,dW2),(b2,db2)]:
p -= 0.1 * g
if step % 400 == 0:
print(f"step {step:4d} loss {loss:.4f}")Gradient Checking
Numerical vs analytical gradient তুলনা — debug-এর সেরা ব্যবস্থা:
(L(θ+ε) − L(θ−ε)) / (2ε) ≈ ∂L/∂θ
Relative error < 10⁻⁷ = ✓; > 10⁻⁴ = bug।
Summary · সারসংক্ষেপ
- Backprop = Chain Rule + dynamic programming।
- চারটি সমীকরণ মুখস্থ না করে derive করতে শিখুন।
- Softmax+CE → δ = ŷ − y।
- Gradient check ছাড়া custom layer কখনো trust করবেন না।