Part 01 · Mathematics for AI
Optimization
Training মানে কুয়াশার মধ্যে পাহাড় থেকে নিচে নামা। Loss function, ধাপে ধাপে gradient descent, learning rate বাছাই, আর কেন মাঝে মাঝে আটকে যায়।
⏱ 1-2 ঘণ্টা · Station 4 / 92
জিনিসটা কী, কেন দরকার
ঘন কুয়াশার মধ্যে একটা পাহাড়ের উপর দাঁড়িয়ে আছো, নামতে চাও নিচের উপত্যকায়। উপত্যকা দেখা যাচ্ছে না। শুধু পায়ের নিচের মাটি টের পাচ্ছো: কোন দিকে ঢাল নিচে নামছে, আর কতটা খাড়া। তাই নিচের দিকে এক পা দাও, আবার টের পাও, আবার এক পা। এটাই gradient descent। এই course এর প্রায় সব model এভাবেই train হয়, দুইটা সংখ্যার line fit থেকে শুরু করে কোটি কোটি weight এর LLM পর্যন্ত।
হাঁটাটা কাজ করবে কিনা, সেটা ঠিক করে তিনটা জিনিস:
- Loss function: পাহাড়ের উচ্চতা, একটা সংখ্যা যেটা বলে model কতটা ভুল।
- Gradient: পায়ের নিচের ঢাল (আগের lesson)।
- Learning rate: এক পা কত বড়।
ভেতরে কীভাবে চলে
Loss function "কতটা ভুল" কে একটা সংখ্যায় আনে। সংখ্যা predict করার সময় সাধারণত mean squared error নেওয়া হয়, মানে (prediction − answer)² এর গড়। Class বাছাইয়ের সময় লাগবে cross-entropy (Part 2)। Training মানে এমন weight খুঁজে বের করা যাতে এই সংখ্যাটা ছোট হয়।
Update এর নিয়ম। বারবার করো:
w = w − learning_rate × gradient(w)
Minus চিহ্ন ঢালের উল্টো দিকে হাঁটায়, মানে নিচের দিকে। যেখানে ঢাল খাড়া, gradient বড়, step ও বড়। নিচের কাছে gradient ছোট হয়ে আসে, তাই step নিজে থেকেই ছোট হয়।
Learning rate একমাত্র knob যেটা তুমি হাতে ঠিক করো:
- বেশি ছোট: প্রতিটা step একটুখানি, training শেষই হয় না।
- ঠিকঠাক: loss দ্রুত নামে, তারপর থিতু হয়।
- বেশি বড়: প্রতিটা step নিচ পেরিয়ে ওপাশে আরো উঁচুতে গিয়ে পড়ে। Loss এদিক ওদিক লাফায়, নয়তো infinity তে চলে যায়।
Local minima। আসল loss এর আকার সুন্দর একটা বাটির মতো না। অনেকগুলো উপত্যকা থাকতে পারে, আর gradient descent প্রথম যেটায় গড়িয়ে পড়ে সেখানেই থেমে যায়। কোথা থেকে শুরু করছো (শুরুর weights), সেটা শেষ কোথায় হবে বদলে দিতে পারে। বিশাল neural network এ এটা যতটা ভয় লাগে ততটা সমস্যা না: ওরা যেসব উপত্যকা পায় সেগুলো মোটামুটি সমান ভালো। বরং saddle point আর সমতল জায়গা, যেখানে ঢাল প্রায় শূন্য কিন্তু নিচে পৌঁছাওনি, সেগুলো training কে বেশি ধীর করে।
Model train করছো, প্রতি 100 step এ loss print হচ্ছে: 2.31, 1.40, 3.95, 18.2, 1.4e6, nan। সবচেয়ে সম্ভাব্য কারণ কী?
ছবিতে দেখো
Code এ তিনটা learning rate
আগের lesson এর এক weight এর model, w = 0 থেকে তিনটা learning rate দিয়ে train করা। তারপর দুইটা উপত্যকা ওয়ালা একটা উঁচুনিচু loss, দুইটা আলাদা জায়গা থেকে শুরু করে।
# Gradient descent on loss(w) = (w*2 - 10)^2, the one-weight model from the last lesson.
# The best w is 5. Watch three learning rates.
def loss(w):
return (2 * w - 10) ** 2
def grad(w):
return 2 * (2 * w - 10) * 2
for lr in [0.01, 0.1, 0.3]:
w = 0.0
trail = []
for step in range(1, 21):
w = w - lr * grad(w) # the whole algorithm is this line
if step in (1, 2, 5, 10, 20):
trail.append(f"{step}:{w:.2f}")
print(f"lr={lr:<4} w after steps {' '.join(trail)} final loss {loss(w):.4f}")
# A bumpy loss with two valleys: where you start decides where you end.
def bumpy(w):
return w**4 - 3 * w**2 + w
def bumpy_grad(w):
return 4 * w**3 - 6 * w + 1
for start in [2.0, -2.0]:
w = start
for _ in range(200):
w -= 0.01 * bumpy_grad(w)
print(f"start {start:+.1f} -> w {w:+.3f}, loss {bumpy(w):+.3f}")package main
import (
"fmt"
"strings"
)
// Gradient descent on loss(w) = (w*2 - 10)^2, the one-weight model from the last lesson.
func loss(w float64) float64 { e := 2*w - 10; return e * e }
func grad(w float64) float64 { return 2 * (2*w - 10) * 2 }
func bumpy(w float64) float64 { return w*w*w*w - 3*w*w + w }
func bumpyGrad(w float64) float64 { return 4*w*w*w - 6*w + 1 }
func main() {
for _, lr := range []float64{0.01, 0.1, 0.3} {
w := 0.0
var trail []string
for step := 1; step <= 20; step++ {
w = w - lr*grad(w) // the whole algorithm is this line
switch step {
case 1, 2, 5, 10, 20:
trail = append(trail, fmt.Sprintf("%d:%.2f", step, w))
}
}
fmt.Printf("lr=%-4v w after steps %s final loss %.4f\n", lr, strings.Join(trail, " "), loss(w))
}
// A bumpy loss with two valleys: where you start decides where you end.
for _, start := range []float64{2, -2} {
w := start
for i := 0; i < 200; i++ {
w -= 0.01 * bumpyGrad(w)
}
fmt.Printf("start %+.1f -> w %+.3f, loss %+.3f\n", start, w, bumpy(w))
}
}Output:
lr=0.01 w after steps 1:0.40 2:0.77 5:1.70 10:2.83 20:4.06 final loss 3.5605
lr=0.1 w after steps 1:4.00 2:4.80 5:5.00 10:5.00 20:5.00 final loss 0.0000
lr=0.3 w after steps 1:12.00 2:-4.80 5:31.89 10:-139.63 20:-4178.41 final loss 70003769.6591
start +2.0 -> w +1.131, loss -1.070
start -2.0 -> w -1.301, loss -3.514
কী দেখলাম:
- lr = 0.01 হামাগুড়ি দিচ্ছে। 20 step পরেও w মাত্র 4.06, loss এখনো 3.56।
- lr = 0.1 এক step এ w = 4.00, step 5 এ 5.00। Loss 0।
- lr = 0.3 লাফ দিয়ে 12, তারপর −4.8, তারপর 31.89, আর step 20 এ loss সাত কোটি। একই model, একই data, একই code: বদলেছে শুধু step এর size।
- উঁচুনিচু loss এ +2 থেকে শুরু করলে থামে w = 1.131 এ (loss −1.07), আর −2 থেকে শুরু করলে w = −1.301 এ (loss −3.51)। দুইটাই থেমেছে যেখানে ঢাল শূন্য, কিন্তু গভীর উপত্যকা পেয়েছে শুধু একটা।
Production এ যা মাথায় রাখবে
- সবার আগে learning rate tune করো। Training উল্টাপাল্টা করলে আর কিছু বদলানোর আগে 3 গুণ আর 10 গুণ ছোট বড় করে দেখো। বেশিরভাগ framework একটা schedule ও ব্যবহার করে: শুরুতে অল্প সময় warm-up, তারপর ধীরে ধীরে rate কমানো।
- ভালো optimiser নাও। সাধারণ gradient descent হলো ভিত্তি। Momentum আর Adam (Part 3) আগের gradient গুলো মনে রাখে, তাই সমতল জায়গা গড়িয়ে পার হয়ে যায়, আর যেসব weight এর আলাদা আলাদা step size লাগে সেগুলোও সামলায়। Transformer এর default হলো Adam।
- Loss curve চোখে রাখো। প্রতিটা step এ loss log করো। যে curve নেমে আবার ওঠে, একটা nan, বা যে curve নড়েই না, সেগুলো যেকোনো একটা সংখ্যার চেয়ে বেশি কথা বলে।
- প্রতি step এ পুরো data র gradient লাগে। সব data দিয়ে হিসাব করা অনেক ধীর, তাই আসল training এ ছোট ছোট random batch নেওয়া হয় (mini-batch SGD)। এতে একটু কাজের noise ও আসে, যেটা খারাপ জায়গা থেকে বের হতে সাহায্য করে।
- nan থেকে বাঁচো। একটা overflow সব weight নষ্ট করে দেয়। Gradient কে একটা সর্বোচ্চ size এ clip করো, আর loss nan বা infinite হলে run নিজে থেকে থামাও, যাতে আজেবাজে জিনিসে GPU র ঘণ্টা নষ্ট না হয়।
এক কথায়
Training মানে loss এর পাহাড় বেয়ে নিচে নামা: w = w − learning_rate × gradient, বারবার। সব ঠিক করে learning rate: বেশি ছোট হলে ধীর, বেশি বড় হলে ফাটে, আর কোথা থেকে শুরু করছো সেটা ঠিক করে কোন উপত্যকায় গিয়ে থামবে।
নিজে করে দেখো
Example টা learning rate 0.2 আর 0.24 দিয়ে চালাও। প্রতিটায় loss কি 0 তে যায়, এদিক ওদিক লাফায়, নাকি ফাটে? তারপর বের করো কোন learning rate এর উপরে এই model সবসময় ফাটবে। Hint: এক step এ w = 5 থেকে দূরত্বটা (1 − 8 × lr) দিয়ে গুণ হয়।
Answer
Update টা হলো w − 5 → (1 − 8·lr)(w − 5)। lr = 0.2 তে factor −0.6: প্রতি step এ w নিচ পেরিয়ে ওপাশে যায়, কিন্তু দূরত্ব কমে, তাই এদিক ওদিক করে converge করে। lr = 0.24 তে factor −0.92: এখনো converge করে, কিন্তু ধীরে, দুই পাশে লাফাতে লাফাতে (diagram এর লাল ball টা)। ফাটবে যখন |1 − 8·lr| > 1, মানে lr 0.25 এর বেশি হলে। lr = 0.125 হলো perfect step: factor 0, এক step এই w = 5 এ পৌঁছে যায়।
Station stamp
Chapter শেষ করো
পড়া শেষ হলে Complete চাপো, progress save হবে। XP শুধু Pro তে — Pro থাকলে এই chapter এ +10 XP পেতে।
Pro নিয়ে XP পাও →