এই পর্বে যা শিখবেন
- Likelihood-এর চোখে cross-entropy, MSE আর L1, আর cross-entropy-র gradient p − লক্ষ্য
- Label smoothing হাতে হিসাব করা, আর calibration-এ তার মাপা প্রভাব
- Class weight আর focal loss: সূত্র, কখন কাজে লাগে, কখন লাগে না
- MSE, L1, Huber আর SmoothL1: outlier-এর সামনে কে কেমন আচরণ করে
- Multi-label BCE, KL divergence আর contrastive loss-এর পরিচয়, reduction ও padding mask, আর task দেখে loss বাছাই
এই কোর্সের পর্ব ১০-এ CrossEntropyLoss-কে logits দিয়েছেন আর দেখেছেন আগে softmax বসালে কী হয়; পর্ব ১১-এ বাংলা রিভিউ padding করে সমান দৈর্ঘ্যের batch বানিয়েছেন। এই পর্বে প্রশ্নটি এক ধাপ ওপরে: কোন loss, আর কেন? Cross-entropy-র তথ্যতত্ত্ব AI-এর ভিত্তি কোর্সের পর্ব ৩৮-এ, আর maximum likelihood মেশিন লার্নিং কোর্সের পর্ব ১৮-এ; এখানে শুধু এক লাইনের মনে করিয়ে দেওয়া, তারপর deep network-এর অনুশীলন। PyTorch পাতায় চলে না, তাই PyTorch-এর সব আউটপুট ডেস্কটপের সত্যিকারের run থেকে; পাতায় চালানো যায় এমন চারটি ব্লক একই ধারণা NumPy দিয়ে দেখায় (প্রথমবার প্যাকেজ নামতে কয়েক সেকেন্ড লাগে)।
১ · Loss আসলে কী মাপে — likelihood-এর চোখে
আবহাওয়া অফিস রোজ বলে “কাল বৃষ্টির সম্ভাবনা ৭০%”. মাস শেষে তাদের কীভাবে নম্বর দেবেন? যেদিন বৃষ্টি হলো, সেদিন তারা বৃষ্টিকে কত সম্ভাবনা দিয়েছিল, তার log নিয়ে যোগ করুন। “৯৯% রোদ” বলে বৃষ্টি হলে জরিমানা বিশাল, “৬০% রোদ” বলে বৃষ্টি হলে জরিমানা মাঝারি। এই হিসাবের খাতাই cross-entropy. আর loss বাছা মানে ঠিক করা, কোন ভুলের জরিমানা কতটা কড়া হবে।
Model x দেখে লক্ষ্যের একটি probability বণ্টন দেয়, আর আমরা চাই দেখা label-গুলোর likelihood সবচেয়ে বেশি হোক। গুণফলের log নিয়ে ঋণাত্মক করলে যোগফল আসে, যাকে কমানো সহজ: negative log-likelihood (NLL). কোন বণ্টন ধরছেন, তার ওপর loss-এর চেহারা নির্ভর করে:
| লক্ষ্যের ধরন আর অনুমান | NLL থেকে যে loss আসে | PyTorch |
|---|---|---|
| K শ্রেণির একটি (categorical), p = softmax(z) | −ln py, অর্থাৎ cross-entropy | nn.CrossEntropyLoss |
| প্রতিটি ট্যাগ আলাদা হ্যাঁ/না (Bernoulli) | binary cross-entropy | nn.BCEWithLogitsLoss |
| সংখ্যা, Gaussian noise, স্থির σ | (y − ŷ)²/(2σ²) + ধ্রুবক, অর্থাৎ MSE | nn.MSELoss |
| সংখ্যা, Laplace noise (মোটা লেজ) | |y − ŷ|/b + ধ্রুবক, অর্থাৎ L1 | nn.L1Loss |
Cross-entropy-র দুটি ব্যবহারিক কথা এই কোর্সে আগেই এসেছে, এখানে শুধু মনে করিয়ে দিই। এক, loss নেয় logits, আর ভেতরে log-sum-exp কৌশলে log-softmax করে, যাতে বড় logit-এ overflow না হয় (পর্ব ০৩, পর্ব ১০)। দুই, logits z-এর সাপেক্ষে gradient খুব সরল: ∂L/∂z = p − y, যেখানে y হলো one-hot লক্ষ্য (পর্ব ০৪-এর P − Y).
এই সরল gradient-এর একটি লুকানো পরিণতি আছে। সঠিক শ্রেণির জন্য gradient py − ১, যা কখনো শূন্য হয় না, শুধু শূন্যের দিকে যায়। ফলে training ডেটায় সব ঠিক হয়ে গেলেও loss সঠিক logit-কে আরও ওপরে ঠেলতে থাকে, আর model ক্রমে ০.৯৯৯-এর মতো চরম probability দিতে শেখে। Train set-এ এতে ক্ষতি নেই, কিন্তু নতুন ডেটায় ভুল উত্তরেও model অতি-আত্মবিশ্বাসী থাকে: একে বলে overconfidence. পরের দুই অংশ এই সমস্যার একটি সহজ ওষুধ নিয়ে।
২ · Label smoothing — লক্ষ্যকে একটু নরম করা
Label smoothing-এ one-hot লক্ষ্যের বদলে একটি নরম লক্ষ্য দেওয়া হয়। K শ্রেণি আর একটি ছোট সংখ্যা ε (প্রায়ই ০.১) নিয়ে:
q = (1 − ε)·y + ε/K · L = −Σk qk ln pk · ∂L/∂z = p − q
এখানে y one-hot লক্ষ্য, p = softmax(z) model-এর probability, আর q নরম লক্ষ্য। সঠিক শ্রেণি পায় ১ − ε + ε/K, বাকি প্রতিটি ε/K. Gradient-এর রূপ একই থাকে, শুধু লক্ষ্য বদলায়; তাই এখন p = q হলে gradient শূন্য, অর্থাৎ model-এর আর চরম probability দেওয়ার তাগিদ নেই। নিচের stepper-এ একটি উদাহরণ হাতে হিসাব করুন।
| ধাপ | |
| হিসাব |
- Logits. তিন শ্রেণির কাঁচা স্কোর ২.০, ০.৫ আর −১.০; সঠিক শ্রেণি ০.
- Softmax. প্রতিটির ez নিয়ে যোগফল ৯.৪০৫৭ দিয়ে ভাগ: p = [০.৭৮৫৬, ০.১৭৫৩, ০.০৩৯১].
- সাধারণ cross-entropy. শুধু সঠিক শ্রেণির −ln p0 = ০.২৪১৩. বাকি দুই শ্রেণির probability loss-এ সরাসরি আসে না।
- নরম লক্ষ্য. ε = ০.১-কে তিন ভাগ করে সবাইকে ০.০৩৩৩, আর সঠিক শ্রেণি পায় ০.৯ + ০.০৩৩৩ = ০.৯৩৩৩.
- Smoothed loss. তিনটি পদের যোগ ০.৩৯১৩. ভুল শ্রেণির log probability-ও এখন জরিমানা পায়। PyTorch-এর
F.cross_entropy(z, y, label_smoothing=0.1)সত্যিকারের run-এ ঠিক ০.৩৯১৩ দিল (অংশ ৮). - Gradient. সঠিক logit-কে ওপরে ঠেলার জোর −০.২১৪৪ থেকে কমে −০.১৪৭৭, আর তৃতীয় শ্রেণিকে নিচে ঠেলার জোর ০.০৩৯১ থেকে ০.০০৫৮. Model ইতিমধ্যে যথেষ্ট নিশ্চিত, তাই ধাক্কা নরম।
এবার কয়েকটি logit vector-এ দুই loss আর সঠিক logit-এর gradient পাশাপাশি দেখুন। নজর রাখুন শেষ দুই সারির চিহ্নের দিকে।
import numpy as np
def log_softmax(z):
z = z - z.max() # stable: সবচেয়ে বড় logit বাদ
return z - np.log(np.exp(z).sum())
def ce(z, y, eps=0.0):
K = len(z)
q = np.full(K, eps / K); q[y] += 1 - eps # smoothed target (1−ε)y + ε/K
lp = log_softmax(z)
return -(q * lp).sum(), np.exp(lp) - q # loss আর ∂L/∂z = p − q
y = 0 # সঠিক শ্রেণি 0, K = 3
for z in ([2.0, 0.5, -1.0], [0.0, 3.0, 0.0], [5.0, 0.0, 0.0], [10.0, 0.0, 0.0]):
z = np.array(z)
l0, g0 = ce(z, y); l1, g1 = ce(z, y, 0.1)
print(f"z={str(z):15s} CE {l0:.4f} | LS {l1:.4f} || ∂/∂z0: CE {g0[0]:+.4f} | LS {g1[0]:+.4f}")
K, eps = 3, 0.1
q = np.full(K, eps / K); q[0] += 1 - eps
print("smoothed target:", q.round(4), "| LS-এর সর্বনিম্ন loss = H(q) =", round(-(q * np.log(q)).sum(), 4))
print("সেরা logit ব্যবধান z0 − z1 = ln(q0/q1) =", round(np.log(q[0] / q[1]), 4))আউটপুট (পাতার Python-এ চালানো):
z=[ 2. 0.5 -1. ] CE 0.2413 | LS 0.3913 || ∂/∂z0: CE -0.2144 | LS -0.1477
z=[0. 3. 0.] CE 3.0949 | LS 2.9949 || ∂/∂z0: CE -0.9547 | LS -0.8881
z=[5. 0. 0.] CE 0.0134 | LS 0.3467 || ∂/∂z0: CE -0.0133 | LS +0.0534
z=[10. 0. 0.] CE 0.0001 | LS 0.6668 || ∂/∂z0: CE -0.0001 | LS +0.0666
smoothed target: [0.9333 0.0333 0.0333] | LS-এর সর্বনিম্ন loss = H(q) = 0.2911
সেরা logit ব্যবধান z0 − z1 = ln(q0/q1) = 3.3322
দ্বিতীয় সারিতে model দৃঢ়ভাবে ভুল; দুই loss-ই জোরালো সংশোধন চায় (−০.৯৫ আর −০.৮৯)। আসল পার্থক্য শেষ দুই সারিতে। সাধারণ CE-তে gradient ঋণাত্মক থাকে (−০.০১৩৩, −০.০০০১): logit ১০ হলেও loss বলে “আরও বাড়াও”, শুধু আস্তে। Label smoothing-এ চিহ্ন উল্টে ধনাত্মক: logit-এর ব্যবধান ৩.৩৩২২ পেরোলেই loss তাকে পেছনে টানে। তাই smoothed loss কখনো শূন্যে নামে না; তার সর্বনিম্ন মান নরম লক্ষ্যের entropy, ০.২৯১১. Training log-এ এই মানের কাছে loss থেমে থাকলে ঘাবড়াবেন না।
৩ · Label smoothing সত্যিকারের training-এ — accuracy, confidence আর ECE
Probability কতটা বিশ্বাসযোগ্য, তা মাপে calibration: model যেসব অনুমানে ০.৮ বলে, তার প্রায় ৮০% ঠিক হলে model calibrated. একটি সংখ্যায় প্রকাশ করে expected calibration error (ECE): অনুমানগুলোকে confidence অনুযায়ী ঝুড়িতে ভাগ করে, প্রতিটি ঝুড়িতে গড় confidence আর আসল accuracy-র পার্থক্য, ঝুড়ির আকার দিয়ে ওজন করে যোগ। এর পুরো ব্যাখ্যা, reliability diagram আর temperature scaling মেশিন লার্নিং কোর্সের পর্ব ২৬-এ।
পরীক্ষা: Fashion-MNIST (Zalando Research-এর পোশাকের ২৮ × ২৮ ছবি, ১০টি শ্রেণি, MIT লাইসেন্স) থেকে ১২,০০০ train ছবি আর পুরো ১০,০০০ test ছবি। Model 784 → 512 → 256 → 10-এর MLP, AdamW, ৩০ epoch, কোনো regularization ছাড়া, যাতে ইচ্ছে করে overfit করে। একবার সাধারণ CE, একবার label_smoothing=0.1; প্রতিটি তিনটি seed-এ। ECE ১৫টি ঝুড়িতে। ডেটা torchvision-এর datasets.FashionMNIST দিয়ে পড়া।
সত্যিকারের run (ডেস্কটপ, CPU; uv project আগের পর্বগুলোর মতো, torch 2.15.0-এর CPU wheel):
~/bazarghar-dl$ uv run python ls_calib.py
torch 2.15.0+cpu | torchvision 0.29.2+cpu | python 3.14.4
train (12000, 784) | test (10000, 784)
label_smoothing=0.0: acc 0.8605 | mean conf 0.9319 | ECE 0.0715 | test NLL 0.5337 | conf on wrong 0.776 | conf>0.99 64.0%
per seed ECE: 0.0694 0.0726 0.0726 | acc: 0.8641 0.8519 0.8656
label_smoothing=0.1: acc 0.8671 | mean conf 0.8400 | ECE 0.0336 | test NLL 0.4675 | conf on wrong 0.660 | conf>0.99 0.2%
per seed ECE: 0.0362 0.0308 0.0336 | acc: 0.8733 0.8562 0.8717
time 47 s (CPU)
পড়ে দেখুন। সাধারণ CE-তে accuracy ০.৮৬, কিন্তু গড় confidence ০.৯৩: model যতটা ঠিক, তার চেয়ে বেশি নিশ্চিত। ৬৪% ছবিতে সে ০.৯৯-এর বেশি probability দিয়েছে, আর ভুল উত্তরেও গড় confidence ০.৭৮. Label smoothing-এ গড় confidence ০.৮৪, accuracy-র (০.৮৭) কাছাকাছি; ECE গড়ে অর্ধেকের কম (০.০৭১৫ থেকে ০.০৩৩৬), আর প্রতিটি seed-এ প্রায় অর্ধেক বা তার কম; test NLL-ও কমেছে। Accuracy-র পার্থক্য (০.৮৬০৫ বনাম ০.৮৬৭১) seed-এর ওঠানামার (০.৮৫২ থেকে ০.৮৬৬) মধ্যে, তাই এখানে “accuracy বেড়েছে” বলা যায় না। এটি একটি ছোট model আর ডেটায় একটি স্থানীয় পরীক্ষা, সাধারণ নিয়ম নয়।
Label smoothing সবসময় calibration দেয় না। লক্ষ্যই যেহেতু সর্বোচ্চ ০.৯৩৩, model সহজ উদাহরণেও কম নিশ্চিত হতে শেখে; কম overfit করা model-এ এতে underconfidence আসতে পারে। Label smoothing ভুল শ্রেণিগুলোকে সমান ঠেলে বলে শ্রেণিগুলোর মধ্যে মিলের তথ্য (শার্ট আর টি-শার্ট কাছাকাছি) কিছুটা মুছে যায়, যা পরে distillation-এ ক্ষতি করতে পারে (ভাবনার প্রশ্ন ১)। আর এটি একটি regularizer, তাই তার অন্য regularizer-এর সঙ্গে তুলনা পর্ব ১৬ (Deep learning-এ regularization)-এর বিষয়। Calibration-ই লক্ষ্য হলে training-এর পরে আলাদা ডেটায় temperature scaling সাধারণত সস্তা আর নির্ভরযোগ্য পথ।
৪ · Imbalance-এর loss — class weight আর focal loss
বাজারঘরের cash-on-delivery অর্ডারের মধ্যে অল্প কিছু ফেরত আসে: ক্রেতা দরজায় পণ্য নেন না। এমন class imbalance-এ সাধারণ CE-র সমস্যা হলো গড়: ৯৭টি সাধারণ অর্ডারের ছোট ছোট loss মিলে ৩টি বিরল অর্ডারের loss-কে ছাপিয়ে যায়। Resampling, SMOTE আর threshold-এর আলোচনা মেশিন লার্নিং কোর্সের পর্ব ৫০-এ, আর WeightedRandomSampler পর্ব ১১-এ। Loss-এর দিক থেকে দুটি প্রচলিত উপায়:
Class weight
প্রতিটি শ্রেণির loss-কে একটি ওজন wc দিয়ে গুণ: L = −wy ln py. “Balanced” ওজন wc = N / (K · nc). PyTorch-এ nn.CrossEntropyLoss(weight=w); দুই শ্রেণির একটি logit হলে BCEWithLogitsLoss(pos_weight=...). সব বিরল উদাহরণের ওপর সমান জোর, সহজ হোক বা কঠিন।
Focal loss
FL = −αt (1 − pt)γ ln pt, যেখানে pt সঠিক শ্রেণির probability, γ ≥ ০ “মনোযোগের” মাত্রা, αt ঐচ্ছিক শ্রেণি-ওজন। γ = ০ হলে সাধারণ CE. Model যে উদাহরণ ইতিমধ্যে ভালো পারে (pt বড়), তার loss প্রায় শূন্যে নামে; জোর যায় কঠিনগুলোতে, যে শ্রেণিরই হোক।
Focal loss এসেছে Lin, Goyal, Girshick, He আর Dollár-এর ২০১৭ সালের প্রবন্ধ “Focal Loss for Dense Object Detection” থেকে (RetinaNet). সেখানে সমস্যা ছিল object detection: একটি ছবিতে হাজার হাজার সম্ভাব্য বাক্স, প্রায় সবই সহজ পটভূমি। তাদের পরীক্ষায় γ = ২, α = ০.২৫ ভালো কাজ করেছিল বলে রিপোর্ট করা; অন্য task-এ এই মান নিজে যাচাই করতে হয়। নিচের stepper-এ দেখুন কীভাবে focal loss সহজদের চুপ করায়।
| উদাহরণ | |
| CE | |
| (1 − p_t)² | |
| Focal | |
| কঠিনের ভাগ |
- একটি সহজ উদাহরণ. Model সঠিক শ্রেণিকে ০.৯৫ দিয়েছে; CE ছোট, ০.০৫১৩, কিন্তু শূন্য নয়।
- Focal-এর গুণক. (১ − ০.৯৫)² = ০.০০২৫; loss ৪০০ গুণ ছোট হয়ে ০.০০০১২৮.
- একটি কঠিন উদাহরণ. pt = ০.২; CE ১.৬০৯৪, গুণক ০.৬৪, focal ১.০৩০০. কঠিন উদাহরণ প্রায় পুরো loss রেখে দেয়।
- পুরো batch, সাধারণ CE. ১০০০টি সহজ মিলে ৫১.২৯৩, ১০টি কঠিন মিলে ১৬.০৯৪. একা একা ছোট হলেও সংখ্যায় বেশি বলে সহজরাই loss-এর ৭৬% নিয়ে নেয়।
- পুরো batch, focal. সহজদের মোট মাত্র ০.১২৮, কঠিনদের ১০.৩০০; কঠিনের ভাগ ২৩.৯% থেকে ৯৮.৮%. Gradient-ও এখন প্রায় পুরোটাই কঠিন উদাহরণ থেকে আসে।
import numpy as np, matplotlib.pyplot as plt
def focal(pt, gamma): # FL = −(1 − p_t)^γ · ln p_t
return -(1 - pt) ** gamma * np.log(pt)
print("p_t CE(γ=0) γ=0.5 γ=1 γ=2 γ=5")
for pt in (0.1, 0.5, 0.9, 0.99):
print(f"{pt:<6}", " ".join(f"{focal(pt, g):8.5f}" for g in (0, 0.5, 1, 2, 5)))
# ১০০০টি সহজ negative (p_t = 0.95) বনাম ১০টি কঠিন positive (p_t = 0.2)
for g in (0, 2):
easy, hard = 1000 * focal(0.95, g), 10 * focal(0.2, g)
print(f"γ={g}: সহজদের মোট {easy:.3f}, কঠিনদের মোট {hard:.3f}, কঠিনের ভাগ {hard / (easy + hard):.1%}")
pt = np.linspace(0.01, 1, 300)
for g in (0, 0.5, 1, 2, 5):
plt.plot(pt, focal(pt, g), label=f"gamma = {g}" + (" (CE)" if g == 0 else ""))
plt.axvspan(0.6, 1, color="gray", alpha=0.1)
plt.text(0.62, 3.6, "well-classified")
plt.ylim(0, 4.5); plt.xlabel("p_t (probability of the true class)"); plt.ylabel("loss")
plt.title("Focal loss down-weights easy examples"); plt.legend(); plt.show()আউটপুট (পাতার Python-এ চালানো; নিচে একটি চিত্রও আঁকা হয়):
p_t CE(γ=0) γ=0.5 γ=1 γ=2 γ=5
0.1 2.30259 2.18442 2.07233 1.86509 1.35965
0.5 0.69315 0.49013 0.34657 0.17329 0.02166
0.9 0.10536 0.03332 0.01054 0.00105 0.00000
0.99 0.01005 0.00101 0.00010 0.00000 0.00000
γ=0: সহজদের মোট 51.293, কঠিনদের মোট 16.094, কঠিনের ভাগ 23.9%
γ=2: সহজদের মোট 0.128, কঠিনদের মোট 10.300, কঠিনের ভাগ 98.8%
pt = ০.১ (খুব ভুল) হলে γ বাড়ালেও loss খুব একটা কমে না (২.৩০ থেকে ১.৮৭, γ = ২-এ)। কিন্তু pt = ০.৯-এ γ = ২ loss-কে ১০০ গুণ ছোট করে (০.১০৫৩৬ থেকে ০.০০১০৫), কারণ (১ − ০.৯)² = ০.০১. চিত্রে ধূসর অংশে সব রেখা প্রায় শূন্যে মিশে যায়: “ভালোভাবে শ্রেণিভুক্ত” উদাহরণ শেখায় আর প্রায় কিছুই যোগ করে না। γ = ৫-এ pt = ০.৫-এর loss-ও প্রায় শূন্য, অর্থাৎ বেশি γ মাঝারি উদাহরণকেও উপেক্ষা করে।
৫ · বাজারঘরের ফেরত-অর্ডার — চার রকম loss-এর সত্যিকারের তুলনা
তত্ত্ব শুনতে ভালো; এবার মেপে দেখি। বাজারঘরের seeded কৃত্রিম ডেটা: প্রতিটি অর্ডারের ৮টি কৃত্রিম সংখ্যাগত feature (standardized), আর একটি অ-রৈখিক নিয়মে ফেরত আসার সম্ভাবনা; ২০,০০০ train আর ২০,০০০ test অর্ডার, ফেরত মাত্র ৩.২%. Model 8 → 64 → 64 → 2-এর MLP, AdamW, ১৫ epoch. চারটি loss, প্রতিটি তিনটি seed-এ। মাপা হলো ০.৫ threshold-এ recall আর precision, threshold-নিরপেক্ষ PR AUC (average precision), আর recall অন্তত ০.৮ রাখলে সর্বোচ্চ precision. এই মাপগুলো AI-এর ভিত্তি কোর্সের পর্ব ৬০-এ।
~/bazarghar-dl$ uv run python imbalance.py
torch 2.15.0+cpu | scikit-learn 1.9.1 | python 3.14.4
train 20000, rare class 3.20% | test rare 3.38%
class weights (balanced): [0.52, 15.6]
loss recall@0.5 precision@0.5 PR-AUC precision@recall0.8
plain CE 0.215±0.024 0.671±0.030 0.415±0.005 0.174±0.008
weighted CE 0.831±0.021 0.155±0.010 0.408±0.004 0.172±0.003
focal g=2 0.223±0.021 0.643±0.046 0.410±0.003 0.181±0.004
focal g=2 + weight 0.824±0.028 0.153±0.015 0.399±0.005 0.169±0.001
3 seeds each, time 19 s (CPU)
এই টেবিলটি এই পর্বের সবচেয়ে জরুরি শিক্ষা। ০.৫ threshold দেখলে মনে হয় class weight যাদু করেছে: recall ০.২১৫ থেকে ০.৮৩১. কিন্তু precision ০.৬৭১ থেকে ০.১৫৫-এ পড়েছে। Threshold-নিরপেক্ষ PR AUC চারটিতেই প্রায় এক (০.৩৯৯ থেকে ০.৪১৫), আর recall ০.৮ রাখলে সবার precision ০.১৭-০.১৮. অর্থাৎ model-গুলো অর্ডারগুলোকে প্রায় একই ক্রমে সাজায়; class weight মূলত probability-কে ওপরে ঠেলে ০.৫ threshold-কে সরিয়ে দিয়েছে। সাধারণ CE-র model-এ threshold নামিয়েও প্রায় একই জায়গায় পৌঁছানো যেত। Focal loss (γ = ২) এখানে PR AUC বাড়ায়নি।
Imbalance-এ loss বদলানোর আগে threshold-নিরপেক্ষ metric (PR AUC) আর validation-এ বাছা threshold দেখুন। Class weight বা focal loss তখনই রাখুন যখন সেগুলো ক্রম-মান (ranking) বা আপনার আসল লক্ষ্য-metric সত্যিই বাড়ায়, কয়েকটি seed-এ। আর মনে রাখুন, class weight দেওয়া model-এর probability আর বাস্তব হার নয়: ০.৭৫ বলা অর্ডারের ৭৫% ফেরত আসবে না। ঘনঘন ছোট ছোট সহজ উদাহরণে ভরা task-এ (detection-এর মতো) focal loss-এর লাভ বেশি দেখা গেছে; একটি ছোট tabular task-এ না-ও দেখা যেতে পারে, যেমন এখানে।
৬ · Regression-এর loss — MSE, L1, Huber আর outlier
বাজারঘর ঢাকার ভেতরে ডেলিভারির দিন অনুমান করতে চায়। বেশিরভাগ অর্ডার ২-৩ দিনে পৌঁছায়, কিন্তু বন্যা বা হরতালে কয়েকটি ২০ দিন আটকে থাকে। এমন outlier-এর সামনে তিনটি loss তিনভাবে আচরণ করে। ভুল r = y − ŷ ধরে:
- MSE: r². ভুল দ্বিগুণ হলে জরিমানা চারগুণ; gradient 2r, তাই বড় ভুল বড় টান দেয়।
- L1 (MAE): |r|. Gradient সবসময় ±১, ভুল যত বড়ই হোক; শূন্যের কাছে gradient লাফ দেয়, তাই শেষ দিকে শেখা একটু অস্থির হতে পারে।
- Huber (সীমা δ): |r| ≤ δ হলে ½r², নইলে δ(|r| − ½δ). ছোট ভুলে MSE-র মতো মসৃণ, বড় ভুলে L1-এর মতো স্থির ঢাল δ. PyTorch-এ
nn.HuberLoss(delta=δ), আর তার আত্মীয় SmoothL1,nn.SmoothL1Loss(beta=β), যা Huber-কে β দিয়ে ভাগ করা রূপ।
তিনটি regression loss — ভুলের আকারের সঙ্গে জরিমানা
½r² (MSE), |r| (L1), Huber with δ = 1
সবচেয়ে সরল “model” হলো একটি constant c, যা সব অর্ডারে একই দিন বলে। কোন c কোন loss-কে সবচেয়ে কম করে? নিচের ব্লকে ৪০টি অর্ডার, যার ৩টি বন্যা-হরতালে আটকে থাকা।
import numpy as np
rng = np.random.default_rng(42) # বাজারঘর: ঢাকার ভেতরে ডেলিভারির দিন
days = np.round(rng.gamma(6, 0.4, 40), 1) # সাধারণ অর্ডার, গড় প্রায় ২.৪ দিন
days[:3] = [14.0, 18.0, 21.0] # বন্যা আর হরতালে আটকে থাকা ৩টি অর্ডার
def huber(r, d=1.0):
a = np.abs(r)
return np.where(a <= d, 0.5 * r**2, d * (a - 0.5 * d))
losses = {"MSE": lambda r: r**2, "L1": np.abs, "Huber δ=1": huber}
grid = np.linspace(0, 10, 10001) # সব constant c পরীক্ষা: অনুমান = c
for name, f in losses.items():
c = grid[np.argmin([f(days - g).mean() for g in grid])]
print(f"{name:9s}: সেরা constant c = {c:.3f}")
print(f"তুলনা: mean {days.mean():.3f} | median {np.median(days):.3f}")
c = 2.5 # c = 2.5-এ প্রতিটি অর্ডারের টান (−∂loss/∂c)
pull = {"MSE": 2 * (days - c), "L1": np.sign(days - c),
"Huber δ=1": np.clip(days - c, -1, 1)}
for name, g in pull.items():
print(f"{name:9s}: ৩টি outlier-এর মোট টান {g[:3].sum():6.2f} | বাকি ৩৭টির {g[3:].sum():6.2f}")আউটপুট (পাতার Python-এ চালানো):
MSE : সেরা constant c = 3.530
L1 : সেরা constant c = 2.400
Huber δ=1: সেরা constant c = 2.448
তুলনা: mean 3.530 | median 2.400
MSE : ৩টি outlier-এর মোট টান 91.00 | বাকি ৩৭টির -8.60
L1 : ৩টি outlier-এর মোট টান 3.00 | বাকি ৩৭টির -5.00
Huber δ=1: ৩টি outlier-এর মোট টান 3.00 | বাকি ৩৭টির -4.60
MSE-র সেরা constant ঠিক mean (৩.৫৩ দিন), L1-এর ঠিক median (২.৪০), আর Huber দুইয়ের মাঝে, median-এর কাছে (২.৪৫)। কারণ টানের হিসাবে: c = ২.৫-এ MSE-তে মাত্র ৩টি outlier ৯১ একক টানে, বাকি ৩৭টি অর্ডার মিলে মাত্র ৮.৬; outlier-ই সিদ্ধান্ত নেয়। L1 আর Huber-এ প্রতিটি অর্ডারের টান সর্বোচ্চ ১, তাই ৩টি outlier মিলে মাত্র ৩. কোনটি “ঠিক”, তা ব্যবসার প্রশ্ন: ক্রেতাকে সাধারণ প্রতিশ্রুতি দিতে median কাজের, আর মোট গাড়ি-ঘণ্টা পরিকল্পনায় mean. Robust regression আর quantile loss মেশিন লার্নিং কোর্সের পর্ব ২৪-এ।
Deep network-এ আরেকটি কারণে Huber জনপ্রিয়: বড় ভুলে MSE-র gradient বিশাল হয়ে training অস্থির করতে পারে, আর Huber তা সীমিত রাখে। Fast R-CNN (Girshick, ২০১৫) bounding box regression-এ SmoothL1 ব্যবহার করেছিল; reinforcement learning-এর DQN-ধারার কাজেও Huber-ধরনের loss দেখা যায়। δ-এর একক লক্ষ্যের এককের সমান (এখানে দিন), তাই লক্ষ্য scale করলে δ-ও বদলাতে হয়।
৭ · Multi-label, KL divergence আর contrastive loss — এক নজরে
Multi-label. একটি পণ্য একসঙ্গে “দেশি”, “অর্গানিক” আর “ছাড়” হতে পারে: এটি multi-label classification. এখানে softmax চলে না, কারণ softmax শ্রেণিগুলোকে প্রতিযোগী করে। প্রতিটি ট্যাগ একটি আলাদা হ্যাঁ/না: C টি logit, (N, C) আকারের float ০/১ লক্ষ্য, আর BCEWithLogitsLoss. বিরল ট্যাগের জন্য pos_weight প্রতিটি ট্যাগের positive-এর loss বাড়ায়। Threshold প্রতিটি ট্যাগে আলাদা বাছা যায় (মেশিন লার্নিং কোর্সের পর্ব ২৫)।
KL divergence. লক্ষ্য যখন one-hot নয়, একটি পুরো বণ্টন, তখন KL divergence KL(p ‖ q) = Σ p ln(p/q) দিয়ে দুটি বণ্টনের দূরত্ব মাপা হয়। সবচেয়ে পরিচিত ব্যবহার knowledge distillation: বড় teacher model-এর logits-কে temperature T দিয়ে ভাগ করে softmax নিলে একটি নরম বণ্টন আসে, যাতে “শার্ট টি-শার্টের কাছাকাছি” ধরনের তথ্য থাকে; ছোট student সেটি নকল করতে শেখে। পুরো পদ্ধতি পর্ব ৫৯ (quantization, distillation আর pruning)-এ। PyTorch-এর nn.KLDivLoss-এর একটি ফাঁদ: input হতে হবে log-probability, target সাধারণ probability, আর গণিতের KL পেতে reduction="batchmean".
Ranking আর contrastive. কখনো শ্রেণি নয়, দূরত্বই লক্ষ্য: “এই দুটি রিভিউ একই পণ্যের কথা বলছে”। Triplet loss max(০, d(a, p) − d(a, n) + margin) একটি anchor-কে তার positive-এর কাছে আর negative থেকে অন্তত margin দূরে চায়। InfoNCE আরও সরল: একটি batch-এর সব জোড়ার similarity-কে temperature দিয়ে ভাগ করে cross-entropy, যেখানে সঠিক জোড়া হলো “সঠিক শ্রেণি”, আর batch-এর বাকিরা negative. এটাই contrastive learning-এর মূল loss. বিস্তারিত পর্ব ৬৭ (Sentence embedding আর semantic search) আর পর্ব ৮২ (CLIP-সহ multimodal model)-এ।
চারটি loss-এর ছোট সত্যিকারের run:
~/bazarghar-dl$ uv run python previews.py
torch 2.15.0+cpu | python 3.14.4
multi-label BCE: 0.2407 | pos_weight=3: 0.5412
teacher soft target T=2: [0.7361, 0.1643, 0.0996]
KLDivLoss(batchmean): 0.1526 | by hand sum p*log(p/q): 0.1526
KLDivLoss default reduction warning: reduction: 'mean' divides the total loss by both the batch s
TripletMarginLoss(margin=1): 0.5833
InfoNCE (cross_entropy on similarity, diagonal = positive): 0.0017
Teacher-এর logits [৪, ১, ০] T = ২ দিয়ে নরম হয়ে [০.৭৩৬১, ০.১৬৪৩, ০.০৯৯৬]; batchmean-এর KL হাতের হিসাবের সঙ্গে হুবহু ০.১৫২৬. Default reduction="mean" দিলে PyTorch সতর্ক করে যে এটি batch আর শ্রেণি দুটির সংখ্যা দিয়েই ভাগ করে, যা KL-এর সংজ্ঞা নয়। শেষ লাইনে InfoNCE আসলে F.cross_entropy(similarity, torch.arange(N)): contrastive loss-ও শেষে cross-entropy.
৮ · Reduction আর masking — গড়টা আসলে কিসের ওপর
প্রতিটি PyTorch loss প্রথমে প্রতিটি উদাহরণের (বা token-এর) জন্য একটি করে loss বানায়, তারপর reduction দিয়ে একটি সংখ্যায় আনে: 'none' সব আলাদা রাখে, 'sum' যোগ করে, 'mean' (default) গড় করে। Token-ভিত্তিক task-এ (প্রতিটি শব্দের tag, পরের token অনুমান) sequence-গুলো padding দিয়ে সমান করা থাকে (পর্ব ১১)। Padding-এর ঘরে কোনো আসল label নেই, তাই সেগুলো loss থেকে বাদ দিতে হয়। CrossEntropyLoss-এর ignore_index (default −১০০) ঠিক এই কাজ করে: লক্ষ্য −১০০ হলে সেই ঘরের loss শূন্য, আর 'mean' শুধু বাকি ঘরের সংখ্যা দিয়ে ভাগ করে।
নিজে mask দিয়ে করলে নিয়ম একটাই: masked গড় = Σ(loss × mask) / Σ mask. নিচের ব্লকে তিনটি বাংলা রিভিউ (দৈর্ঘ্য ৭, ৩, ২), padding করে সবাই ৭; দুটি প্রচলিত ভুল আর একটি বৈধ বিকল্প।
import numpy as np
rng = np.random.default_rng(42) # ৩টি বাংলা রিভিউ, token-level task, ৪টি tag
lengths = np.array([7, 3, 2]) # আসল দৈর্ঘ্য; padding করে সবাই ৭
B, T, C = 3, 7, 4
logits = rng.normal(0, 1.5, (B, T, C))
target = rng.integers(0, C, (B, T))
mask = np.arange(T)[None, :] < lengths[:, None] # True = আসল token, False = padding
target[~mask] = 0 # padding-এ বসানো ভুয়া label 0
z = logits - logits.max(-1, keepdims=True)
logp = z - np.log(np.exp(z).sum(-1, keepdims=True))
tok_loss = -np.take_along_axis(logp, target[..., None], -1)[..., 0] # (B, T)
print("mask:\n", mask.astype(int))
print("ভুল ১, সব ঘরের গড় (padding-সহ) :", round(tok_loss.mean(), 4))
print("ভুল ২, (loss*mask).mean() :", round((tok_loss * mask).mean(), 4))
right = (tok_loss * mask).sum() / mask.sum()
print("ঠিক, masked token গড় (sum/count) :", round(right, 4), "| আসল token", mask.sum())
per_seq = (tok_loss * mask).sum(1) / lengths
print("অন্য পছন্দ, প্রতি রিভিউর গড়ের গড় :", round(per_seq.mean(), 4), "| প্রতি রিভিউ", per_seq.round(4))আউটপুট (পাতার Python-এ চালানো):
mask:
[[1 1 1 1 1 1 1]
[1 1 1 0 0 0 0]
[1 1 0 0 0 0 0]]
ভুল ১, সব ঘরের গড় (padding-সহ) : 1.3113
ভুল ২, (loss*mask).mean() : 0.6608
ঠিক, masked token গড় (sum/count) : 1.1565 | আসল token 12
অন্য পছন্দ, প্রতি রিভিউর গড়ের গড় : 1.4048 | প্রতি রিভিউ [0.9426 0.7355 2.5364]
২১টি ঘরের মধ্যে আসল token মাত্র ১২টি। ভুল ১ padding-এর ভুয়া label-কেও শেখায়, model তখন “padding-এর পরে tag ০” মুখস্থ করে আর সংখ্যাটিও (১.৩১১৩) অর্থহীন। ভুল ২ আরও চুপচাপ: mask দিয়ে padding শূন্য করেছে, কিন্তু ভাগ করেছে ২১ দিয়ে, ১২ দিয়ে নয়; ফলে loss (০.৬৬০৮) আসলের প্রায় অর্ধেক দেখায়, আর batch-এ padding যত বেশি, loss তত ছোট দেখায়। ঠিক মান ১.১৫৬৫. শেষ লাইন একটি বৈধ বিকল্প, ভুল নয়: প্রতিটি রিভিউকে সমান ওজন দিলে ছোট রিভিউর (২ token, loss ২.৫৪) প্রভাব বাড়ে। কোনটি চান, তা ঠিক করে লিখুন (ভাবনার প্রশ্ন ৫)।
PyTorch-এ একই জিনিসগুলো, সঙ্গে weight-এর একটি সূক্ষ্ম নিয়ম। দুটি বাক্য, প্রতিটিতে ৪টি অবস্থান, ৫টি শ্রেণি, তিনটি padding ঘর (−১০০):
~/bazarghar-dl$ uv run python reduction.py
torch 2.15.0+cpu | python 3.14.4
reduction='none' : tensor([0.4433, 0.6587, 0.4278, 0.0000, 0.5727, 3.1816, 0.0000, 0.0000])
reduction='sum' : tensor(5.2840)
reduction='mean' : tensor(1.0568)
logits (B, C, T) form: 1.0568084716796875
weight + mean : 2.0011656284332275
sum / count : 3.602097749710083 | sum / sum(w): 2.0011653900146484
label_smoothing=0.1: 0.3913113474845886 | by hand: 0.3913113474845886
bad class index: IndexError - Target 7 is out of bounds.
all ignored -> mean: nan
HuberLoss(delta=2): tensor([0.0450, 0.3200, 6.0000]) | 2*SmoothL1(beta=2): tensor([0.0450, 0.3200, 6.0000])
- 'mean' = ৫.২৮৪০ / ৫ = ১.০৫৬৮: ৮টি ঘরের মধ্যে ৫টি আসল; ignore করা ঘর ভাগের সংখ্যায় নেই।
- আকার: sequence-এর জন্য logits (B, T, C) হলে
CrossEntropyLossচায় (B, C, T), তাইlogits.transpose(1, 2); অথবা (B·T, C)-তে চ্যাপ্টা করুন। দুটি পথ একই ১.০৫৬৮. - Weight-এর গড়: শ্রেণি ৪-এর weight ৫ দিলে 'mean' দেয় ২.০০১২, যা weighted যোগফল ÷ weight-এর যোগফল; token সংখ্যা দিয়ে ভাগ করলে আসত ৩.৬০২১. নিজে 'none' নিয়ে গড় করলে এই পার্থক্য মনে রাখুন।
- দুটি বিপদ: শ্রেণি-সূচক পরিসরের বাইরে হলে IndexError (GPU-তে প্রায়ই অস্পষ্ট CUDA error হয়ে আসে); আর একটি batch-এর সব ঘর ignore হলে 'mean' দেয়
nan, যা পুরো training নষ্ট করতে পারে। খুব ছোট বা পুরো padding-এর batch থাকলে আগে পরীক্ষা করুন। - Huber বনাম SmoothL1:
HuberLoss(delta=2)= ২ ×SmoothL1Loss(beta=2); β = ১-এ দুটি এক।
৯ · Task দেখে loss বাছাই
সব মিলিয়ে প্রশ্নগুলো একই ক্রমে: output কী রকম (একটি শ্রেণি, কয়েকটি ট্যাগ, সংখ্যা, দূরত্ব)? ডেটায় noise বা outlier কেমন? শ্রেণির ভারসাম্য কেমন? আর শেষে কোন metric-এ বিচার হবে? নিচের stepper-এ বাজারঘরের পাঁচটি task.
| Task | |
| Output | |
| Loss | |
| সতর্কতা |
- একটি বিভাগ. শ্রেণিগুলো একে অপরকে বাদ দেয়, তাই categorical likelihood: cross-entropy. Overconfidence চিন্তার হলে label smoothing ০.১ চেষ্টা করুন, আর ECE মেপে দেখুন।
- একাধিক ট্যাগ. ট্যাগগুলো একে অপরকে বাদ দেয় না; প্রতিটি আলাদা Bernoulli, তাই BCEWithLogitsLoss আর float ০/১ লক্ষ্য। বিরল ট্যাগে pos_weight.
- ডেলিভারির দিন. সংখ্যা, আর outlier আছে যা আসল কিন্তু বিরল; Huber সাধারণ অর্ডারে MSE-র মতো মসৃণ, outlier-এ সীমিত টান। “৫০% অর্ডার এর মধ্যে” প্রতিশ্রুতি দিতে চাইলে L1 (median), অন্য quantile চাইলে pinball loss.
- বিরল ফেরত. সাধারণ CE দিয়ে শুরু, PR AUC দেখে, validation-এ threshold বাছা। Class weight বা focal loss রাখুন শুধু যদি কয়েকটি seed-এ লক্ষ্য-metric সত্যিই বাড়ায়; অংশ ৫-এ বাড়ায়নি।
- Token-এর tag. প্রতিটি token-এ একটি শ্রেণি, তাই cross-entropy, কিন্তু padding বাদ দিতে ignore_index বা mask, আর গড় token-এর সংখ্যায়। Sequence labeling-এর পুরো আলোচনা পর্ব ৪৩-এ।
আরও গভীরে: Label smoothing-এর পরিচিত প্রথম বর্ণনা Szegedy ও সহকর্মীদের “Rethinking the Inception Architecture for Computer Vision” (arXiv ২০১৫, CVPR ২০১৬); Transformer-এর মূল প্রবন্ধও (Vaswani ও সহকর্মীরা, ২০১৭) ε = ০.১ ব্যবহার করে লিখেছিল যে এতে perplexity খারাপ হয় কিন্তু BLEU ভালো হয়। Modern network-এর overconfidence নিয়ে বহুল উদ্ধৃত কাজ Guo ও সহকর্মীদের “On Calibration of Modern Neural Networks” (ICML ২০১৭)। Cross-entropy আর Brier score দুটিই “strictly proper scoring rule”: আসল probability বললেই প্রত্যাশিত জরিমানা সবচেয়ে কম (Gneiting আর Raftery, ২০০৭)। PyTorch-এর loss-গুলোর ঠিক সংজ্ঞা, বিশেষ করে weight আর reduction-এর আচরণ, নিজের version-এর torch.nn docs-এ মিলিয়ে নিন।
পরীক্ষা ও ইন্টারভিউতে:
- K = ৫, ε = ০.১-এ label smoothing-এর লক্ষ্য? সঠিক শ্রেণি ০.৯ + ০.০২ = ০.৯২, বাকি প্রতিটি ০.০২.
- Focal loss-এ γ = ২, pt = ০.৯ হলে CE-র তুলনায় কত গুণ ছোট? (১ − ০.৯)² = ০.০১, অর্থাৎ ১০০ গুণ।
- একটি constant fit-এ MSE আর L1 কী দেয়? MSE mean, L1 median; Huber মাঝামাঝি।
- Multi-label-এ softmax কেন নয়? Softmax শ্রেণিগুলোকে প্রতিযোগী করে আর যোগফল ১ বাধ্য করে; প্রতিটি ট্যাগ আলাদা sigmoid + BCE.
- Padding-এর loss কীভাবে বাদ দেবেন? লক্ষ্য −১০০ (ignore_index) বা Σ(loss·mask)/Σmask; mask করে সব ঘর দিয়ে ভাগ ভুল।
১০ · AI-এর যুগে — AI-এর বাছা loss যাচাই
“Imbalanced ডেটার জন্য একটি loss দাও” বললে AI assistant প্রায়ই সঙ্গে সঙ্গে focal loss লিখে দেয়, কারণ নামটি পরিচিত। এই পর্বের প্রায় সব ভুলই চুপচাপ: কোড চলে, loss নামে, শুধু metric বা probability ভুল। তাই নিচের জায়গাগুলো আলাদা করে দেখুন।
| AI প্রায়ই যা করে | ফল | কীভাবে ধরবেন |
|---|---|---|
Focal loss-এ আগে softmax, তারপর log আলাদা করে | ছোট probability-তে log(0), nan | log_softmax থেকে log pt, তারপর exp |
Multi-label task-এ CrossEntropyLoss | ট্যাগগুলো জোর করে প্রতিযোগী | লক্ষ্যের আকার (N, C) float হলে BCEWithLogitsLoss |
| Padding-সহ সব token-এর গড়, বা mask করে সব ঘর দিয়ে ভাগ | ভুয়া label শেখা, বা loss কম দেখানো | Token-সংখ্যা গুনে হাতে একটি batch-এর গড় মেলান |
| Class weight দিয়ে “recall বেড়েছে” দাবি | শুধু threshold সরেছে, ranking একই | PR AUC আর একই recall-এ precision, কয়েকটি seed-এ |
KLDivLoss-এ দুটি সাধারণ probability, default reduction | ভুল মান, সতর্কবার্তা | Input log-probability, reduction="batchmean", হাতে হিসাবের সঙ্গে মিল |
পুরোনো বা বানানো argument (যেমন size_average, reduce) | Deprecated বা error | নিজের PyTorch version-এর docs |
AI-কে loss-এর সঙ্গে প্রমাণও চাইতে বলুন:
AI-এর দেওয়া loss হাতে পেলে — যাচাইয়ের চেকলিস্ট
ভাবনার প্রশ্ন
প্রতিটি প্রশ্ন নিয়ে নিজে কিছুক্ষণ ভাবুন — তারপর “→ উত্তর” চাপুন।
প্র ০১Label smoothing এত সরল একটি কৌশল — তবু কেন বলা হয় এটি কিছু তথ্য মুছে দেয়, আর distillation-এ কেন সাবধান থাকতে হয়?
Label smoothing-এর পরিচিত প্রথম বর্ণনা Inception-v3-এর প্রবন্ধে (Szegedy ও সহকর্মীরা, arXiv ২০১৫, CVPR ২০১৬)। যুক্তি ছিল সহজ: one-hot লক্ষ্য model-কে সঠিক logit অসীমের দিকে ঠেলতে বলে, যা overfitting আর অতি-আত্মবিশ্বাস বাড়ায়; ε দিয়ে লক্ষ্য একটু নরম করলে সেই তাগিদ থামে। পরে Transformer-এর মূল প্রবন্ধ (২০১৭) ε = ০.১ ব্যবহার করে এবং স্পষ্ট লেখে যে model “কম নিশ্চিত” হতে শেখায় perplexity খারাপ হয়, কিন্তু অনুবাদের BLEU ভালো হয়। অর্থাৎ শুরু থেকেই এটি একটি বিনিময়।
Müller, Kornblith আর Hinton-এর “When Does Label Smoothing Help?” (NeurIPS ২০১৯) ভেতরের ছবিটি দেখান। শেষ layer-এর আগের representation-এ label smoothing একই শ্রেণির উদাহরণগুলোকে শক্ত গুচ্ছে টানে, আর গুচ্ছগুলোকে প্রায় সমান দূরত্বে রাখে, কারণ প্রতিটি ভুল শ্রেণি একই ε/K পায়। ফলে “এই শার্টটি টি-শার্টের কাছাকাছি, জুতার থেকে অনেক দূরে” এই তথ্য কিছুটা হারায়। তাঁদের পরীক্ষায় label smoothing দিয়ে train করা teacher থেকে distillation-এ student খারাপ শিখেছিল, কারণ distillation ঠিক এই আপেক্ষিক মিলের তথ্যই ব্যবহার করে। একই প্রবন্ধে calibration-এ উন্নতিও দেখানো হয়, যা অংশ ৩-এর ছোট পরীক্ষার সঙ্গে মেলে।
ব্যবহারিক দিক থেকে তিনটি কথা। প্রথম, label noise থাকলে label smoothing একধরনের সুরক্ষা দেয়, কারণ ভুল label-এর ওপর সম্পূর্ণ বিশ্বাস করে না। দ্বিতীয়, শ্রেণি অনেক হলে (হাজারের মতো) ε/K খুব ছোট, তাই প্রভাবও বদলায়; ε টিউন করতে হয়। তৃতীয়, model-এর probability পরে অন্য কোনো সিস্টেমে যাবে (teacher, ranking, ঝুঁকির হিসাব) কি না, তা আগে ভাবুন। শুধু accuracy চাইলে এটি প্রায় বিনা খরচের regularizer, কিন্তু probability-র গঠন বদলে দেয়।
মূল উপলব্ধি: Label smoothing confidence কমায় আর প্রায়ই calibration ভালো করে, কিন্তু শ্রেণিগুলোর আপেক্ষিক মিলের তথ্য কিছুটা মুছে দেয়; teacher model বা probability-নির্ভর সিস্টেমে ব্যবহারের আগে মেপে দেখুন।
প্র ০২Focal loss object detection-এ এত সফল হলো, অথচ বাজারঘরের tabular task-এ PR AUC বাড়াল না — কেন?
Focal loss-এর জন্ম একটি নির্দিষ্ট সমস্যা থেকে। ২০১৭ সালের আগে সবচেয়ে নির্ভুল detector-গুলো দুই ধাপের ছিল: প্রথমে কয়েকশো সম্ভাব্য অঞ্চল বাছাই, তারপর শ্রেণিভুক্ত করা। এক ধাপের detector দ্রুত, কিন্তু প্রতিটি ছবিতে প্রায় এক লাখ সম্ভাব্য বাক্স সরাসরি শ্রেণিভুক্ত করে, যার প্রায় সবই সহজ পটভূমি। Lin ও সহকর্মীরা যুক্তি দেন যে এই অসংখ্য সহজ negative-এর ছোট ছোট loss মিলে training-কে দখল করে নেয়, যা অংশ ৪-এর stepper-এ ১০০০টি সহজ বনাম ১০টি কঠিন উদাহরণে দেখেছেন। Focal loss দিয়ে তাঁদের এক ধাপের RetinaNet সেই সময়ের দুই ধাপের detector-গুলোর সমান বা ভালো ফল দিয়েছিল বলে রিপোর্ট করা।
বাজারঘরের task-এর চেহারা আলাদা। এখানে imbalance প্রায় ৩০:১, detection-এর পটভূমি বনাম বস্তুর মতো হাজার:এক-এর ঘরে নয়; আর সাধারণ অর্ডারগুলোর অনেকই খুব সহজ নয়, কারণ ডেটায় আসল noise আছে (একই রকম feature-এর দুটি অর্ডারের একটি ফেরত আসে, অন্যটি আসে না)। সেই noise-ভরা উদাহরণগুলো focal loss-এর চোখে “কঠিন”, তাই সে সেগুলোতে জোর দেয়, যদিও আরও শেখার কিছু নেই। তার ওপর PR AUC একটি ranking metric; একটি loss probability-কে ওপরে-নিচে সরালেও ক্রম একই থাকলে PR AUC বদলায় না। Class weight ঠিক এটাই করেছে।
আরও একটি বিষয়: ছোট MLP আর সরল feature-এ model-এর ক্ষমতাই সীমা হতে পারে। loss-এর জোর যেখানেই দিন, model যা আলাদা করতে পারে না, তা পারবে না। গবেষণায়ও focal loss-এর লাভ task ভেদে মিশ্র দেখা গেছে; Mukhoti ও সহকর্মীরা (২০২০) আবার দেখান যে focal loss calibration-এ সাহায্য করতে পারে, যা আলাদা একটি সুবিধা। তাই “imbalance মানেই focal loss” একটি সাধারণীকরণ, নিয়ম নয়।
মূল উপলব্ধি: Focal loss বিপুল সংখ্যক সহজ উদাহরণের দখল ভাঙতে তৈরি; noise-ভরা, মাঝারি imbalance-এর task-এ তার লাভ না-ও থাকতে পারে, তাই threshold-নিরপেক্ষ metric-এ কয়েকটি seed-এ মেপে সিদ্ধান্ত নিন।
প্র ০৩শ্রেণিভুক্তির বিচার শেষে accuracy দিয়ে হয়, তবু training-এ accuracy বা MSE নয়, cross-entropy কেন?
প্রথম কারণ গাণিতিক। Accuracy একটি সিঁড়ির মতো function: weight সামান্য বদলালে প্রায় সবসময় accuracy একই থাকে, আর কোনো এক জায়গায় হঠাৎ লাফ দেয়। তার gradient প্রায় সর্বত্র শূন্য, তাই gradient descent কোনো দিক পায় না। এ জন্য একটি মসৃণ “বিকল্প” loss লাগে, যা কমালে accuracy-ও সাধারণত বাড়ে; cross-entropy সেই বিকল্প।
দ্বিতীয় কারণ gradient-এর আকার। Sigmoid বা softmax-এর পরে MSE বসালে gradient-এ softmax-এর derivative গুণ হয়, যা model ভুলভাবে নিশ্চিত হলে প্রায় শূন্য। অর্থাৎ যখন সংশোধন সবচেয়ে দরকার, তখনই শেখা থামে। Cross-entropy-তে log আর softmax-এর exp কাটাকাটি হয়ে gradient দাঁড়ায় p − y, যা ভুল যত বড়, তত বড়। ১৯৮০-৯০-এর দশকের neural network-এ অনেকে MSE ব্যবহার করতেন; শ্রেণিভুক্তিতে cross-entropy-র সুবিধা পরে ধীরে ধীরে মানক অভ্যাসে পরিণত হয়।
তৃতীয় কারণ পরিসংখ্যানিক। Cross-entropy হলো categorical likelihood-এর negative log, তাই এটি কমানো মানে maximum likelihood. আর এটি একটি strictly proper scoring rule (Gneiting আর Raftery, ২০০৭): model যদি আসল probability জানে, তবে সেটাই বললে প্রত্যাশিত জরিমানা সবচেয়ে কম। তাই তত্ত্বে cross-entropy model-কে সৎ probability দিতে উৎসাহ দেয়। বাস্তবে overparameterized network train set মুখস্থ করে বলে এই তত্ত্ব পুরো খাটে না; Guo ও সহকর্মীরা (২০১৭) দেখান যে আধুনিক গভীর network প্রায়ই অতি-আত্মবিশ্বাসী, যা অংশ ৩-এর ০.৯৩ বনাম ০.৮৬-তেও দেখেছেন। একই কারণে Brier score (probability-র MSE) আরেকটি proper rule, কিন্তু তার gradient দুর্বল বলে training-এ কম ব্যবহৃত।
মূল উপলব্ধি: Cross-entropy মসৃণ, ভুলের অনুপাতে জোরালো gradient দেয়, আর সৎ probability-কে পুরস্কৃত করে; তবু গভীর network-এ overconfidence আসে, তাই calibration আলাদা করে মাপতে হয়।
প্র ০৪Outlier দেখলেই Huber বা L1 বসানো কি সবসময় ঠিক? Outlier যদি আসল তথ্য হয়?
Robust পরিসংখ্যানের আধুনিক ভিত্তি Peter Huber-এর ১৯৬৪ সালের প্রবন্ধ “Robust Estimation of a Location Parameter”. তিনি প্রশ্ন করেন: ডেটার বেশিরভাগ যদি প্রায় normal হয় কিন্তু অল্প কিছু অংশ দূষিত হয়, তবে কোন অনুমান সবচেয়ে খারাপ অবস্থাতেও ভালো থাকে? উত্তর হিসেবে আসে মাঝে বর্গ, দূরে সরলরেখার loss, যা আজ Huber loss নামে পরিচিত। Deep learning-এ এর আত্মীয় SmoothL1 Fast R-CNN (Girshick, ২০১৫)-এ bounding box-এর জন্য ব্যবহৃত হয়, কারণ box-এর লক্ষ্যে মাঝে মাঝে বড় ভুল থাকে আর MSE তাতে training অস্থির করত।
কিন্তু “outlier” শব্দটি দুই রকম জিনিস ঢাকে। এক, ভুল এন্ট্রি: কেউ ২ দিনের জায়গায় ২০ লিখেছেন। এগুলোর প্রভাব কমানো ঠিক, আর পারলে ডেটা পরিষ্কার করাই ভালো। দুই, আসল কিন্তু বিরল ঘটনা: সত্যিই বন্যায় ২০ দিন লেগেছে। এগুলো ব্যবসার জন্য হয়তো সবচেয়ে জরুরি তথ্য। অংশ ৬-এর ব্লকে L1-এর উত্তর ছিল ২.৪ দিন, যা “সাধারণ অর্ডার”-এর জন্য ভালো প্রতিশ্রুতি; কিন্তু গুদামের মোট খরচ বা গাড়ির পরিকল্পনা করতে mean (৩.৫৩)-ই প্রাসঙ্গিক, কারণ খরচ যোগ হয়, median নয়।
তাই প্রশ্নটি loss-এর নয়, লক্ষ্যের: আপনি কোন পরিসংখ্যানটি অনুমান করতে চান? MSE শর্তসাপেক্ষ গড় দেয়, L1 শর্তসাপেক্ষ median, pinball loss যেকোনো quantile (যেমন “৯০% অর্ডার এর মধ্যে”, মেশিন লার্নিং কোর্সের পর্ব ২৪)। বিরল ঝুঁকি নিজেই লক্ষ্য হলে আলাদা model বা অনুমানের পরিসর (conformal prediction) আরও সৎ। আর Huber-এর δ লক্ষ্যের এককে, তাই লক্ষ্য standardize করলে δ = ১-এর অর্থ “এক মানবিচ্যুতি”; না করলে অর্থ “এক দিন”.
মূল উপলব্ধি: Robust loss ভুল এন্ট্রির টান কমায়, কিন্তু আসল বিরল ঘটনার তথ্যও চাপা দেয়; আগে ঠিক করুন mean, median না কোনো quantile আপনার সিদ্ধান্তের জন্য দরকার, তারপর loss বাছুন।
প্র ০৫Sequence task-এ loss token-এর গড়ে নেবেন, না sequence-এর গড়ের গড়ে? আর gradient accumulation-এ এতে কী গোলমাল হতে পারে?
অংশ ৮-এর ব্লকে দুটি বৈধ উত্তর এসেছিল: token গড় ১.১৫৬৫, আর প্রতি রিভিউর গড়ের গড় ১.৪০৪৮. প্রথমটিতে প্রতিটি token সমান ওজন পায়, তাই লম্বা রিভিউর প্রভাব বেশি। দ্বিতীয়টিতে প্রতিটি রিভিউ সমান, তাই ২ token-এর একটি ছোট রিভিউ ৭ token-এর রিভিউয়ের সমান গুরুত্ব পায়। Language model-এর pretraining-এ সাধারণত token গড় নেওয়া হয়, কারণ লক্ষ্য প্রতিটি পরের token ভালোভাবে অনুমান করা। কিন্তু যদি ছোট উত্তরগুলো সমান গুরুত্বপূর্ণ হয় (যেমন chatbot-এর ছোট উত্তর), তবে sequence-ভিত্তিক গড় যুক্তিসঙ্গত। দুটির কোনোটিই “ভুল” নয়; ভুল হলো না জেনে একটি বেছে নেওয়া।
গোলমাল বাধে gradient accumulation-এ, যেখানে বড় batch-এর অনুকরণে কয়েকটি ছোট batch-এর gradient যোগ করা হয় (পর্ব ১৫)। যদি প্রতিটি ছোট batch নিজের token-সংখ্যা দিয়ে গড় করে, তারপর সেই গড়গুলোর আবার গড় নেওয়া হয়, তবে তা পুরো বড় batch-এর token গড়ের সমান নয়: কম token-এর batch বেশি ওজন পায়। ঠিক এই ধরনের অসমতা নিয়ে ২০২৪ সালে কয়েকটি জনপ্রিয় training library-তে gradient accumulation-এর loss ঠিক না থাকার একটি সমস্যা প্রকাশ্যে আলোচিত হয়েছিল, আর পরে সংশোধন করা হয় বলে জানা যায়। সমাধানের ধারণা সরল: প্রতিটি ছোট batch থেকে loss-এর যোগফল নিন, আর শেষে পুরো বড় batch-এর মোট আসল token-সংখ্যা দিয়ে একবার ভাগ করুন।
একই যুক্তি একাধিক GPU-তে চলা training-এও খাটে, যেখানে প্রতিটি device আলাদা batch দেখে। আর এটি পর্ব ১০-এর “metric গড় batch-এর আকার দিয়ে” নিয়মের সরাসরি সম্প্রসারণ: গড় সবসময় কোন একক (উদাহরণ, token, sequence) ধরে, তা স্পষ্ট হতে হবে।
মূল উপলব্ধি: Token গড় আর sequence গড় দুটি আলাদা লক্ষ্য; যেটিই বাছুন, mask সঠিক রাখুন আর accumulation বা একাধিক device-এ যোগফল ও মোট গণনা আলাদা রেখে শেষে একবার ভাগ করুন।
অনুশীলন
প্রথমে খাতায় করুন, তারপর উত্তর মেলান।
-
পূর্ণ numerical: ৪ শ্রেণির একটি model সঠিক শ্রেণি ১-এর একটি উদাহরণে probability দিল p = [০.১, ০.৭, ০.১, ০.১]. (ক) সাধারণ cross-entropy কত? (খ) ε = ০.১-এ label smoothing-এর লক্ষ্য আর loss কত? (গ) γ = ২-এ focal loss (α ছাড়া) কত? (ঘ) একটি train set-এ ৯,৬০০টি সাধারণ আর ৪০০টি বিরল উদাহরণ; balanced class weight কত?
(ক) −ln ০.৭ = ০.৩৫৬৭. (খ) লক্ষ্য q = [০.০২৫, ০.৯২৫, ০.০২৫, ০.০২৫] (০.৯ + ০.১/৪ আর ০.১/৪)। Loss = ০.৯২৫ × ০.৩৫৬৭ + ৩ × ০.০২৫ × (−ln ০.১) = ০.৩২৯৯ + ০.০৭৫ × ২.৩০২৬ = ০.৩২৯৯ + ০.১৭২৭ = ০.৫০২৬. (গ) (১ − ০.৭)² × ০.৩৫৬৭ = ০.০৯ × ০.৩৫৬৭ = ০.০৩২১, CE-র প্রায় এগারো ভাগের এক ভাগ। (ঘ) wc = N/(K·nc): সাধারণ ১০,০০০/(২ × ৯,৬০০) ≈ ০.৫২০৮, বিরল ১০,০০০/(২ × ৪০০) = ১২.৫; অনুপাত ২৪:১, যা শ্রেণির অনুপাতের সমান।
-
সমালোচনা ও নকশা: একটি AI assistant বাংলা রিভিউয়ের token tagging-এর জন্য এই loss দিয়েছে:
p = logits.softmax(-1); loss = -(1 - p.gather(-1, y[..., None])) ** 2 * p.gather(-1, y[..., None]).log(); loss = (loss.squeeze(-1) * mask).mean(), আর padding-এর ঘরে y = ০. সঙ্গে দাবি: “focal loss imbalance ঠিক করবে, recall দেখুন ০.৮৩ হয়েছে”. কী কী সমস্যা, আর আপনি কীভাবে ঠিক করবেন?১, স্থিরতা: softmax-এর পরে log; খুব ছোট p-তে log(০) = −∞ আর nan.
log_softmaxথেকে log pt নিন, pt = exp(log pt). ২, গড়: mask দিয়ে padding শূন্য করে.mean()সব ঘর দিয়ে ভাগ করে; loss কম দেখায় আর padding-এর পরিমাণের ওপর নির্ভর করে। লিখুন(loss * mask).sum() / mask.sum(), অথবা padding-এ y = −১০০ দিয়ে বাদ দিন। ৩, দাবি: একটি threshold-এ recall দেখে উন্নতি বলা যায় না; সাধারণ CE-র সঙ্গে একই threshold-নিরপেক্ষ metric (প্রতিটি tag-এর PR AUC বা macro-F1, validation-এ বাছা threshold-এ) তুলনা করুন, কয়েকটি seed-এ। ৪, যাচাই: γ = ০ দিলে loss যেনF.cross_entropy(..., ignore_index=-100)-এর সঙ্গে হুবহু মেলে, তার একটি পরীক্ষা লিখুন। -
আউটপুট অনুমান করুন: চালানোর আগে লিখে ফেলুন নিচের কোড কী ছাপবে (ln ৩ ≈ ১.০৯৮৬)।
import torch, torch.nn as nn z = torch.zeros(3, 3); y = torch.tensor([0, -100, 2]) for red in ("none", "sum", "mean"): print(red, nn.CrossEntropyLoss(reduction=red)(z, y)) print("ls", nn.CrossEntropyLoss(label_smoothing=0.1)(z, y))none tensor([1.0986, 0.0000, 1.0986]) sum tensor(2.1972) mean tensor(1.0986) ls tensor(1.0986)(সত্যিকারের run, PyTorch 2.15.0.) সব logit শূন্য, তাই প্রতিটি শ্রেণির probability ১/৩ আর loss ln ৩ = ১.০৯৮৬. মাঝের লক্ষ্য −১০০, তাই তার loss ০ আর গড়ে গোনা হয় না: যোগফল ২.১৯৭২, ভাগ ২ দিয়ে, গড় ১.০৯৮৬ (৩ দিয়ে ভাগ করলে আসত ০.৭৩২৪)। Label smoothing-এও ১.০৯৮৬, কারণ সমান probability-তে প্রতিটি শ্রেণির −ln p একই, আর q-এর যোগফল ১.
-
কোড লিখুন: একটি
focal_loss(logits, target, gamma=2.0, alpha=None, ignore_index=-100)function লিখুন: logits (N, C), target (N,) int64; ignore করা ঘর বাদ; alpha থাকলে প্রতিটি শ্রেণির ওজন; ফল আসল উদাহরণগুলোর গড়। γ = ০-এ এটিF.cross_entropy-র সমান কি না যাচাই করুন।import torch.nn.functional as F def focal_loss(logits, target, gamma=2.0, alpha=None, ignore_index=-100): valid = target != ignore_index logits, target = logits[valid], target[valid] logp_t = F.log_softmax(logits, dim=1).gather(1, target[:, None]).squeeze(1) loss = -(1 - logp_t.exp()) ** gamma * logp_t if alpha is not None: loss = loss * alpha[target] return loss.mean()log_softmaxথেকে log pt নেওয়ায় কোনো log(০) নেই। ছয়টি এলোমেলো উদাহরণে (একটি −১০০) সত্যিকারের run-এ γ = ০ দিলে এলো1.808111548423767, আরF.cross_entropy-ও হুবহু1.808111548423767; γ = ২-এ ১.৩৪৯৮. লক্ষ্য করুন: alpha দিলে এখানে সাধারণ গড় নেওয়া হয়েছে, PyTorch-এর weighted CE-র মতো weight-এর যোগফল দিয়ে ভাগ নয়; কোনটি চান তা লিখে রাখুন। সব ঘর ignore হলেmean()nan দেবে, তাই সেটিও পরীক্ষা করুন।
নিজেকে যাচাই করুন
ভুল হলে কারণসহ ব্যাখ্যা পাবেন, আবার চেষ্টাও করতে পারবেন।
ক্রমPadding-সহ একটি token tagging batch-এর masked cross-entropy হাতে বের করার ধাপগুলো সঠিক ক্রমে সাজান (▲▼ চেপে সরান)
- Model থেকে (B, T, C) আকারের logits নেওয়া
- প্রতিটি ঘরে সবচেয়ে বড় logit বিয়োগ করে log-softmax
- প্রতিটি ঘরে সঠিক tag-এর log-probability তুলে নিয়ে ঋণাত্মক করা
- আসল দৈর্ঘ্য থেকে mask বানিয়ে padding ঘরের loss শূন্য করা
- Mask করা loss-এর যোগফলকে আসল token-এর সংখ্যা দিয়ে ভাগ করা
৫ শ্রেণির একটি classifier-এ ε = ০.১ দিয়ে label smoothing করলে সঠিক শ্রেণি আর প্রতিটি ভুল শ্রেণির লক্ষ্য-probability কত?
- ০.৯ আর ০.১
- ০.৯২ আর ০.০২
- ০.৯ আর ০.০২৫
- ০.৮৪ আর ০.০৪
Focal loss FL = −(1 − pt)γ ln pt-এ γ = ২. একটি উদাহরণে সঠিক শ্রেণির probability pt = ০.৯. সাধারণ cross-entropy-র তুলনায় focal loss কত গুণ ছোট?
- ১০ গুণ
- ২ গুণ
- ১০০ গুণ
- একই থাকে
ডেলিভারির দিনের ৪০টি মান, যার ৩টি বড় outlier (১৪, ১৮, ২১ দিন)। সব অর্ডারে একটিই constant অনুমান দিলে কোন loss সেরা constant হিসেবে median বেছে নেয়?
- L1 (mean absolute error)
- MSE
- Huber (δ = ১)
- Cross-entropy
PyTorch-এ nn.CrossEntropyLoss(weight=w), default reduction="mean". একটি batch-এর per-sample loss-এর ওপর গড়টি কীভাবে হিসাব হয়?
- Weighted loss-এর যোগফল ÷ উদাহরণের সংখ্যা
- Weight উপেক্ষা করে সাধারণ গড়
- Weighted loss-এর যোগফল ÷ শ্রেণির সংখ্যা
- Weighted loss-এর যোগফল ÷ সেই উদাহরণগুলোর লক্ষ্য-শ্রেণির weight-এর যোগফল
একটি পণ্যের একসঙ্গে কয়েকটি ট্যাগ থাকতে পারে (দেশি, অর্গানিক, ছাড়, উপহার)। PyTorch-এ কোন সমন্বয় ঠিক?
- (N, 4) logits, (N,) int64 লক্ষ্য, CrossEntropyLoss
- (N, 4) logits, (N, 4) float ০/১ লক্ষ্য, BCEWithLogitsLoss
- (N, 4) sigmoid-এর পরের মান, MSELoss
- (N, 1) logit, BCEWithLogitsLoss
৩% বিরল শ্রেণির একটি binary task-এ একই model সাধারণ cross-entropy আর balanced class weight দিয়ে train করা হলো। সাধারণত কী আশা করবেন?
- সব metric-এ, PR AUC-সহ, স্পষ্ট উন্নতি
- ০.৫ threshold-এ বিরল শ্রেণির recall কমে
- ০.৫ threshold-এ recall বাড়ে, precision কমে, PR AUC প্রায় একই থাকতে পারে
- Probability আরও ভালোভাবে calibrated হয়
শব্দকোষ
লেখার মধ্যে ডটেড দাগ দেওয়া শব্দে মাউস রাখুন বা চাপুন — অর্থ দেখাবে। এই পর্বের সব নতুন শব্দ এখানে একসাথে:
মনে রাখুন
- Loss = অনুমান: cross-entropy categorical NLL, BCE Bernoulli, MSE Gaussian, L1 Laplace. Cross-entropy-র gradient p − লক্ষ্য, যা সঠিক logit-কে কখনো থামায় না।
- Label smoothing: q = (1 − ε)y + ε/K; loss-এর নিচের সীমা H(q), confidence কমে, ECE প্রায়ই কমে, কিন্তু শ্রেণির মিলের তথ্য কিছুটা হারায়।
- Imbalance: class weight আর focal loss (−(1 − pt)γ ln pt) মূলত জোরের বণ্টন আর threshold বদলায়; বিচার PR AUC আর বাছা threshold-এ, কয়েকটি seed-এ।
- Regression: MSE → mean, L1 → median, Huber মাঝে; Huber = δ × SmoothL1(β = δ), δ লক্ষ্যের এককে।
- Reduction আর mask: ignore_index −১০০ বা Σ(loss·mask)/Σmask; weight দিলে 'mean' ভাগ করে weight-এর যোগফলে; সব-padding batch-এ nan.
আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ
- পর্ব ১৪ · Weight initialization আর normalization — Xavier, He, BatchNorm আর LayerNormপরবর্তী পর্বXavier আর He init, symmetry-র সমস্যা, BatchNorm, LayerNorm আর RMSNorm বোঝা।
- ডিপ লার্নিং, NLP আর Generative AI · কোর্স হোম৯১টি পর্ব১৪টি মডিউলের পুরো রোডম্যাপ; পর্ব ১৪ (initialization আর normalization) এখান থেকে খুলবেন।
- পর্ব ১০ · Training loopআগের পর্বCrossEntropyLoss-এ logits, BCEWithLogitsLoss আর batch-এর আকার দিয়ে গড়।
- পর্ব ১১ · Dataset আর DataLoaderআগের পর্বPadding, attention mask আর WeightedRandomSampler.
- AI-এর ভিত্তি · পর্ব ৩৮ · Entropy আর informationআগের ভিত্তিEntropy, cross-entropy আর KL divergence-এর মানে।
- মেশিন লার্নিং · পর্ব ২৬ · Probability calibrationআগের ভিত্তিReliability diagram, ECE আর temperature scaling.
- মেশিন লার্নিং · পর্ব ৫০ · Imbalanced ডেটাআগের ভিত্তিResampling, SMOTE, class weight আর threshold.
- মেশিন লার্নিং · পর্ব ২৪ · Robust আর quantile regressionপাশের ট্র্যাকHuber, pinball loss আর অনুমানের পরিসর।