Part 02 · Machine Learning
Overfitting and Regularization
Training set মুখস্থ করা মানে শেখা না। Bias-variance trade-off, learning curve পড়া, আর model কে সৎ রাখতে L1, L2 আর early stopping।
⏱ 1-2 ঘণ্টা · Station 13 / 92
জিনিসটা কী, কেন দরকার
দুইজন student গত বছরের প্রশ্ন দিয়ে পরীক্ষার প্রস্তুতি নিচ্ছে। একজন প্রতিটা answer হুবহু মুখস্থ করে। অন্যজন বোঝে প্রতিটা answer কেন ঠিক। গত বছরের প্রশ্নে দুইজনেই 100%। এই বছরের নতুন প্রশ্নে pass করে শুধু দ্বিতীয়জন।
যে model pattern না শিখে training data মুখস্থ করে, সে overfit করছে। Launch এর পরে model fail করার সবচেয়ে common কারণ এটাই, আর model যত বড় হয় তত সহজে হয়, কারণ বড় model এর noise সহ সবকিছু মুখস্থ করার জায়গা থাকে। এই lesson এ দেখবে কীভাবে এটা ধরা যায় (learning curve, train/validation এর ফাঁক), আর কীভাবে লড়াই করা যায়: সহজ model, আরো data, L1/L2 regularisation আর early stopping।
ভেতরে কীভাবে চলে
ভুল হওয়ার দুই রাস্তা।
- High bias (underfitting): pattern এর তুলনায় model বেশি সহজ। ঢেউয়ের মধ্য দিয়ে একটা সোজা লাইন। Training data তেও খারাপ, নতুন data তেও।
- High variance (overfitting): model এত নমনীয় যে noise এর দিকেও বেঁকে যায়। Training data তে দারুণ, নতুন data তে খারাপ।
Model কে বেশি নমনীয় করলে bias কমে আর variance বাড়ে। সবচেয়ে ভালো জায়গাটা মাঝখানে; একেই বলে bias-variance trade-off।
কীভাবে দেখবে। Training data র loss কে এমন একটা validation set এর loss এর সাথে মেলাও যেটায় model কখনো train হয় না:
| train loss | validation loss | রোগ | চেষ্টা করো |
|---|---|---|---|
| বেশি | বেশি | underfitting | বড় model, ভালো feature, আরো train |
| কম | অনেক বেশি | overfitting | আরো data, regularisation, সহজ model, early stopping |
| কম | train এর কাছাকাছি | ঠিকঠাক fit | ship করো, চোখ রাখো |
Learning curve training চলার সাথে (বা data বাড়ার সাথে) দুইটা loss আঁকে। ফাঁক বাড়তে থাকা মানে overfitting।
Regularisation loss এর সাথে বড় weight এর জন্য একটা জরিমানা যোগ করে, কারণ বুনো, overfit model কে প্রতিটা point এর ভেতর দিয়ে বাঁকতে বিশাল weight লাগে:
L2 (ridge / weight decay): loss + λ × Σ w² pulls all weights toward 0 smoothly
L1 (lasso): loss + λ × Σ |w| pushes some weights to exactly 0 (feature selection)
λ (lambda) ঠিক করে জরিমানা কত কড়া। বেশি ছোট হলে কিছুই হয় না, বেশি বড় হলে model আবার চ্যাপ্টা হয়ে underfit করে।
Early stopping। Validation loss দেখতে দেখতে train করো; যেখানে সেটা সবচেয়ে কম ছিল সেখানকার weight রাখো, আর বাড়তে থাকলে থামো। খরচ নেই, আর ধাপে ধাপে train হয় এমন যেকোনো model এ চলে। একই পরিবারে neural network এর প্রিয় হলো dropout (Part 3)।
তোমার model: train loss 0.02, validation loss 0.31। এই সপ্তাহে একটা জিনিস করতে পারবে। কোনটায় সবচেয়ে বেশি কাজ হবে?
ছবিতে দেখো
Code এ মুখস্থ ধরা
একই 10 টা point এ degree 1, 3 আর 9 এর polynomial fit, তারপর degree 9 চারটা L2 শক্তিতে, তারপর validation loss দেখতে দেখতে degree 9 এ সাধারণ gradient descent। শুধু NumPy।
import numpy as np
# 10 training points and 10 validation points from the same curve, y = sin(2πx), plus fixed noise.
NOISE = [0.18, -0.25, 0.10, -0.05, 0.22, -0.30, 0.05, 0.15, -0.20, 0.12,
-0.10, 0.20, -0.15, 0.08, -0.22, 0.25, -0.05, 0.10, -0.18, 0.06]
x_train = np.linspace(0.0, 1.0, 10)
x_val = np.linspace(0.05, 0.95, 10)
y_train = np.sin(2 * np.pi * x_train) + NOISE[:10]
y_val = np.sin(2 * np.pi * x_val) + NOISE[10:]
def features(x, degree):
return np.vstack([x ** p for p in range(degree + 1)]).T # columns 1, x, x², ...
def fit(degree, lam=0.0):
X = features(x_train, degree)
# ridge regression: minimise squared error + lam × (sum of squared weights), solved exactly
penalty = lam * np.eye(degree + 1)
penalty[0, 0] = 0 # don't punish the intercept
return np.linalg.solve(X.T @ X + penalty, X.T @ y_train)
def mse(w, x, y, degree):
return float(np.mean((features(x, degree) @ w - y) ** 2))
print("degree train MSE val MSE biggest |weight|")
for d in (1, 3, 9):
w = fit(d)
print(f"{d:>6} {mse(w, x_train, y_train, d):9.4f} {mse(w, x_val, y_val, d):7.4f} {np.abs(w).max():12.1f}")
print("\ndegree 9 with an L2 penalty")
print("lambda train MSE val MSE biggest |weight|")
for lam in (0.0, 1e-6, 1e-3, 1.0):
w = fit(9, lam)
print(f"{lam:<7g} {mse(w, x_train, y_train, 9):9.4f} {mse(w, x_val, y_val, 9):7.4f} {np.abs(w).max():12.1f}")
# Early stopping: plain gradient descent on degree 9. Train loss keeps falling; watch validation.
X = features(x_train, 9)
w = np.zeros(10)
best = (float("inf"), 0)
print("\nstep train MSE val MSE")
for step in range(1, 3_000_001):
w -= 0.3 * 2 * X.T @ (X @ w - y_train) / len(y_train)
if step in (1_000, 10_000, 100_000, 300_000, 1_000_000, 3_000_000):
v = mse(w, x_val, y_val, 9)
best = min(best, (v, step))
print(f"{step:>9,} {mse(w, x_train, y_train, 9):9.4f} {v:7.4f}")
print(f"stop at step {best[1]:,}: best validation MSE {best[0]:.4f}")
Output:
degree train MSE val MSE biggest |weight|
1 0.2968 0.2317 1.4
3 0.0442 0.0235 30.9
9 0.0000 0.7600 702046.4
degree 9 with an L2 penalty
lambda train MSE val MSE biggest |weight|
0 0.0000 0.7600 702046.4
1e-06 0.0164 0.0357 142.4
0.001 0.0456 0.0319 9.3
1 0.2703 0.2552 0.5
step train MSE val MSE
1,000 0.0926 0.0760
10,000 0.0444 0.0306
100,000 0.0372 0.0228
300,000 0.0363 0.0227
1,000,000 0.0335 0.0228
3,000,000 0.0272 0.0243
stop at step 300,000: best validation MSE 0.0227
কী দেখলাম:
- Degree 1 underfit: train MSE 0.30, validation 0.23, দুইটাই খারাপ।
- Degree 3 ঠিকঠাক: train 0.044, validation 0.024। (এখানে validation train এর চেয়ে কম এসেছে কারণ এই validation point গুলোতে noise কম পড়েছে।)
- Degree 9 মুখস্থ করে: train MSE 0.0000, validation 0.76, degree 3 এর চেয়ে ত্রিশ গুণ খারাপ। সবচেয়ে বড় weight 702,046: প্রতিটা noisy point এর ভেতর দিয়ে curve বাঁকাতে এতটাই লাগে।
- L2 ঠিক করে দেয়। λ = 0.000001 দিলেই সবচেয়ে বড় weight 142 এ নামে আর validation 0.036। λ = 0.001 দেয় 0.032, প্রায় degree 3 এর মতো, অথচ "বেশি নমনীয়" model দিয়েই। λ = 1 বেশি কড়া: weight প্রায় 0, আবার underfitting (0.26)।
- Early stopping: train MSE পুরো সময় কমে (0.093 → 0.027), কিন্তু validation step 300,000 এর কাছে সবচেয়ে কম হয়, 0.0227, তারপর আস্তে আস্তে বাড়ে। ওখানে থামো আর ওই weight রাখো।
Production এ যা মাথায় রাখবে
- বড় model এ overfitting ই স্বাভাবিক। লাখ লাখ weight এর neural network যেকোনো dataset মুখস্থ করতে পারে। Regularisation (weight decay, dropout, data augmentation) আর early stopping প্রতিটা training run এর সাধারণ অংশ, বাড়তি কিছু না।
- চালাক কৌশলের চেয়ে বেশি data ভালো। আরো label দেওয়া example পাওয়া গেলে সেটাই সাধারণত সবচেয়ে নির্ভরযোগ্য সমাধান।
- λ tune করো validation এ, report করো test এ। λ একটা hyperparameter; test এর score দেখে বাছলে test set leak হয় (এই part এর lesson 1)।
- Early stopping এর জন্য checkpoint রাখো। প্রতিটা evaluation এ weight save করো আর validation loss দেখে সেরাটা রাখো। শুধু থামলে হবে না: সেরা checkpoint টা ফিরিয়ে আনো।
- Eval set এও overfit হয়। একটা benchmark এ মাসের পর মাস টুকটাক বদল করলে তোমার system ওই benchmark এই overfit হতে পারে। Evaluation data আসল traffic থেকে নিয়মিত নতুন করো (Part 8)।
এক কথায়
Overfitting মানে noise মুখস্থ করা: training loss কম, validation loss অনেক বেশি। লড়ো আরো data, সহজ model, বড় weight এর উপর L1/L2 জরিমানা, আর validation loss যেখানে সবচেয়ে কম সেখানে early stopping দিয়ে।
নিজে করে দেখো
L2 এর loop এ λ = 1e-4 আর λ = 0.01 যোগ করে আবার চালাও। Validation MSE কোথায় সবচেয়ে কম? তারপর code ছাড়া, উপরের সংখ্যাগুলো দিয়ে learning curve টা এঁকে ফেলো (degree 1 থেকে 9 এর বিপরীতে train আর validation loss)।
Answer
λ = 1e-4 দেয় validation MSE 0.0232 (সবচেয়ে বড় weight 11.7), এখানে চেষ্টা করা মানগুলোর মধ্যে সেরা, 1e-3 এর (0.0319) চেয়ে ভালো; λ = 0.01 এ একটু underfit শুরু হয়ে যায় (0.0723)। সেরা λ সেখানে, যেখানে weight ছোট কিন্তু পিষে ফেলা না। আঁকাটা: training loss degree 1 থেকে 9 পর্যন্ত টানা কমে, degree 9 এ প্রায় 0। Validation loss degree 1 থেকে 3 পর্যন্ত কমে, কয়েক degree কম থাকে, তারপর degree 9 এ লাফিয়ে 0.76 এর দিকে ওঠে। ডান দিকে খুলে যাওয়া ফাঁকটা overfitting; বাম দিকের উঁচু অংশটা underfitting।
Station stamp
Chapter শেষ করো
পড়া শেষ হলে Complete চাপো, progress save হবে। XP শুধু Pro তে — Pro থাকলে এই chapter এ +10 XP পেতে।
Pro নিয়ে XP পাও →