Part 03 · Deep Learning
Neural Networks and Perceptrons
একটা neuron মানে weighted sum আর একটা switch। এগুলো layer এ সাজাও, activation function যোগ করো, তাহলে এমন আকার আঁকা যায় যেটা কোনো সোজা line পারে না।
⏱ 1-2 ঘণ্টা · Station 16 / 92
জিনিসটা কী, কেন দরকার
Logistic regression data র মধ্য দিয়ে একটা সোজা লাইন টানে: লাইনের এক পাশে সব "হ্যাঁ", অন্য পাশে সব "না"। অনেক আসল problem সোজা লাইন দিয়ে ভাগ হয় না। এই pixel টা কি চেহারার অংশ? এই কথাটা কি ব্যঙ্গ? Answer নির্ভর করে input গুলোর combination এর উপর, তাদের weight দেওয়া যোগফলের উপর না।
Neural network সহজ unit গুলো স্তরে স্তরে সাজায় যাতে combination গুলো শেখা যায়। প্রতিটা unit, মানে neuron, প্রায় কিছুই করে না: একটা weight দেওয়া যোগফল আর একটা switch। কিন্তু এদের layer, আর layer গুলোর মাঝে একটা non-linear switch, মিলে যেকোনো আকার আঁকতে পারে। এখান থেকে সামনের সব model এর ভিত্তি এটাই, LLM এর ভেতরের transformer সহ।
ভেতরে কীভাবে চলে
একটা neuron (perceptron)। Input x, weight w, bias b:
z = w1·x1 + w2·x2 + ... + b (the weighted sum, exactly like logistic regression)
output = activation(z) (the switch)
একটা neuron একটা লাইন টানে। AND শিখতে পারে ("দুইটাই on"), কিন্তু XOR ("ঠিক একটা on") পারে না: এমন কোনো একটা সোজা লাইন নেই যেটা (0,1) আর (1,0) কে এক পাশে আর (0,0) আর (1,1) কে অন্য পাশে রাখে। 1969 এ দেখানো এই সীমাবদ্ধতা neural network এর গবেষণা বছরের পর বছর আটকে রেখেছিল।
Layer। কয়েকটা neuron এর output আরো neuron এ পাঠাও। প্রথম layer (একটা hidden layer) সহজ pattern ধরতে পারে, "অন্তত একটা input on" আর "দুইটাই on", আর পরের layer সেগুলো জোড়া দেয়: "অন্তত একটা, কিন্তু দুইটা না" মানেই XOR। প্রতিটা layer হলো একটা matrix multiply (Part 1 থেকে), তারপর একটা activation।
Activation function ই depth কে কাজের করে। এগুলো ছাড়া layer এর স্তূপ মানে matrix multiply এর স্তূপ, যেটা মিলে একটাই matrix multiply হয়ে যায়: যত layer ই যোগ করো, আবার সেই এক সোজা লাইন। Common গুলো:
| Activation | Formula | কোথায় |
|---|---|---|
| ReLU | max(0, z) | hidden layer; default: সস্তা আর ভালো train হয় |
| GELU | মসৃণ একটা ReLU | transformer এর hidden layer |
| sigmoid | 1 / (1 + e^−z) | একটা হ্যাঁ/না output |
| softmax | e^zᵢ / Σ e^zⱼ | অনেক class থেকে একটা বাছার শেষ layer |
সাইজ। 784 input আর 128 neuron এর একটা layer এ 784 × 128 টা weight আর 128 টা bias: 100,480 টা parameter। Network এর শক্তি, আর খরচও, আসে এই সংখ্যাগুলো থেকে।
5 টা hidden layer এর একটা network বানালে, কিন্তু activation function দিতে ভুলে গেলে, তাই প্রতিটা layer শুধু matrix multiply আর bias। এটা কী শিখতে পারবে?
ছবিতে দেখো
Code এ XOR
Perceptron rule দিয়ে AND আর XOR এ train করা একটা neuron, তারপর হাতে weight বসানো ReLU সহ দুই layer এর network যেটা সত্যিই XOR solve করে। তারপর activation সরিয়ে একই network, আর শেষে তিনটা score এ softmax।
import math
INPUTS = [(0, 0), (0, 1), (1, 0), (1, 1)]
AND = [0, 0, 0, 1]
XOR = [0, 1, 1, 0]
def step(z):
return 1 if z > 0 else 0
def train_perceptron(targets, epochs=20):
w1 = w2 = b = 0.0
for _ in range(epochs):
for (x1, x2), y in zip(INPUTS, targets):
err = y - step(w1 * x1 + w2 * x2 + b) # perceptron rule: nudge weights only when wrong
w1 += 0.1 * err * x1
w2 += 0.1 * err * x2
b += 0.1 * err
preds = [step(w1 * x1 + w2 * x2 + b) for x1, x2 in INPUTS]
return preds, sum(p == y for p, y in zip(preds, targets))
for name, targets in (("AND", AND), ("XOR", XOR)):
preds, ok = train_perceptron(targets)
print(f"one neuron learning {name}: predictions {preds}, {ok}/4 right")
# Two layers with ReLU, weights set by hand: h1 = "at least one is on", h2 = "both are on".
def relu(z):
return max(0.0, z)
print("\ntwo-layer network on XOR")
for x1, x2 in INPUTS:
h1 = relu(x1 + x2) # 0, 1, 1, 2
h2 = relu(x1 + x2 - 1) # 0, 0, 0, 1
out = h1 - 2 * h2 # 0, 1, 1, 0
print(f" in ({x1}, {x2}) hidden ({h1:.0f}, {h2:.0f}) out {out:.0f}")
# Without the activation, two layers collapse into one straight line.
print("\nsame network, activation removed")
for x1, x2 in INPUTS:
h1, h2 = x1 + x2, x1 + x2 - 1
print(f" in ({x1}, {x2}) out {h1 - 2 * h2:+.0f}")
# Softmax turns the last layer's scores into probabilities over classes.
scores = [2.0, 0.5, -1.0]
exps = [math.exp(s) for s in scores]
print("\nsoftmax", [round(e / sum(exps), 3) for e in exps])package main
import (
"fmt"
"math"
"strings"
)
var inputs = [][2]float64{{0, 0}, {0, 1}, {1, 0}, {1, 1}}
func step(z float64) int {
if z > 0 {
return 1
}
return 0
}
func trainPerceptron(targets []int) ([]int, int) {
var w1, w2, b float64
for e := 0; e < 20; e++ {
for i, x := range inputs {
err := float64(targets[i] - step(w1*x[0]+w2*x[1]+b)) // perceptron rule: nudge weights only when wrong
w1 += 0.1 * err * x[0]
w2 += 0.1 * err * x[1]
b += 0.1 * err
}
}
preds, ok := make([]int, 4), 0
for i, x := range inputs {
preds[i] = step(w1*x[0] + w2*x[1] + b)
if preds[i] == targets[i] {
ok++
}
}
return preds, ok
}
func list[T any](xs []T, f string) string {
parts := make([]string, len(xs))
for i, x := range xs {
parts[i] = fmt.Sprintf(f, x)
}
return "[" + strings.Join(parts, ", ") + "]"
}
func relu(z float64) float64 { return math.Max(0, z) }
func main() {
for _, t := range []struct {
name string
targets []int
}{{"AND", []int{0, 0, 0, 1}}, {"XOR", []int{0, 1, 1, 0}}} {
preds, ok := trainPerceptron(t.targets)
fmt.Printf("one neuron learning %s: predictions %s, %d/4 right\n", t.name, list(preds, "%d"), ok)
}
// Two layers with ReLU, weights set by hand: h1 = "at least one is on", h2 = "both are on".
fmt.Println("\ntwo-layer network on XOR")
for _, x := range inputs {
h1 := relu(x[0] + x[1])
h2 := relu(x[0] + x[1] - 1)
fmt.Printf(" in (%.0f, %.0f) hidden (%.0f, %.0f) out %.0f\n", x[0], x[1], h1, h2, h1-2*h2)
}
// Without the activation, two layers collapse into one straight line.
fmt.Println("\nsame network, activation removed")
for _, x := range inputs {
h1, h2 := x[0]+x[1], x[0]+x[1]-1
fmt.Printf(" in (%.0f, %.0f) out %+.0f\n", x[0], x[1], h1-2*h2)
}
// Softmax turns the last layer's scores into probabilities over classes.
scores := []float64{2.0, 0.5, -1.0}
sum := 0.0
for _, s := range scores {
sum += math.Exp(s)
}
probs := make([]float64, 3)
for i, s := range scores {
probs[i] = math.Exp(s) / sum
}
fmt.Println("\nsoftmax", list(probs, "%.3f"))
}Output:
one neuron learning AND: predictions [0, 0, 0, 1], 4/4 right
one neuron learning XOR: predictions [1, 1, 0, 0], 2/4 right
two-layer network on XOR
in (0, 0) hidden (0, 0) out 0
in (0, 1) hidden (1, 0) out 1
in (1, 0) hidden (1, 0) out 1
in (1, 1) hidden (2, 1) out 0
same network, activation removed
in (0, 0) out +2
in (0, 1) out +1
in (1, 0) out +1
in (1, 1) out +0
softmax [0.786, 0.175, 0.039]
কী দেখলাম:
- একটা neuron AND নিখুঁত শেখে (4/4), আর XOR এ ফেল করে (2/4, আন্দাজের চেয়ে ভালো না), যত লম্বাই train করো। এটা সোজা লাইনের সীমা, training এর সমস্যা না।
- ReLU সহ দুই layer চারটা input এই XOR ঠিক করে। Hidden মানগুলো দেখো: h1 গোনে কয়টা input on (0, 1, 1, 2), h2 জ্বলে শুধু দুইটাই on থাকলে (0, 0, 0, 1)। Output h1 − 2·h2 এগুলোকে বানায় 0, 1, 1, 0। Hidden layer নতুন feature বানিয়েছে; output সেগুলো জোড়া দিয়েছে।
- Activation সরালে output হয় +2, +1, +1, +0: একটা সোজা লাইন, 2 − x1 − x2। XOR এর আকার হারিয়ে গেল। ReLU র ওই এক লাইনই পুরো পার্থক্য।
- Softmax score 2.0, 0.5, −1.0 কে বানায় probability 0.786, 0.175, 0.039, যোগ করলে 1।
এখানে weight হাতে বসিয়েছি কারণ XOR যথেষ্ট ছোট। আসল problem এ কেউ পারে না: পরের lesson দেখাবে network কীভাবে নিজেই এগুলো খুঁজে বের করে।
Production এ যা মাথায় রাখবে
- Width আর depth একটা বাজেট। বেশি neuron আর layer আরো জটিল pattern ধরতে পারে, কিন্তু প্রতিটা parameter এর memory লাগে, inference এ compute লাগে, আর overfit না করে fit করতে training data লাগে। ছোট দিয়ে শুরু করো, validation এর উন্নতি থামা পর্যন্ত বাড়াও।
- মরা ReLU। যে ReLU র input প্রতিটা example এ negative, সে চিরকাল 0 দেয় আর শেখা বন্ধ করে দেয়। বেশি learning rate এর কারণ। Leaky ReLU বা GELU (শূন্যের নিচে ছোট একটা ঢাল) এটা এড়ায়।
- সংখ্যার নিরাপত্তা। বড় score এ softmax overflow করে; আসল code আগে সবচেয়ে বড় score বিয়োগ করে নেয় (Part 1)। Framework এর একসাথে softmax আর cross-entropy ওয়ালা loss ব্যবহার করো, এটা নিজেই করে দেয়।
- সবসময় neural net না। Row আর column এর data তে প্রায়ই gradient-boosted tree জেতে (Part 2)। Neural network চমকায় ছবি, audio, text আর গঠন ওয়ালা data তে, যেটা এই part এর বাকি অংশে আছে।
এক কথায়
Neuron হলো weight দেওয়া যোগফল আর একটা activation; একটা neuron একটা লাইন টানে। Non-linear activation (ReLU) সহ layer চাপালে network নতুন feature বানাতে আর যেকোনো আকার আঁকতে পারে; activation ছাড়া যত layer ই হোক, সব মিলে একটা।
নিজে করে দেখো
হাতে দুই layer এর একটা ReLU network design করো যেটা XNOR এর জন্য 1 দেয় (দুইটা input সমান হলে 1, না হলে 0)। Hint: XNOR = 1 − XOR। তারপর 784 input, 128 এর একটা hidden layer আর 10 output ওয়ালা network এর parameter গোনো।
Answer
XOR এর hidden layer টাই রাখো (h1 = ReLU(x1 + x2), h2 = ReLU(x1 + x2 − 1)), শুধু output বদলাও: out = 1 − h1 + 2·h2, মানে weight −1 আর +2, bias 1। এটা দেয় 1, 0, 0, 1। Parameter: hidden layer এ 784 × 128 + 128 = 100,480, output এ 128 × 10 + 10 = 1,290, মোট 101,770। এই part এর শেষের project এ ঠিক এই network টাই হাতে লেখা digit এ train করবে।
Station stamp
Chapter শেষ করো
পড়া শেষ হলে Complete চাপো, progress save হবে। XP শুধু Pro তে — Pro থাকলে এই chapter এ +10 XP পেতে।
Pro নিয়ে XP পাও →