এই পর্বে যা শিখবেন
- Calibration আর discrimination আলাদা করা, আর কোন কাজে সৎ সম্ভাবনা লাগে তা চেনা
- Reliability diagram হাতে আঁকা, সমান-প্রস্থ আর সমান-সংখ্যার ঝুড়ির পার্থক্য, আর ECE ও Brier score হাতে হিসাব
- Brier score-কে reliability, resolution আর uncertainty-তে ভাঙা এবং যোগফল মিলিয়ে দেখা
- Platt scaling আর isotonic regression নিজে লেখা, তারপর CalibratedClassifierCV দিয়ে, আর calibration-এর leakage ধরা
- Calibrated সম্ভাবনা দিয়ে খরচের সিদ্ধান্ত, আর ফেরতের হার বদলালে odds দিয়ে সম্ভাবনা সংশোধন
AI-এর ভিত্তি কোর্সের পর্ব ৫৯-এ calibration-এর প্রথম দেখা পেয়েছেন: calibration_curve দিয়ে পাঁচটি ঝুড়ি, আর কড়া penalty দিলে logistic regression-এর সম্ভাবনা গড়ের দিকে চেপে যায়। সেখানে কথা দেওয়া ছিল, সারানোর পদ্ধতি পরের কোর্সে আসবে। এই কোর্সের পর্ব ০২-এ দেখেছেন log loss আর Brier score proper scoring rule, আর hinge loss-এর সেরা উত্তর সম্ভাবনা নয়। এই পর্ব সেই সুতোগুলো এক জায়গায় বাঁধে: সম্ভাবনা কতটা সৎ তা কীভাবে মাপবেন, কেন model ভুল বলে, আর কীভাবে সারাবেন। চালানো যায় এমন চারটি ব্লক পাতাতেই চলে (ব্রাউজারের Python, scikit-learn 1.8.0); প্রথমবার scikit-learn নামতে প্রায় দশ সেকেন্ড লাগে।
১ · ০.৭ বললে কি ৭০%? — calibration আর discrimination
আবহাওয়া অফিস বলল, “কাল বৃষ্টির সম্ভাবনা ৭০%”. একটি দিন দেখে এই কথা ঠিক না ভুল বলা যায় না। কিন্তু যতদিন তারা “৭০%” বলেছে, সেই দিনগুলোর কতদিনে সত্যিই বৃষ্টি হয়েছে? প্রায় ৭০% হলে পূর্বাভাস সৎ। ৯০% দিনে বৃষ্টি হলে তারা সাবধানী, ৪০% দিনে হলে অতি-আত্মবিশ্বাসী। Machine learning-এর calibration ঠিক এই পরীক্ষা।
সূত্রে: model প্রতিটি অর্ডারের জন্য একটি সংখ্যা p̂(x) দেয়। Model পুরোপুরি calibrated যদি প্রতিটি p-এর জন্য
P(Y = 1 | p̂(X) = p) = p
এখানে Y আসল ফল (ফেরত এলে ১); বাঁ দিক মানে “যেসব অর্ডারে model p বলেছে, তাদের ফেরতের আসল হার”. শর্তটি একটি অর্ডারের নয়, একই সংখ্যা পাওয়া দলের।
এর পাশে আরেকটি গুণ আছে: discrimination, অর্থাৎ ফেরত-অর্ডারকে বেশি আর না-ফেরত অর্ডারকে কম সংখ্যা দেওয়ার ক্ষমতা। AUC এটিই মাপে (AI-এর ভিত্তি কোর্সের পর্ব ৬০)। দুটি গুণ স্বাধীন, দুটি চরম উদাহরণে তা পরিষ্কার:
- Model ক: প্রতিটি ফেরত-অর্ডারকে ০.৫১, প্রতিটি না-ফেরতকে ০.৪৯ বলে। ক্রম নিখুঁত, AUC = ১. কিন্তু “০.৫১” বলা অর্ডারগুলোর ১০০% ফেরত এসেছে: ভয়ানক ভুল calibrated.
- Model খ: সবাইকে দোকানের গড় ফেরতের হার ০.৩২ বলে। “০.৩২” বলা অর্ডারগুলোর ঠিক ৩২% ফেরত: সংজ্ঞা অনুযায়ী calibrated. কিন্তু AUC = ০.৫, কোনো কাজের নয়।
Score-এর ওপর যেকোনো একঘেয়ে বাড়ন্ত রূপান্তর ক্রম বদলায় না, তাই AUC-ও না। Calibration ঠিক এমন রূপান্তর: ক্রম ভালো করে না, শুধু সংখ্যাগুলোকে সৎ করে।
| সম্ভাবনা দিয়ে কী করবেন | Calibration লাগে? | কেন |
|---|---|---|
| সবচেয়ে ঝুঁকির ২০০ অর্ডারে ফোন করা (শুধু ক্রম) | না | ক্রম একই থাকে |
| খরচ দেখে threshold, যেমন p > ০.২ হলে ফোন | হ্যাঁ | ০.২ সংখ্যাটির অর্থ আছে (অংশ ৯) |
| মাসে কত টাকা ফেরতে যাবে, তার বাজেট (p-এর যোগফল) | হ্যাঁ | যোগফল তখনই সৎ, যখন প্রতিটি p সৎ |
| দুটি model-এর সম্ভাবনা মেলানো, বা অন্য হিসাবে বসানো | হ্যাঁ | মাপ এক না হলে মেলানো অর্থহীন |
| গ্রাহক বা কর্মীকে “৮৫% নিশ্চিত” দেখানো | হ্যাঁ | মানুষ সংখ্যাটি বিশ্বাস করে সিদ্ধান্ত নেয় |
২ · Reliability diagram — ঝুড়ি ধরে মিলিয়ে দেখা
সংজ্ঞার “p̂ = p” শর্তটি বাস্তবে সরাসরি মাপা যায় না, কারণ ঠিক ০.৬৫০০০ পাওয়া অর্ডার হয়তো একটিও নেই। তাই কাছাকাছি সংখ্যাগুলোকে একটি ঝুড়িতে (bin) রাখা হয়। প্রতিটি ঝুড়ির জন্য দুটি সংখ্যা: গড় অনুমান (x অক্ষ) আর বাস্তবে ফেরতের হার (y অক্ষ)। বিন্দুগুলো কর্ণরেখা y = x-এর ওপর থাকলে model calibrated. নিচে একটি ঝুড়ি ভরার পুরো হিসাব:
- কাঁচা ডেটা। বারোটি test অর্ডার, model-এর সম্ভাবনা p আর পরে জানা ফল y. Calibration সবসময় নতুন ডেটায় মাপতে হয়।
- ঝুড়ি বাছাই। [০.৬, ০.৭) ঝুড়িতে পড়ে অর্ডার ৪, ৭, ৮, ৯ আর ১০. বাকি ঝুড়িতেও একই কাজ।
- গড় অনুমান। যোগফল ৩.২৫, গড় ০.৬৫. ঝুড়ির মাঝখান নয়, আসল গড়টিই x অক্ষে বসে (এখানে কাকতালীয়ভাবে দুটি সমান)।
- বাস্তব হার। পাঁচটির তিনটি ফেরত এসেছে, হার ৩/৫ = ০.৬০. এটি y অক্ষ।
- বিন্দু আর ফাঁক। (০.৬৫, ০.৬০) কর্ণরেখার ০.০৫ নিচে: model যত বলেছে, ঘটেছে তার চেয়ে কম।
- সাবধান, n ছোট। আসল হার ০.৬৫ হলেও পাঁচটির হারের standard deviation প্রায় ০.২১. তাই ০.০৫-এর ফাঁক থেকে কিছুই বলা যায় না; প্রতিটি ঝুড়িতে যথেষ্ট অর্ডার লাগে।
ঝুড়ি কীভাবে কাটবেন — সমান প্রস্থ না সমান সংখ্যা
scikit-learn-এর calibration_curve(y_true, y_prob, n_bins=5, strategy="uniform") দুই রকম ঝুড়ি দেয়। "uniform" মানে [০, ০.১), [০.১, ০.২) … সমান প্রস্থ; পড়া সহজ, কিন্তু অনুমান কম পড়া অঞ্চলের ঝুড়িতে দুই-চারটি অর্ডার, তাই বিন্দু লাফায়। "quantile" মানে প্রতিটি ঝুড়িতে প্রায় সমান অর্ডার; বিন্দুগুলো সমান নির্ভরযোগ্য, কিন্তু অনুমান ঘন হলে গাদাগাদি। খালি ঝুড়ি বাদ পড়ে। দুটিই দেখুন, সঙ্গে অনুমানের একটি histogram: কোন অঞ্চলে কত অর্ডার, তা না জানলে বাঁকা বিন্দুর গুরুত্ব বোঝা যায় না।
Reliability diagram-এর তিনটি চেনা আকার
Reading a reliability diagram: diagonal, over-confident and under-confident shapes
৩ · ECE, MCE আর Brier score — calibration এক সংখ্যায়
ছবি পড়তে ভালো, কিন্তু অনেক model তুলনা বা রিপোর্টের জন্য একটি সংখ্যা দরকার। সবচেয়ে প্রচলিত হলো expected calibration error (ECE): প্রতিটি ঝুড়ির ফাঁক, ঝুড়ির অর্ডারের অনুপাত দিয়ে ওজন করে যোগ।
ECE = ∑b (nb / N) · | ōb − p̄b |
এখানে b একটি ঝুড়ি, nb তার অর্ডারসংখ্যা, N মোট অর্ডার, p̄b ঝুড়ির গড় অনুমান আর ōb বাস্তব হার। সবচেয়ে বড় ফাঁকটিকে বলে MCE (maximum calibration error). এই দুটি নাম জনপ্রিয় হয় Mahdi Pakdaman Naeini, Gregory Cooper আর Milos Hauskrecht-এর ২০১৫ সালের AAAI প্রবন্ধ থেকে।
- ঝুড়ির সারাংশ। ২০টি অর্ডার তিনটি ঝুড়িতে। প্রথম ঝুড়িতে model গড়ে ০.১৫ বলেছে, ঘটেছে ০.২৫; দ্বিতীয়তে ০.৫০ বনাম ০.৪২৮৬; তৃতীয়তে ০.৮৪ বনাম ০.৬০.
- প্রতিটি ফাঁক। পরম পার্থক্য: ০.১০, ০.০৭১৪ আর ০.২৪. চিহ্ন বাদ যায়, তাই কম বলা আর বেশি বলা একে অন্যকে কাটে না।
- ওজন। প্রতিটি ঝুড়ির অর্ডারের অনুপাত: ০.৪০, ০.৩৫, ০.২৫. যেখানে বেশি অর্ডার, সেখানকার ভুল বেশি গুরুত্বপূর্ণ।
- ECE. ওজন × ফাঁক যোগ: ০.০৪০ + ০.০২৫ + ০.০৬০ = ০.১২৫. অর্থ: একটি এলোমেলো অর্ডার নিলে, তার ঝুড়িতে model গড়ে প্রায় ১২.৫ শতাংশ বিন্দু ভুল বলে।
- MCE আর সাধারণ গড়। সবচেয়ে খারাপ ঝুড়ি তৃতীয়টি, ফাঁক ০.২৪: উঁচু ঝুঁকির অর্ডারে model বেশি আশাবাদী। ঝুড়িগুলোর সাধারণ গড় নিলে ০.১৩৭ হতো; ECE তা নয়, ওজনযুক্ত গড়।
ECE-এর তিনটি দুর্বলতা। এক, সংখ্যাটি ঝুড়ির সংখ্যা আর ধরনের ওপর নির্ভর করে; দুটি ECE তুলনায় binning এক হতে হবে। দুই, ছোট নমুনায় এলোমেলোতাই ফাঁক তৈরি করে, তাই নিখুঁত calibrated model-এরও ECE শূন্যের ওপরে। তিন, model খ-এর মতো সবাইকে গড় হার বলা model-এর ECE প্রায় শূন্য। তাই ECE রোগনির্ণয়ের যন্ত্র, model বাছাইয়ের একমাত্র মাপ নয়।
Brier score — ক্রম আর সততা একসঙ্গে
Glenn Brier ১৯৫০ সালে Monthly Weather Review-এ বৃষ্টির পূর্বাভাস যাচাইয়ের জন্য যে মাপ প্রস্তাব করেন, binary ক্ষেত্রে তা হলো:
BS = (1/N) ∑i (pi − yi)²
যেখানে pi অনুমান আর yi ০ বা ১. ০.৮ বলে ফেরত এলে (০.৮ − ১)² = ০.০৪, না এলে (০.৮ − ০)² = ০.৬৪. এটি log loss-এর মতোই proper scoring rule (পর্ব ০২): আসল সম্ভাবনা সৎভাবে বললেই প্রত্যাশিত Brier সবচেয়ে কম। তবে log loss আত্মবিশ্বাসী ভুলকে অসীম পর্যন্ত শাস্তি দিতে পারে, Brier সর্বোচ্চ ১. ঝুড়ি লাগে না বলে binning-এর পছন্দও ঢোকে না। তাই model তুলনায় Brier বা log loss, রোগনির্ণয়ে reliability diagram আর ECE.
৪ · চার model, একই ফেরত-ডেটা — reliability diagram হাতে-কলমে
এই পর্বের ডেটা: বাজারঘরের ৫,০০০টি কাল্পনিক অর্ডার, seed দিয়ে বানানো, কোনো আসল দোকানের নয়। ছয়টি feature (ডেলিভারির দিন, দূরত্ব, courier-এর দেরির সূচক, দাম, পোশাক কি না, প্রথম অর্ডার কি না), লক্ষ্য ফেরত আসবে কি না। দূরত্ব আর দেরির সূচক ইচ্ছা করে ডেলিভারির দিনের সঙ্গে জড়ানো, আর ফেরতের আসল নিয়মে তারা নেই। ভাগ: ২,৫০০ train, ১,০০০ calibration, ১,৫০০ তালাবন্ধ test. চারটি ব্লকই এই module থেকে ডেটা নেয়।
# bazar_returns.py — বাজারঘরের কাল্পনিক অর্ডার আর ফেরত (seed দিয়ে বানানো)
import numpy as np
def make_returns(n=5000, seed=26, rate_shift=0.0):
rng = np.random.default_rng(seed)
days = rng.gamma(3, 1.2, n) # ডেলিভারিতে দিন
dist = 0.8 * days + rng.normal(0, 0.6, n) # hub থেকে দূরত্ব (১০০ km), days-এর সঙ্গে জড়ানো
late = days + rng.normal(0, 0.8, n) # courier-এর দেরির সূচক, এটিও জড়ানো
price = rng.lognormal(0.0, 0.6, n) # দাম, হাজার টাকা
fashion = rng.integers(0, 2, n) # পোশাক বা জুতা?
first = rng.integers(0, 2, n) # গ্রাহকের প্রথম অর্ডার?
z = (-4.0 + rate_shift + 0.45 * days + 0.3 * price + 1.1 * fashion
+ 0.7 * first + 0.6 * fashion * first)
y = (rng.random(n) < 1 / (1 + np.exp(-z))).astype(int)
X = np.column_stack([days, dist, late, price, fashion, first])
return X, y
def split(X, y): # train ২৫০০ · calibration ১০০০ · test ১৫০০
return (X[:2500], y[:2500]), (X[2500:3500], y[2500:3500]), (X[3500:], y[3500:])
def ece(p, y, bins=10): # সমান-প্রস্থে ECE (ব্লক ১-এর একই function)
idx = np.minimum((p * bins).astype(int), bins - 1)
return sum(np.mean(idx == b) * abs(p[idx == b].mean() - y[idx == b].mean())
for b in range(bins) if np.any(idx == b))প্রথম ব্লক চারটি model শেখায়: logistic regression, Gaussian Naive Bayes, ২০০ গাছের random forest, আর RBF SVM. SVM-এর decision function-কে সরাসরি sigmoid দিয়ে ০–১-এ আনা হয়েছে, যা অনেকে না ভেবেই করেন। তারপর দুই রকম ঝুড়িতে reliability diagram, আর নিজে লেখা ECE ও Brier.
import numpy as np
import matplotlib.pyplot as plt
from sklearn.calibration import calibration_curve
from sklearn.ensemble import RandomForestClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.naive_bayes import GaussianNB
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC
from bazar_returns import make_returns, split
X, y = make_returns()
(Xtr, ytr), _, (Xte, yte) = split(X, y)
def ece(p, y, bins=10): # নিজে লেখা ECE, সমান-প্রস্থের ঝুড়ি
idx = np.minimum((p * bins).astype(int), bins - 1)
return sum(np.mean(idx == b) * abs(p[idx == b].mean() - y[idx == b].mean())
for b in range(bins) if np.any(idx == b))
models = {"logistic": LogisticRegression(max_iter=1000), "gaussian NB": GaussianNB(),
"forest": RandomForestClassifier(200, random_state=0)}
probs = {k: m.fit(Xtr, ytr).predict_proba(Xte)[:, 1] for k, m in models.items()}
svm = make_pipeline(StandardScaler(), SVC()).fit(Xtr, ytr)
probs["SVM sigmoid"] = 1 / (1 + np.exp(-svm.decision_function(Xte))) # score-এ সরাসরি sigmoid
fig, axes = plt.subplots(1, 2, figsize=(9, 4.2), sharey=True)
for ax, strat in zip(axes, ["uniform", "quantile"]):
ax.plot([0, 1], [0, 1], "k--", lw=1, label="perfect")
for name, p in probs.items():
frac, mean = calibration_curve(yte, p, n_bins=10, strategy=strat)
ax.plot(mean, frac, "o-", ms=3, label=name)
ax.set(title=f"strategy='{strat}'", xlabel="mean predicted probability")
axes[0].set_ylabel("observed return rate"); axes[0].legend(fontsize=8)
print(f"test orders = {len(yte)}, returned = {yte.mean():.3f}\nmodel Brier ECE")
for name, p in probs.items():
print(f"{name:12s} {np.mean((p - yte) ** 2):.4f} {ece(p, yte):.4f}")আসল আউটপুট (ব্রাউজারের Python), নিচে দুটি reliability diagram:
test orders = 1500, returned = 0.321
model Brier ECE
logistic 0.1668 0.0248
gaussian NB 0.2117 0.1624
forest 0.1768 0.0306
SVM sigmoid 0.1806 0.0872
Logistic regression কর্ণের সবচেয়ে কাছে, ECE ০.০২৫, Brier সবচেয়ে কম ০.১৬৭; ডেটার আসল নিয়মই প্রায় logistic. Naive Bayes সবচেয়ে খারাপ, ECE ০.১৬২: ছবিতে তার রেখা চ্যাপ্টা, ছবি ২৬.১-এর লাল রেখার মতো। একই ডেটায় ঝুড়িগুলো আলাদা করে গুনলে দেখা যায়, ১৬৯টি অর্ডারে সে গড়ে ০.৯৭৮ বলেছে, ফেরত এসেছে ৬৭%; আবার ৭৮৬টি অর্ডারে গড়ে ০.০৪৯ বলেছে, ফেরত এসেছে ১৪.৫%. দুই দিকেই চরম। Forest এই ডেটায় ভালোই (ECE ০.০৩১), ওপরের প্রান্তে একটু নিচে। SVM sigmoid-এর quantile ছবিতে অনেক বিন্দু x ≈ ০.২৭-এ গাদাগাদি, আর তাদের বাস্তব হার ০.১ থেকে ০.২; কারণ পরের অংশে। লক্ষ করুন, forest-এর ECE SVM-এর চেয়ে অনেক ভালো অথচ Brier প্রায় সমান, কারণ Brier-এ ক্রমের দক্ষতাও ঢোকে।
৫ · Model কেন ভুল calibrated হয়
Calibration নির্ভর করে model কোন loss কমিয়েছে, কী ধরে নিয়েছে, আর ডেটা কতটা মিলেছে তার ওপর। Alexandru Niculescu-Mizil আর Rich Caruana ২০০৫ সালের ICML প্রবন্ধে (“Predicting good probabilities with supervised learning”) দশটির মতো algorithm অনেক ডেটাসেটে তুলনা করে চেনা আকারগুলো দেখান। মূল কারণগুলো:
| Model বা কৌশল | সাধারণ বিকৃতি | কারণ |
|---|---|---|
| Naive Bayes | চরমে ঠেলে, অতি-আত্মবিশ্বাসী | জড়ানো feature-কে স্বাধীন ধরে, একই প্রমাণ বারবার গোনে (আমাদের days, dist, late) |
| SVM (score-এ sigmoid) | মাঝে চাপা, S-আকার | Score হলো margin থেকে দূরত্ব, সম্ভাবনা নয়; hinge loss-এর সেরা উত্তর শুধু চিহ্ন (পর্ব ০২) |
| Bagging আর random forest | প্রায়ই প্রান্তে চাপা | অনেক গাছের গড়ে ০ বা ১ পেতে সব গাছকে একমত হতে হয়, যা কম ঘটে |
| AdaBoost আর বেশি গাছের boosting | S-আকার, বা overfit হলে চরম | Margin বাড়ানোর loss; গাছ বাড়লে train-এ নিশ্চয়তা বাড়তে থাকে |
| Logistic regression | প্রায়ই ভালো | Log loss proper; কিন্তু model-এর রূপ ভুল বা penalty কড়া হলে ভাঙে |
| Class weight, oversampling, SMOTE | সব সম্ভাবনা ওপরে সরে | শেখার সময়ের prior আর বাস্তবের prior আলাদা (অংশ ৯-এর সূত্রে সংশোধন) |
| বড় neural network | প্রায়ই অতি-আত্মবিশ্বাসী | Train-এ log loss প্রায় শূন্যে নামানো; Guo ও সহকর্মীরা ২০১৭ |
Naive Bayes-এর হিসাবটি দেখুন। AI-এর ভিত্তি কোর্সের পর্ব ৫১-এ দেখেছেন, Naive Bayes প্রতিটি feature-এর likelihood ratio গুণ করে। ধরুন “ডেলিভারিতে ৮ দিন” একাই ফেরতের odds ৩ গুণ করে। আমাদের ডেটায় দূরত্ব আর দেরির সূচক প্রায় একই তথ্য বহন করে, তাই তারাও প্রত্যেকে প্রায় ৩ গুণ বলে। Naive Bayes তিনটিকে আলাদা প্রমাণ ধরে odds ২৭ গুণ করে, অথচ আসল প্রমাণ ৩ গুণের। ফল: odds-এর log মাপে প্রায় তিন গুণ চরম অনুমান। ক্রম তুলনামূলক কম ক্ষতিগ্রস্ত হয়।
SVM-এর গাদাগাদি। SVM-এর decision function f(x) margin-এর ভাষায় মাপা: যে বিন্দু সঠিক দিকে margin-এর বাইরে, তার |f| ≥ ১, আর soft-margin SVM অনেক বিন্দুকে ঠিক f ≈ ±১-এ বসায় (পর্ব ২৮, Soft margin — hinge loss, C আর dual problem-এ এর কারণ আসবে)। আমাদের run-এ test অর্ডারের score-এর মধ্যমা প্রায় −১.০০, আর σ(−১) = ১/(১ + e) ≈ ০.২৬৯. তাই প্রায় অর্ধেক অর্ডার একই “০.২৭” পায়, যদিও তাদের আসল হার এর চেয়ে কম। Score-এর মাপ C, kernel আর scaling-এর ওপর নির্ভর করে; σ(f)-এর কোনো সম্ভাবনা-অর্থ নেই।
Resampling-এর গোপন খরচ। ফেরত-অর্ডার কম বলে অনেকে oversample বা class_weight="balanced" দেন (পর্ব ৫০, Imbalanced ডেটা — resampling, SMOTE, class weight আর threshold). তখন model শেখে ৫০% ফেরতের জগতে, আর তার সম্ভাবনা সেই জগতের। সংখ্যাটি ব্যবহার করলে আসল হারের ডেটায় নতুন করে calibrate করুন, বা অংশ ৯-এর prior-সংশোধন দিন। আর পর্ব ১৮-এর perfect separation মনে করুন: overfitting সাধারণভাবেই অতি-আত্মবিশ্বাস আনে।
৬ · Brier score ভাঙা — reliability, resolution আর uncertainty
Allan Murphy ১৯৭৩ সালে (Journal of Applied Meteorology) দেখান, ঝুড়ি ধরে হিসাব করলে Brier score তিনটি অর্থপূর্ণ অংশে ভাঙে। এই Brier decomposition বলে model-এর ক্ষতি কোথা থেকে আসছে:
BS ≈ REL − RES + UNC
- REL (reliability) = ∑b (nb/N)(p̄b − ōb)²: ঝুড়ির গড় অনুমান আর বাস্তব হারের ফাঁকের বর্গ। এটিই calibration-এর ভুল; কম হলে ভালো। ECE-র সঙ্গে পার্থক্য শুধু পরম মানের বদলে বর্গ।
- RES (resolution) = ∑b (nb/N)(ōb − ō)²: ঝুড়িগুলোর বাস্তব হার সামগ্রিক হার ō থেকে কত দূরে। Model অর্ডারগুলোকে সত্যিই আলাদা দলে ভাগ করতে পারলে বড়; বেশি হলে ভালো, তাই বিয়োগ।
- UNC (uncertainty) = ō(১ − ō): সমস্যাটি নিজে কতটা অনিশ্চিত। Model এটি বদলাতে পারে না; ō = ০.৫ হলে সর্বোচ্চ ০.২৫.
Model খ সবাইকে ō বলে: একটিই ঝুড়ি, REL = RES = ০, তাই BS = UNC. এজন্য Brier skill score = ১ − BS/UNC মাপে “সবাইকে গড় হার বলা”-র চেয়ে কত ভালো। মূল শিক্ষা: calibration শুধু REL কমায়; RES বাড়াতে লাগে ভালো feature আর model.
“≈” কেন? ঝুড়ির ভেতরে অনুমানগুলো হুবহু এক না হলে একটি ছোট অতিরিক্ত পদ থাকে। এক ঝুড়ির ভেতরে বর্গ ভেঙে লিখলে হুবহু অভেদটি দাঁড়ায় BS = REL − RES + UNC + (WBV − ২·WBC), যেখানে WBV = (1/N)∑(pi − p̄b)² ঝুড়ির ভেতরের অনুমানের ছড়ানো, আর WBC = (1/N)∑(pi − p̄b)(yi − ōb) ঝুড়ির ভেতরে অনুমান আর ফলের সহ-ভেদ। ব্লকটি তিনটি অংশ আর এই অতিরিক্ত পদ হিসাব করে মিলিয়ে দেখায়।
import numpy as np
from sklearn.linear_model import LogisticRegression
from sklearn.naive_bayes import GaussianNB
from bazar_returns import make_returns, split
X, y = make_returns()
(Xtr, ytr), _, (Xte, o) = split(X, y)
def murphy(f, o, bins=10): # Brier-কে তিন ভাগে ভাঙা, সমান-প্রস্থের ঝুড়ি
k = np.minimum((f * bins).astype(int), bins - 1)
N, obar = len(f), o.mean()
rel = res = within = 0.0
for b in np.unique(k):
m = k == b
fk, ok = f[m].mean(), o[m].mean()
rel += m.sum() * (fk - ok) ** 2 / N # reliability: অনুমান বনাম বাস্তব
res += m.sum() * (ok - obar) ** 2 / N # resolution: ঝুড়ির হার গড় থেকে কত দূরে
within += np.sum((f[m] - fk) ** 2 - 2 * (f[m] - fk) * (o[m] - ok)) / N
return rel, res, obar * (1 - obar), within
models = {"logistic": LogisticRegression(max_iter=1000), "gaussian NB": GaussianNB()}
for name, mdl in models.items():
f = mdl.fit(Xtr, ytr).predict_proba(Xte)[:, 1]
rel, res, unc, within = murphy(f, o)
bs = np.mean((f - o) ** 2)
print(f"{name}: Brier = {bs:.4f}, skill vs base rate = {1 - bs / unc:.3f}")
print(f" REL {rel:.4f} - RES {res:.4f} + UNC {unc:.4f} = {rel - res + unc:.4f}")
print(f" + within-bin {within:+.4f} = {rel - res + unc + within:.4f}")
base = np.full(len(o), o.mean()) # সবাইকে একই গড় হার বলা
rel, res, unc, _ = murphy(base, o)
print(f"always {o.mean():.3f}: REL {rel:.4f}, RES {res:.4f}, Brier {np.mean((base - o) ** 2):.4f}")আসল আউটপুট (ব্রাউজারের Python):
logistic: Brier = 0.1668, skill vs base rate = 0.235
REL 0.0013 - RES 0.0518 + UNC 0.2181 = 0.1676
+ within-bin -0.0007 = 0.1668
gaussian NB: Brier = 0.2117, skill vs base rate = 0.029
REL 0.0347 - RES 0.0394 + UNC 0.2181 = 0.2134
+ within-bin -0.0017 = 0.2117
always 0.321: REL 0.0000, RES 0.0000, Brier 0.2181
দুই model-এর UNC একই, ০.৩২১ × ০.৬৭৯ = ০.২১৮১, কারণ এটি ডেটার গুণ। ঝুড়ির ভেতরের পদসহ যোগফল Brier-এর সঙ্গে হুবহু মিলেছে। Naive Bayes-এর REL ০.০৩৪৭, logistic-এর প্রায় ২৭ গুণ: calibration-এর ক্ষতি, যা সারানো যায়। কিন্তু তার RES-ও কম (০.০৩৯৪ বনাম ০.০৫১৮): জড়ানো feature ক্রমকেও কিছুটা নষ্ট করেছে, যা calibration ফেরাতে পারবে না। Skill ০.০২৯ মানে সে “সবাইকে ০.৩২১ বলা”-র চেয়ে মাত্র ৩% ভালো।
৭ · Platt scaling আর isotonic regression — score থেকে সৎ সম্ভাবনা
সারানোর মূল ভাবনা একটাই: model-এর score s রেখে দিন, শুধু তার ওপর একটি একঘেয়ে function g শিখুন যাতে g(s) সৎ সম্ভাবনা হয়। g শেখানো হয় এমন ডেটায় যা model দেখেনি, কারণ train ডেটায় model-এর score নিজেই আশাবাদী। একে বলে calibration set.
Platt scaling — দুটি সংখ্যার sigmoid
John Platt ১৯৯৯ সালে SVM-এর score-কে সম্ভাবনায় আনতে প্রস্তাব করেন (Advances in Large Margin Classifiers বইয়ের অধ্যায়, ২০০০ সালে প্রকাশিত):
p = σ(a · s + b) = 1 / (1 + e−(a·s + b))
a আর b শেখা হয় calibration set-এ log loss কমিয়ে; অর্থাৎ score-কে একমাত্র feature ধরে একটি এক-মাত্রার logistic regression. a score-কে প্রসারিত বা সংকুচিত করে (a < ১ মানে model অতি-আত্মবিশ্বাসী ছিল), b সরায়। ছোট ডেটায় sigmoid খুব খাড়া না হতে Platt লক্ষ্য ১ আর ০-এর বদলে (N+ + ১)/(N+ + ২) আর ১/(N− + ২) নেন; scikit-learn-ও তাই করে।
দুটি সূক্ষ্ম বিষয়। এক, s কোনটি? SVM-এ decision function; যে model নিজেই সম্ভাবনা দেয়, সেখানে log-odds (logit) log(p/(১ − p)) স্বাভাবিক, কারণ sigmoid তার উল্টো। কিন্তু CalibratedClassifierCV decision function না পেলে কাঁচা predict_proba-কেই s নেয় (1.8.0-এর docs আর source). দুই, Platt ধরে নেয় বিকৃতিটি sigmoid-আকারের; SVM বা boosting-এর S-আকারে তা মেলে, অন্য আকারে পুরোটা সারে না।
Isotonic regression — শুধু “একঘেয়ে” শর্ত
Bianca Zadrozny আর Charles Elkan ২০০২ সালে (KDD) প্রস্তাব করেন: g-এর কোনো আকার ধরে নেবেন না, শুধু চান g একঘেয়ে বাড়ন্ত হোক। Calibration set-এ (si, yi) জোড়াগুলোয় এমন একঘেয়ে সিঁড়ি খুঁজুন যার বর্গ-ভুল সবচেয়ে কম। উত্তর দেয় pool adjacent violators (PAV) algorithm (Ayer ও সহকর্মীরা, ১৯৫৫): score অনুযায়ী সাজিয়ে বাঁ থেকে ডানে যান, কোথাও ক্রম ভাঙলে পাশের মানগুলো মিলিয়ে গড় করুন, যতক্ষণ না সব একঘেয়ে হয়। নিচে ৮টি বিন্দুতে পুরো হিসাব, আর একই ৮টিতে Platt:
- শুরু। আটটি calibration অর্ডার, score-এর ক্রমে; প্রতিটির মান তার y. একঘেয়ে মানে বাঁ থেকে ডানে মান কখনো কমবে না, কিন্তু এখানে ১ → ০ লাফ আছে।
- প্রথম মিলন। দ্বিতীয় (১) আর তৃতীয় (০) অর্ডার ক্রম ভেঙেছে, তাই দুটিকে এক দলে মিলিয়ে গড় ½ দেওয়া হলো।
- মিলন ছড়ায়। নতুন দলের ½ চতুর্থ অর্ডারের ০-এর চেয়ে বড়, তাই তিনটি মিলে গড় (১ + ০ + ০)/৩ = ⅓. পরে পঞ্চম (১) আর ষষ্ঠ (০) মিলে ½. এখন পুরো সারি একঘেয়ে: ০, ⅓, ⅓, ⅓, ½, ½, ১, ১.
- ফল চারটি ধাপ। শেষটি ঠিক ১: score ১ বা বেশি হলে isotonic বলবে “ফেরত নিশ্চিত”, মাত্র দুটি অর্ডার দেখে। (scikit-learn ধাপের মাঝে সরলরেখায় interpolate করে।)
- Platt. একই আটটিতে শাস্তিহীন এক-মাত্রার logistic: a = ০.৮৬৬, b = ০.২১৬. সম্ভাবনা ০.১৮ থেকে ০.৮২, মসৃণ।
- শিক্ষা। এই আটটিতে isotonic-এর Brier কম (০.১৪৬ বনাম ০.২০৪), কিন্তু সেটি এলোমেলোতা মুখস্থ করা। ধাপ যত বেশি হতে পারে, ডেটা তত লাগে। scikit-learn-এর docs বলে নমুনা ১,০০০-এর অনেক কম হলে isotonic overfit করে; তখন Platt, আর ডেটা অনেক হলে isotonic.
অনেক শ্রেণি হলে — temperature scaling
Platt আর isotonic দুই শ্রেণির জন্য; অনেক শ্রেণিতে scikit-learn প্রতিটি শ্রেণির one-vs-rest calibrator শেখায়, তারপর যোগফল ১ করে (পর্ব ২৫, Multiclass আর multilabel — OvR, OvO, softmax আর classifier chain). Chuan Guo ও সহকর্মীরা ২০১৭ সালের ICML-এ সরলতর পথ জনপ্রিয় করেন: temperature scaling, অর্থাৎ p = softmax(z/T), সব logit একটি সংখ্যা T দিয়ে ভাগ। T > ১ সম্ভাবনা নরম করে, কিন্তু সবচেয়ে বড় logit বড়ই থাকে, তাই accuracy বদলায় না। scikit-learn 1.8-এ method="temperature" যোগ হয়েছে। Scikit-learn-এর সঙ্গে আসা digits ডেটায় (১০ শ্রেণি) প্রায় শাস্তিহীন logistic regression, আলাদা ভাগে T; ডেস্কটপে সত্যিকারের run (Python 3.14.4, scikit-learn 1.8.0, একটি run):
~/bazarghar-ml$ python temp_scaling.py
scikit-learn 1.8.0
raw accuracy 0.963 log loss 0.428 mean max-prob 0.993
temperature accuracy 0.963 log loss 0.165 mean max-prob 0.940
inverse temperature beta = 0.206, so T = 4.84
Accuracy হুবহু এক (০.৯৬৩), কিন্তু log loss ০.৪২৮ থেকে ০.১৬৫. কাঁচা model গড়ে ৯৯.৩% নিশ্চয়তা দেখাচ্ছিল অথচ ঠিক ছিল ৯৬.৩%; T ≈ ৪.৮-এ ভাগের পর ৯৪.০%. ভেতরে রাখা beta_ = ১/T একটি private attribute, যার নাম বদলাতে পারে।
৮ · হাতে-কলমে — আলাদা calibration ডেটা, CalibratedClassifierCV আর ফাঁদ
তিন ভাগের নিয়ম
Train the model, fit the calibrator, evaluate — on three different sets
- Train
২,৫০০ অর্ডারmodel শেখে - Calibration
১,০০০ অর্ডারশুধু g(s) শেখে - Test
১,৫০০ অর্ডারশেষে একবার মাপা
CalibratedClassifierCV(cv=5).CalibratedClassifierCV(estimator, method=..., cv=5)-এ ডিফল্ট ensemble="auto" এখানে True: প্রতিটি fold-এ চার ভাগে model-এর একটি কপি, বাকি ভাগে তার calibrator; শেষে পাঁচ জোড়ার সম্ভাবনার গড়। ফলে আলাদা calibration ভাগ লাগে না (AI-এর ভিত্তি কোর্সের পর্ব ৬৬-এর cross-validation-এর মতো)। আগে শেখানো model হলে FrozenEstimator-এ মুড়ে দিন; তখন দেওয়া সব ডেটা শুধু calibration-এ যায়, আর ভাগ আলাদা রাখার দায় আপনার। পুরোনো লেখায় (আর AI-এর কোডে) যে cv="prefit" দেখবেন, তা 1.8.0-এ আর নেই; ডেস্কটপে সত্যিকারের run:
~/bazarghar-ml$ python prefit.py
…
sklearn.utils._param_validation.InvalidParameterError: The 'cv' parameter of CalibratedClassifierCV must be an int in the range [2, inf), an object implementing 'split' and 'get_n_splits', an iterable or None. Got 'prefit' instead.
নিচের ব্লক Naive Bayes-কে চারভাবে সারায়: নিজে লেখা Platt (logit score-এর ওপর এক-মাত্রার logistic), নিজে লেখা isotonic (দুটিই ১,০০০টি calibration অর্ডারে), আর CalibratedClassifierCV-এর sigmoid ও isotonic (train আর calibration মিলিয়ে ৩,৫০০টিতে ৫-fold). তারপর ফাঁদটি: forest-এর calibrator তার নিজের train অর্ডারেই শেখানো।
import numpy as np
from sklearn.calibration import CalibratedClassifierCV
from sklearn.ensemble import RandomForestClassifier
from sklearn.isotonic import IsotonicRegression
from sklearn.linear_model import LogisticRegression
from sklearn.naive_bayes import GaussianNB
from bazar_returns import make_returns, split, ece
X, y = make_returns()
(Xtr, ytr), (Xc, yc), (Xte, yte) = split(X, y)
nb = GaussianNB().fit(Xtr, ytr) # শুধু train অংশে শেখা
logit = lambda p: np.log(np.clip(p, 1e-12, 1) / np.clip(1 - p, 1e-12, 1))
s_c, s_te = (logit(nb.predict_proba(A)[:, 1]) for A in (Xc, Xte))
platt = LogisticRegression(C=1e10).fit(s_c[:, None], yc) # ১-মাত্রার logistic = Platt
a, b = platt.coef_[0, 0], platt.intercept_[0]
iso = IsotonicRegression(out_of_bounds="clip").fit(s_c, yc)
res = {"raw NB": 1 / (1 + np.exp(-s_te)),
"Platt (own)": platt.predict_proba(s_te[:, None])[:, 1],
"isotonic (own)": iso.predict(s_te)}
for m in ("sigmoid", "isotonic"): # train + calibration একসঙ্গে, ৫-fold
cc = CalibratedClassifierCV(GaussianNB(), method=m, cv=5)
res[f"CCV {m}"] = cc.fit(np.r_[Xtr, Xc], np.r_[ytr, yc]).predict_proba(Xte)[:, 1]
print(f"Platt: p = sigmoid({a:.3f} * score {b:+.3f}); isotonic knots = {len(iso.X_thresholds_)}")
print("on test Brier ECE")
for k, p in res.items():
print(f"{k:16s} {np.mean((p - yte) ** 2):.4f} {ece(p, yte):.4f}")
rf = RandomForestClassifier(200, random_state=0).fit(Xtr, ytr) # ফাঁদ: train-এর ওপরেই calibration
for name, (A, t) in {"on train (leak)": (Xtr, ytr), "on held-out": (Xc, yc)}.items():
cal = IsotonicRegression(out_of_bounds="clip").fit(rf.predict_proba(A)[:, 1], t)
p = cal.predict(rf.predict_proba(Xte)[:, 1])
print(f"forest isotonic {name:16s} Brier {np.mean((p - yte) ** 2):.4f} ECE {ece(p, yte):.4f}")
p = rf.predict_proba(Xte)[:, 1]
print(f"forest raw Brier {np.mean((p - yte) ** 2):.4f} ECE {ece(p, yte):.4f}")আসল আউটপুট (ব্রাউজারের Python):
Platt: p = sigmoid(0.356 * score -0.395); isotonic knots = 30
on test Brier ECE
raw NB 0.2117 0.1624
Platt (own) 0.1880 0.0870
isotonic (own) 0.1787 0.0453
CCV sigmoid 0.1872 0.1005
CCV isotonic 0.1785 0.0429
forest isotonic on train (leak) Brier 0.2332 ECE 0.2221
forest isotonic on held-out Brier 0.1768 ECE 0.0325
forest raw Brier 0.1768 ECE 0.0306
Platt-এর a = ০.৩৫৬: Naive Bayes-এর log-odds প্রায় তিন গুণ চরম ছিল, তাই Platt তাকে প্রায় এক-তৃতীয়াংশে নামিয়েছে, অংশ ৫-এর “একই প্রমাণ তিনবার গোনা”-র সঙ্গে চমৎকার মিল। b = −০.৩৯৫ একটু নিচে সরায়। Platt ECE ০.১৬২ থেকে ০.০৮৭-এ নামিয়েছে, পুরোটা নয়; isotonic ০.০৪৫-এ, Brier-ও কম। Naive Bayes-এর বিকৃতি শুধু sigmoid-আকারের নয়, আর ১,০০০টি অর্ডার isotonic-এর ৩০টি গিঁটের জন্য যথেষ্ট। CCV sigmoid নিজের Platt-এর চেয়েও খারাপ (০.১০০৫): GaussianNB-এর decision function নেই, তাই sigmoid বসেছে কাঁচা সম্ভাবনায়, logit-এ নয়, আর ০.৯৯৯ বনাম ০.৯৫-এর পার্থক্য প্রায় হারিয়ে যায়। CCV isotonic সবচেয়ে ভালো (০.০৪৩)।
ফাঁদ। Forest নিজের train অর্ডারে প্রায় নিখুঁত, কারণ প্রতিটি গাছ সেই সারিগুলো দেখেছে; তার train-এর score-এ ফেরত-অর্ডার প্রায় সবই ওপরে, না-ফেরতগুলো নিচে। Isotonic তাই শেখে “মাঝারি score মানেই প্রায় নিশ্চিত ফেরত”, যা নতুন অর্ডারে মিথ্যা: test-এ ECE ০.০৩১ থেকে লাফিয়ে ০.২২২, কাঁচা model-এর চেয়েও সাত গুণ খারাপ। আলাদা ভাগে শেখালে ECE ০.০৩২৫, কাঁচার প্রায় সমান: এই forest আগেই মোটামুটি calibrated ছিল। আগে মাপুন, তারপর সারান। একই ফাঁদ data leakage-এর আরেক রূপ (AI-এর ভিত্তি কোর্সের পর্ব ৫৬)।
৯ · Calibration কেন দরকার — খরচের সিদ্ধান্ত আর prior বদল
পর্ব ০২-এর অংশ ৭ আর AI-এর ভিত্তি কোর্সের পর্ব ৫৪-এ দেখেছেন, সিদ্ধান্ত নিতে হয় expected cost দেখে। বাজারঘর ঝুঁকির অর্ডারে ডেলিভারির আগে ফোন করে অগ্রিম চার্জ চায়। কাল্পনিক সংখ্যায়: প্রতিটি ফোনে খরচ ৬০ টাকা, আর ফোন করলে ফেরত আটকায়; ফোন না করলে ফেরত এলে ৩০০ টাকা ক্ষতি (দুই দিকের courier আর আবার প্যাক)। ফেরতের সম্ভাবনা p হলে:
ফোন করলে খরচ ৬০ · না করলে প্রত্যাশিত খরচ ৩০০ · p ⇒ ফোন করুন যদি p > ৬০/৩০০ = ০.২
সাধারণ রূপে, চারটি ঘরের cost matrix-এ threshold t* = (cFP − cTN) / [(cFP − cTN) + (cFN − cTP)]; এখানে cFP = cTP = ৬০, cFN = ৩০০, cTN = ০, তাই ৬০/(৬০ + ২৪০) = ০.২. Charles Elkan ২০০১ সালের IJCAI প্রবন্ধে (“The foundations of cost-sensitive learning”) এটি গুছিয়ে লেখেন। লুকানো শর্ত: p সৎ হতে হবে।
Prior বদলালে — odds দিয়ে সংশোধন
ঈদের মৌসুমে পোশাকের অর্ডার বাড়ে, আর ফেরতের সামগ্রিক হার π = ০.৩১ থেকে ধরা যাক π′ = ০.৫০ হয়। যদি ফেরত-অর্ডার আর না-ফেরত অর্ডারগুলো দেখতে আগের মতোই থাকে, অর্থাৎ P(x | y) না বদলায় (একে বলে label shift বা prior shift), তবে Bayes-এর সূত্র থেকে নতুন সম্ভাবনা আসে model আবার না শিখিয়েই:
p′ = p·(π′/π) / [ p·(π′/π) + (1 − p)·(1 − π′)/(1 − π) ]
অর্থাৎ odds′ = odds × [π′/(১ − π′)] / [π/(১ − π)]. Marco Saerens ও সহকর্মীরা ২০০২ সালে (Neural Computation) এটি আর π′ অজানা হলে EM দিয়ে অনুমানের পদ্ধতি দেন। সূত্রটি ধরে নেয় p আগে থেকেই calibrated. নিচের ব্লক দুটি কাজই দেখায়।
import numpy as np
from sklearn.calibration import CalibratedClassifierCV
from sklearn.linear_model import LogisticRegression
from sklearn.naive_bayes import GaussianNB
from bazar_returns import make_returns, split, ece
X, y = make_returns()
(Xtr, ytr), (Xc, yc), (Xte, yte) = split(X, y)
CALL, RETURN = 60, 300 # টাকা: ফোন করে নিশ্চিত করা, আর ফেরতের ক্ষতি
t = CALL / RETURN # p > 0.2 হলে ফোন করাই সস্তা
raw = GaussianNB().fit(Xtr, ytr).predict_proba(Xte)[:, 1]
cal = CalibratedClassifierCV(GaussianNB(), method="isotonic", cv=5).fit(
np.r_[Xtr, Xc], np.r_[ytr, yc]).predict_proba(Xte)[:, 1]
for name, p in {"raw NB": raw, "calibrated NB": cal}.items():
act = p > t
real = np.where(act, CALL, RETURN * yte).sum() # আসলে কত খরচ হলো
plan = np.where(act, CALL, RETURN * p).sum() # model নিজে যা ভেবেছিল
print(f"{name:14s} calls {act.sum():4d} planned {plan:7.0f} real {real:7.0f} taka")
print(f"call nobody: {RETURN * yte.sum()} taka, call everyone: {CALL * len(yte)} taka")
# ঈদের মৌসুম: ফেরতের হার বাড়ে, কিন্তু ফেরত-অর্ডারগুলোর চেহারা একই (label shift)
Xp, yp = make_returns(n=20000, seed=99)
rng = np.random.default_rng(1)
pos, neg = rng.permutation(np.flatnonzero(yp == 1)), rng.permutation(np.flatnonzero(yp == 0))
idx = np.r_[pos[:750], neg[:750]] # নতুন হার 0.50
lr = LogisticRegression(max_iter=1000).fit(Xtr, ytr)
p_old = lr.predict_proba(Xp[idx])[:, 1]
pi_old, pi_new = ytr.mean(), 0.50
r1, r0 = pi_new / pi_old, (1 - pi_new) / (1 - pi_old)
p_new = p_old * r1 / (p_old * r1 + (1 - p_old) * r0) # odds-কে prior-এর অনুপাতে গুণ
print(f"train rate {pi_old:.3f} -> Eid rate {yp[idx].mean():.3f}")
for name, p in {"as trained": p_old, "prior-adjusted": p_new}.items():
print(f"{name:15s} mean p {p.mean():.3f} Brier {np.mean((p - yp[idx]) ** 2):.4f}"
f" ECE {ece(p, yp[idx]):.4f}")আসল আউটপুট (ব্রাউজারের Python):
raw NB calls 481 planned 49979 real 91260 taka
calibrated NB calls 864 planned 71350 real 71940 taka
call nobody: 144600 taka, call everyone: 90000 taka
train rate 0.309 -> Eid rate 0.500
as trained mean p 0.356 Brier 0.2023 ECE 0.1444
prior-adjusted mean p 0.499 Brier 0.1777 ECE 0.0242
খরচ। কাঁচা Naive Bayes মাত্র ৪৮১টিতে ফোন করতে বলে, কারণ বহু অর্ডারকে সে ০.০৫-এর মতো বলেছিল, যাদের আসলে প্রায় ১৪% ফেরত আসে। তার হিসাবে খরচ প্রায় ৫০ হাজার টাকা; আসলে ৯১,২৬০, “সবাইকে ফোন” (৯০,০০০)-এর চেয়েও খারাপ! Calibrated সংস্করণ ৮৬৪টিতে ফোন করে, খরচ ৭১,৯৪০ টাকা, প্রায় ১৯ হাজার কম, আর পরিকল্পনা (৭১,৩৫০) আসলের প্রায় সমান। ক্রম প্রায় একই; শুধু সংখ্যাগুলো সৎ হয়েছে, তাই বাজেটও বিশ্বাসযোগ্য।
ঈদ। একটি বড় কাল্পনিক অর্ডার-ভান্ডার থেকে ৭৫০টি ফেরত আর ৭৫০টি না-ফেরত তোলা হয়েছে: শ্রেণির চেহারা একই, শুধু হার ০.৫০. পুরোনো model গড়ে ০.৩৫৬ বলে, ECE ০.১৪৪; সংশোধনের পর ০.৪৯৯ আর ECE ০.০২৪, model আবার না শিখিয়েই। বাস্তবে π′ আগে জানা থাকে না (গত ঈদের হার বা Saerens-এর EM), আর চেহারাও বদলালে এই সূত্র যথেষ্ট নয়: পর্ব ৫৯ (Distribution shift — covariate, label আর concept shift ধরা ও সামলানো)।
আরও গভীরে: Zadrozny আর Elkan ২০০১ সালে (ICML) histogram binning দেন, যা প্রতিটি ঝুড়ির বাস্তব হারকেই নতুন সম্ভাবনা বানায়; Naeini ও সহকর্মীদের BBQ (২০১৫) অনেক binning-এর Bayesian গড় নেয়। Meelis Kull, Telmo Silva Filho আর Peter Flach ২০১৭ সালে beta calibration প্রস্তাব করেন, যা Platt-এর চেয়ে নমনীয় কিন্তু isotonic-এর চেয়ে কম ডেটা চায়, আর identity function-কেও ধরতে পারে। Brier-এর হুবহু ভাঙনে ঝুড়ির ভেতরের পদ নিয়ে David Stephenson ও সহকর্মীরা ২০০৮ সালে Weather and Forecasting-এ বিস্তারিত লেখেন। আর calibration-এর একটি শক্ত রূপ, conformal prediction, পরিসর দিয়ে নিশ্চয়তার গ্যারান্টি দেয় (পর্ব ৫৮)।
পরীক্ষা ও ইন্টারভিউতে:
- Calibration আর discrimination-এর পার্থক্য? Calibration: “০.৭ বলা অর্ডারের ৭০% ঘটে”; discrimination: ঘটা আর না-ঘটাকে আলাদা ক্রমে রাখা (AUC). একঘেয়ে calibration AUC বদলায় না।
- ECE হাতে কীভাবে? প্রতিটি ঝুড়িতে |বাস্তব হার − গড় অনুমান|, ঝুড়ির অনুপাত nb/N দিয়ে ওজন করে যোগ।
- Brier-এর Murphy ভাঙন? BS = REL − RES + UNC; UNC = ō(১ − ō), সবাইকে গড় হার বললে REL = RES = ০.
- Platt আর isotonic কখন? Platt: দুটি parameter, sigmoid আকার ধরে, কম ডেটায় নিরাপদ। Isotonic: যেকোনো একঘেয়ে আকার, PAV দিয়ে, কিন্তু ডেটা কম হলে overfit.
- Prior বদলালে কী করবেন? P(x | y) একই থাকলে odds × [π′/(১ − π′)]/[π/(১ − π)].
১০ · AI-এর যুগে — সম্ভাবনার কোড আর দাবি যাচাই
AI assistant-এর calibration কোড চলে আর সুন্দর সংখ্যা ছাপে। বিপদ: ভুল জায়গায় শেখানো calibrator-ও চমৎকার ECE দেখায়, যদি একই ডেটায় মাপা হয়। পরিচিত ভুলগুলো:
| AI প্রায়ই যা করে | কেন ভুল | কীভাবে ধরবেন |
|---|---|---|
CalibratedClassifierCV(model, cv="prefit") লেখে | 1.8.0-এ InvalidParameterError; পুরোনো API | নিজের version-এর docs; FrozenEstimator |
| Train ডেটাতেই calibrator শেখায়, বা সেখানেই ECE মাপে | Leakage; অংশ ৮-এ test ECE ০.০৩ থেকে ০.২২ | তিন ভাগ বা cv=5; test-এ reliability diagram |
SMOTE বা class_weight-এর পর predict_proba-কে আসল ঝুঁকি বলে | Prior বদলে গেছে; সব সম্ভাবনা ফোলা | আসল হারের ডেটায় calibration, বা prior-সংশোধন |
| ২০০টি নমুনায় isotonic বসায় | ধাপ মুখস্থ করে, প্রান্তে ০ বা ১ | কম ডেটায় Platt; কয়েকটি seed-এ তুলনা |
| “Calibration-এর পর AUC বেড়েছে” দাবি করে | একঘেয়ে রূপান্তর ক্রম বদলায় না (isotonic-এর tie-তে সামান্য বদল) | AUC আগে-পরে পাশাপাশি; উন্নতি দেখা উচিত Brier আর ECE-তে |
AI-কে শুধু কোড নয়, ভাগ, তুলনা আর যাচাই চাইতে বলুন:
AI-এর দেওয়া calibration হাতে পেলে — যাচাইয়ের চেকলিস্ট
ভাবনার প্রশ্ন
প্রতিটি প্রশ্ন নিয়ে নিজে কিছুক্ষণ ভাবুন — তারপর “→ উত্তর” চাপুন।
প্র ০১Calibration-এর ধারণা এসেছে আবহাওয়ার পূর্বাভাস থেকে। আবহাওয়াবিদরা এতে এত এগিয়ে কেন, আর ML তাঁদের কাছ থেকে কী শিখতে পারে?
আবহাওয়ার পূর্বাভাস সম্ভবত প্রথম ক্ষেত্র, যেখানে সম্ভাবনার সংখ্যা প্রতিদিন জনসমক্ষে বলা হয় আর পরদিনই যাচাই হয়। Glenn Brier ১৯৫০ সালে তাঁর score প্রস্তাব করেন ঠিক এই কারণে: পূর্বাভাসদাতারা যেন “বৃষ্টি হতে পারে” ধরনের অস্পষ্ট কথা না বলে, সংখ্যা দেন, আর সেই সংখ্যার জন্য দায় নেন। Allan Murphy ১৯৭০-এর দশকে Brier-কে reliability, resolution আর uncertainty-তে ভাঙেন, আর Murphy ও Robert Winkler-এর মতো গবেষকরা যুক্তরাষ্ট্রের জাতীয় আবহাওয়া সংস্থার বৃষ্টির সম্ভাবনার পূর্বাভাস বিশ্লেষণ করে দেখান যে সেগুলো মোটামুটি ভালো calibrated ছিল। Morris DeGroot আর Stephen Fienberg ১৯৮৩ সালে পূর্বাভাসদাতাদের তুলনার তাত্ত্বিক কাঠামো দেন, যেখানে calibration আর “refinement” (প্রায় resolution-এর মতো) আলাদা গুণ।
এই সাফল্যের পেছনে কয়েকটি অভ্যাস আছে, যা ML প্রায়ই ভোলে। প্রথম, অবিরাম প্রতিক্রিয়া: প্রতিটি পূর্বাভাস পরদিন যাচাই হয়, আর হাজার হাজার দিনের reliability diagram আঁকা যায়। দ্বিতীয়, যাচাই সবসময় ভবিষ্যতের ডেটায়, train-এর ডেটায় নয়। তৃতীয়, model-এর কাঁচা আউটপুট সরাসরি প্রকাশ হয় না; সংখ্যাভিত্তিক model-এর আউটপুটকে পরিসংখ্যান দিয়ে সংশোধন করা হয় (model output statistics নামে এই ধারা ১৯৭০-এর দশক থেকে চলে আসছে), যা আসলে calibration-এরই একটি রূপ। চতুর্থ, মৌসুমের পরিবর্তন মাথায় রাখা: বর্ষার “৭০%” আর শীতের “৭০%” আলাদা ঝুড়িতে যাচাই করা।
বাজারঘরের মতো একটি দোকানের জন্য শিক্ষা সরাসরি: ফেরতের সম্ভাবনা প্রতি সপ্তাহে নতুন ডেটায় reliability diagram দিয়ে দেখা, ঈদ বা বর্ষার মতো মৌসুম আলাদা করে দেখা, আর model-এর পরে একটি হালকা calibration স্তর রাখা যা নিয়মিত হালনাগাদ হয়।
মূল উপলব্ধি: calibration একবারের কাজ নয়, নিয়মিত যাচাইয়ের অভ্যাস; আবহাওয়াবিদরা ভালো কারণ তাঁরা প্রতিদিন নিজেদের সংখ্যার হিসাব দেন।
প্র ০২আধুনিক neural network আর বড় language model কি calibrated? “৯৯% নিশ্চিত” বলা AI-কে কতটা বিশ্বাস করবেন?
Chuan Guo, Geoff Pleiss, Yu Sun আর Kilian Weinberger ২০১৭ সালের ICML প্রবন্ধে (“On calibration of modern neural networks”) দেখান যে ১৯৯০-এর দশকের ছোট neural network তুলনামূলক ভালো calibrated ছিল, কিন্তু গভীর ও চওড়া আধুনিক network (যেমন ResNet), batch normalization আর কম weight decay নিয়ে, accuracy বাড়লেও প্রায়ই অতি-আত্মবিশ্বাসী হয়ে পড়ে। তাঁদের ব্যাখ্যা: train-এ log loss কমাতে কমাতে network নিশ্চয়তা বাড়াতে থাকে, যদিও ভুলের হার আর কমে না। প্রতিকার হিসেবে তাঁরা temperature scaling-কে সবচেয়ে সরল আর কার্যকর পেয়েছিলেন, যা অংশ ৭-এ দেখেছেন।
পরের গবেষণা ছবিটি জটিল করে। Matthias Minderer ও সহকর্মীরা ২০২১ সালে (NeurIPS) দেখান, কিছু নতুন architecture (যেমন vision transformer) আগের convolutional network-এর চেয়ে ভালো calibrated হতে পারে, আর calibration-এর ধারা শুধু আকার বা accuracy দিয়ে ব্যাখ্যা হয় না। Yaniv Ovadia ও সহকর্মীরা ২০১৯ সালে দেখান, ডেটার ধরন বদলালে (distribution shift) প্রায় সব পদ্ধতির calibration খারাপ হয়, temperature scaling-সহ।
Language model-এর ক্ষেত্রে OpenAI-এর ২০২৩ সালের GPT-4 technical report-এ একটি চিত্রে দেখানো হয়েছিল, একটি MCQ benchmark-এ pre-trained model-এর উত্তরের সম্ভাবনা বেশ ভালো calibrated, কিন্তু মানুষের পছন্দ দিয়ে পরে প্রশিক্ষণের (RLHF) পর calibration কমে যায়। এটি একটি নির্দিষ্ট পরীক্ষার ফল, সাধারণ সূত্র নয়। আর chat-এ model যখন লিখে বলে “আমি ৯৯% নিশ্চিত”, সেই লেখা সংখ্যাটি token-এর সম্ভাবনা নয়; সেটি একটি বাক্য, যার calibration আলাদা করে মাপা না হলে কিছুই জানা যায় না।
ব্যবহারিক নিয়ম: যে AI-এর সম্ভাবনা আপনার সিদ্ধান্তে ঢুকবে, তার reliability diagram নিজের ডেটায়, নিজের কাজে আঁকুন। প্রকাশিত benchmark-এর calibration আপনার ডেটায় টিকবে, তা ধরে নেবেন না।
মূল উপলব্ধি: accuracy আর calibration আলাদা গুণ, আর বড় model-এর নিশ্চয়তার ভাষা বিশ্বাসের যোগ্য কি না, তা শুধু নিজের ডেটায় মেপেই জানা যায়।
প্র ০৩প্রতিটি দলের জন্য আলাদাভাবে calibrated একটি ঝুঁকির score কি ন্যায্য? COMPAS বিতর্ক থেকে কী শেখার আছে?
২০১৬ সালে ProPublica যুক্তরাষ্ট্রের আদালতে ব্যবহৃত COMPAS নামের একটি পুনরায় অপরাধের ঝুঁকির score বিশ্লেষণ করে লেখে, যারা পরে আর অপরাধ করেনি তাদের মধ্যে কৃষ্ণাঙ্গদের “উচ্চ ঝুঁকি” বলার হার শ্বেতাঙ্গদের প্রায় দ্বিগুণ। নির্মাতা প্রতিষ্ঠান (তখন Northpointe) জবাবে বলে, score দুই দলেই calibrated: একই score পাওয়া মানুষদের মধ্যে পুনরায় অপরাধের হার দুই দলে প্রায় এক। দুই পক্ষের হিসাবই নিজের সংজ্ঞায় মোটামুটি ঠিক ছিল বলে পরে অনেক বিশ্লেষক মত দেন।
একই বছর Jon Kleinberg, Sendhil Mullainathan আর Manish Raghavan, আর আলাদাভাবে Alexandra Chouldechova দেখান যে এটি কাকতাল নয়। দুই দলের আসল হার (base rate) আলাদা হলে, আর model নিখুঁত না হলে, “প্রতিটি দলে calibration” আর “দুই দলে সমান false positive ও false negative হার” একসঙ্গে পাওয়া গণিতগতভাবে অসম্ভব। অর্থাৎ ন্যায্যতার কোন সংজ্ঞা বেছে নেবেন, তা একটি মূল্যবোধের সিদ্ধান্ত, শুধু প্রযুক্তিগত নয়।
বাজারঘরের ক্ষেত্রে ভাবুন: ফেরতের ঝুঁকির score যদি জেলাভেদে calibrated হয়, তবু যে জেলায় ফেরতের হার বেশি, সেখানকার সৎ গ্রাহকরা বেশি ফোন পাবেন আর বেশি অগ্রিম চার্জ দেবেন। Calibration নিশ্চিত করে সংখ্যাটি সৎ; কিন্তু সেই সংখ্যা দিয়ে কার ওপর কতটা বোঝা চাপাবেন, তা আলাদা প্রশ্ন। আর একটি সূক্ষ্মতা: সামগ্রিকভাবে calibrated model কোনো একটি দলে খারাপ calibrated হতে পারে, তাই দলভিত্তিক reliability diagram আলাদা করে আঁকা দরকার। পর্ব ৬০ (ML-এ ন্যায্যতা — pre-, in- আর post-processing প্রতিকার) এই trade-off নিয়ে বিস্তারিত আলোচনা করবে।
মূল উপলব্ধি: দলভিত্তিক calibration একটি ন্যায্যতার মাপ, কিন্তু একমাত্র নয়; base rate আলাদা হলে সব মাপ একসঙ্গে মেলে না, তাই কোনটি বেছে নিচ্ছেন তা প্রকাশ্যে বলা জরুরি।
প্র ০৪ECE কম মানেই কি ভালো model? ECE-র সমালোচনা কী, আর তার বদলে কী দেখবেন?
না। প্রথম সমস্যা অংশ ১-এর model খ: সবাইকে গড় হার বললে ECE প্রায় শূন্য, অথচ model অকেজো। ECE শুধু reliability দেখে, resolution দেখে না। তাই ECE কখনো একা model বাছাইয়ের মাপ হওয়া উচিত নয়; সঙ্গে Brier বা log loss থাকতে হবে, যারা দুটি গুণই পুরস্কৃত করে।
দ্বিতীয় সমস্যা binning. Jeremy Nixon ও সহকর্মীরা ২০১৯ সালে (“Measuring calibration in deep learning”) দেখান, ঝুড়ির সংখ্যা, সমান-প্রস্থ না সমান-সংখ্যা, আর শুধু সবচেয়ে বড় শ্রেণি দেখা হবে না সব শ্রেণি, এই পছন্দগুলো বদলালে model-দের ক্রম পর্যন্ত বদলে যেতে পারে। তাঁরা adaptive (সমান-সংখ্যা) ঝুড়ি আর শ্রেণিভিত্তিক মাপের পক্ষে যুক্তি দেন। Ananya Kumar, Percy Liang আর Tengyu Ma ২০১৯ সালে (NeurIPS) দেখান, binning-ভিত্তিক মাপ calibration-এর ভুল কম করেও দেখাতে পারে, আর ছোট নমুনায় ECE-র অনুমান পক্ষপাতী হয়; তাঁরা পক্ষপাত-সংশোধিত অনুমানের কথা বলেন।
তৃতীয়, ECE একটি গড়, তাই সবচেয়ে গুরুত্বপূর্ণ অঞ্চলের ভুল লুকিয়ে ফেলতে পারে। বাজারঘরের সিদ্ধান্ত হয় p ≈ ০.২-এর কাছে; সেখানে ভুল হলে খরচ বাড়ে, অথচ ০.৯-এর ঝুড়ির ভুল সিদ্ধান্ত বদলায় না। তাই সিদ্ধান্তের আশপাশের ঝুড়িগুলো আলাদা করে দেখা, বা সরাসরি প্রত্যাশিত খরচের পার্থক্য মাপা (অংশ ৯-এর মতো) অনেক বেশি অর্থবহ।
ব্যবহারিক তালিকা: reliability diagram দুই strategy-তে, ঝুড়ির গণনাসহ; ECE-র পাশে binning-এর বিবরণ, আর সম্ভব হলে bootstrap দিয়ে interval (পর্ব ২১); Brier বা log loss; আর কাজের মাপ, যেমন টাকায় খরচ।
মূল উপলব্ধি: ECE একটি রোগনির্ণয়ের থার্মোমিটার, রায় নয়; model বাছাই হয় proper scoring rule আর কাজের খরচ দিয়ে।
প্র ০৫বাজারঘর নতুন একটি শহরে ডেলিভারি শুরু করল। পুরোনো ডেটায় calibrated model কি সেখানেও calibrated থাকবে?
সম্ভবত না, আর কতটা ভাঙবে তা নির্ভর করে কী বদলেছে তার ওপর। Calibration একটি নির্দিষ্ট বণ্টনের গুণ: “০.৭ বলা অর্ডারের ৭০% ফেরত” কথাটি সেই অর্ডারগুলোর জন্য, যাদের ওপর মাপা হয়েছে। নতুন শহরে তিন ধরনের পরিবর্তন হতে পারে। শুধু ফেরতের সামগ্রিক হার বদলালে, আর ফেরত-অর্ডারগুলোর চেহারা একই থাকলে (label shift), অংশ ৯-এর odds-সংশোধনই যথেষ্ট; শুধু নতুন হারটি জানতে হবে। Marco Saerens, Patrice Latinne আর Christine Decaestecker ২০০২ সালে দেখান, নতুন শহরের label ছাড়া অনুমানগুলো থেকেই EM দিয়ে নতুন হার অনুমান করা যায়, যদি model calibrated থাকে।
যদি অর্ডারের চেহারা বদলায় (covariate shift), যেমন নতুন শহরে ডেলিভারির দিন বেশি বা দাম কম, তবে model এমন অঞ্চলে অনুমান করছে যেখানে সে কম শিখেছে। Yaniv Ovadia ও সহকর্মীদের ২০১৯ সালের বড় তুলনায় দেখা যায়, shift বাড়লে প্রায় সব পদ্ধতির calibration খারাপ হয়, আর পুরোনো ডেটায় শেখানো temperature বা Platt নতুন ডেটায় পুরোপুরি টেকে না। সবচেয়ে কঠিন হলো concept shift: একই ধরনের অর্ডারে ফেরতের আসল সম্ভাবনাই বদলে গেছে, যেমন নতুন শহরে একটি courier কোম্পানির সেবা খারাপ।
ব্যবহারিক পরিকল্পনা: প্রথম কয়েক সপ্তাহ model-এর সংখ্যাকে আংশিক অবিশ্বাস করুন আর threshold একটু সাবধানী রাখুন; প্রতি সপ্তাহে label আসামাত্র নতুন শহরের reliability diagram আলাদা করে আঁকুন; কয়েকশো label জমলে নতুন শহরের ডেটায় শুধু calibrator (Platt, কারণ ডেটা কম) নতুন করে শেখান, model নয়; আর বড় পার্থক্য দেখা গেলে পুরো model আবার শেখান। এই ধারণাগুলো পর্ব ৫৯ (distribution shift) আর পর্ব ৬৯ (ML system-এর test আর নজরদারি)-এ বিস্তারিত আসবে।
মূল উপলব্ধি: calibration ডেটার গুণ, model-এর চিরস্থায়ী গুণ নয়; নতুন পরিবেশে আবার মাপুন, আর সস্তা calibration স্তরটি আগে হালনাগাদ করুন।
অনুশীলন
হিসাবগুলো খাতায় করুন, তারপর উত্তর মেলান। চাইলে অংশ ৪, ৬ আর ৮-এর ব্লক বদলে যাচাই করুন।
-
পূর্ণ numerical: আটটি অর্ডারের অনুমান আর ফল: (০.১, ০), (০.২, ০), (০.৩, ১), (০.২, ০), (০.৭, ১), (০.৯, ১), (০.৮, ০), (০.৮, ১). দুটি ঝুড়ি: [০, ০.৫) আর [০.৫, ১]. (ক) ECE (খ) Brier score (গ) REL, RES আর UNC বের করুন, আর ঝুড়ির ভেতরের পদ দিয়ে যোগফল মিলিয়ে দেখান।
ঝুড়ি: নিচের ঝুড়িতে প্রথম চারটি, গড় অনুমান (০.১ + ০.২ + ০.৩ + ০.২)/৪ = ০.২০, বাস্তব হার ১/৪ = ০.২৫. ওপরের ঝুড়িতে শেষ চারটি, গড় ০.৮০, হার ৩/৪ = ০.৭৫.
(ক) ECE = ০.৫ × |০.২৫ − ০.২০| + ০.৫ × |০.৭৫ − ০.৮০| = ০.০২৫ + ০.০২৫ = ০.০৫.
(খ) বর্গ-ভুল: ০.০১, ০.০৪, ০.৪৯, ০.০৪, ০.০৯, ০.০১, ০.৬৪, ০.০৪; যোগ ১.৩৬, Brier = ১.৩৬/৮ = ০.১৭.
(গ) ō = ০.৫, UNC = ০.২৫. REL = ০.৫ × ০.০৫² × ২ = ০.০০২৫. RES = ০.৫ × ০.২৫² × ২ = ০.০৬২৫. REL − RES + UNC = ০.১৯. ঝুড়ির ভেতরে: WBV = (০.০১ × ৪)/৮ = ০.০০৫; WBC = [(−০.১)(−০.২৫) + (০.১)(০.৭৫) + (−০.১)(০.২৫) + (০.১)(০.২৫)]/৮ = ০.১/৮ = ০.০১২৫. WBV − ২·WBC = −০.০২০, মোট ০.১৯ − ০.০২ = ০.১৭, হুবহু Brier (অংশ ৬-এর
murphy-তেbins=2দিলেও একই)। -
সমালোচনা ও নকশা: একটি AI assistant এই পরিকল্পনা দিয়েছে: “ফেরত-অর্ডার কম, তাই gradient boosting-এ class weight দিয়ে দুই শ্রেণি সমান করেছি। তারপর
CalibratedClassifierCV(model, cv="prefit", method="isotonic")একই train ডেটায় fit করেছি, train-এ ECE ০.০০৪. মোট ২৫০টি অর্ডার আলাদা রাখা আছে, কিন্তু সেগুলো লাগেনি। এখনpredict_proba-র যোগফল দিয়ে মাসিক ফেরতের বাজেট বানাব।” কী কী সমস্যা, আর সঠিক নকশা কী?সমস্যা: (১)
cv="prefit"scikit-learn 1.8.0-এInvalidParameterErrorদেয়; কোডটি আদৌ চলেনি, বা পুরোনো version-এ চলেছে। (২) Calibrator train ডেটায় শেখানো: অংশ ৮-এর মতো leakage, test-এ বিকৃতি বাড়তে পারে। (৩) ECE মাপা হয়েছে সেই train-এই, তাই ০.০০৪ অর্থহীন। (৪) Class weight-এ model ৫০% হারের জগতে শিখেছে, তাই কাঁচা সম্ভাবনা ফোলা; বাজেট বেশি আসবে। আসল হারের ডেটায় calibration এটি সারাতে পারত, কিন্তু সেখানে হয়নি। (৫) ২৫০টি অর্ডারে isotonic সহজেই overfit করে।সঠিক নকশা: model train অংশে (class weight রাখলেও চলে, ক্রমের জন্য); calibrator আলাদা ভাগে, যার ফেরতের হার আসলের মতো, বা
CalibratedClassifierCV(cv=5); ডেটা কম বলেmethod="sigmoid"; আগে শেখানো model হলেFrozenEstimator. তারপর তালাবন্ধ test-এ reliability diagram, Brier আর ECE, আর বাজেট বনাম আসল ফেরত মেলানো। -
আউটপুট অনুমান করুন: চালানোর আগে লিখে ফেলুন নিচের কোড কী ছাপবে।
import numpy as np from sklearn.isotonic import IsotonicRegression s = np.array([1, 2, 3, 4, 5, 6]) y = np.array([0, 1, 0, 1, 1, 1]) iso = IsotonicRegression(out_of_bounds="clip").fit(s, y) print(iso.predict([1, 2.5, 3, 7]))[0. 0.5 0.5 1. ]PAV: মান ০, ১, ০, ১, ১, ১. দ্বিতীয় (১) আর তৃতীয় (০) ক্রম ভেঙেছে, মিলিয়ে ½; এখন ০, ½, ½, ১, ১, ১, যা একঘেয়ে। s = ১-এ ০. s = ২.৫ দুটি ½-এর মাঝে, সরলরেখায় interpolation-এও ½. s = ৩-এ ½. s = ৭ সীমার বাইরে,
clipশেষ মান ১ রাখে। “0.” আর “1.” NumPy-র ছাপার ধরন (ডেস্কটপে scikit-learn 1.8.0-এ মেলানো)। -
Platt আর prior, হাতে: (ক) একটি SVM-এর score-এর ওপর Platt শিখেছে a = ১.২, b = −০.৮. s = ০, ১ আর ২-এ সম্ভাবনা কত? (খ) Model শেখানো হয়েছিল এমন সময়ে যখন ফেরতের হার ২০%; এখন হার ৪০%, আর ফেরত-অর্ডারের চেহারা একই। Model একটি অর্ডারে ০.৩০ বলছে; সংশোধিত সম্ভাবনা কত? (গ) ফোনের খরচ ৬০ টাকা, ফেরতের ক্ষতি ৩০০ টাকা হলে এই অর্ডারে ফোন করবেন কি?
(ক) p = σ(১.২s − ০.৮). s = ০: σ(−০.৮) = ১/(১ + e০.৮) = ১/(১ + ২.২২৬) ≈ ০.৩১০. s = ১: σ(০.৪) ≈ ০.৫৯৯. s = ২: σ(১.৬) ≈ ০.৮৩২.
(খ) odds = ০.৩/০.৭ = ০.৪২৯. Prior-odds-এর অনুপাত = (০.৪/০.৬)/(০.২/০.৮) = ০.৬৬৭/০.২৫ = ২.৬৬৭. নতুন odds = ০.৪২৯ × ২.৬৬৭ = ১.১৪৩, p′ = ১.১৪৩/২.১৪৩ ≈ ০.৫৩৩. সূত্রে: ০.৩ × ২ / (০.৩ × ২ + ০.৭ × ০.৭৫) = ০.৬/১.১২৫ = ০.৫৩৩.
(গ) Threshold ৬০/৩০০ = ০.২. পুরোনো ০.৩০ বা নতুন ০.৫৩৩, দুটিতেই ফোন করা সস্তা: প্রত্যাশিত ক্ষতি ৩০০ × ০.৫৩৩ = ১৬০ টাকা, ফোনের ৬০-এর চেয়ে বেশি। কিন্তু ০.১৫ বলা একটি অর্ডারে সিদ্ধান্ত বদলায়: সংশোধনের আগে ০.১৫ < ০.২ (ফোন নয়), পরে ০.৩২ (ফোন)। Prior বদল ঠিক threshold-এর কাছের অর্ডারগুলোর সিদ্ধান্ত বদলায়।
নিজেকে যাচাই করুন
ভুল হলে কারণসহ ব্যাখ্যা পাবেন, আবার চেষ্টাও করতে পারবেন।
ক্রমএকটি classifier-এর সম্ভাবনা calibrate করে খরচের সিদ্ধান্তে ব্যবহারের ধাপগুলো সঠিক ক্রমে সাজান (▲▼ চেপে সরান)
- ডেটা train, calibration আর test-এ ভাগ করা, test তালাবন্ধ রাখা
- শুধু train অংশে model শেখানো
- Calibration অংশে model-এর score নেওয়া আর Platt বা isotonic শেখানো
- Test-এ reliability diagram, ECE আর Brier দিয়ে আগে-পরে তুলনা
- Calibrated সম্ভাবনায় খরচ থেকে পাওয়া threshold বসিয়ে সিদ্ধান্ত
- নতুন label এলে নিয়মিত reliability diagram দিয়ে নজরদারি
২০টি অর্ডার তিনটি ঝুড়িতে: ঝুড়ি ১-এ ১০টি, গড় অনুমান ০.২, বাস্তব হার ০.১; ঝুড়ি ২-এ ৬টি, গড় ০.৫, হার ০.৫; ঝুড়ি ৩-এ ৪টি, গড় ০.৯, হার ০.৭৫. ECE কত?
- ০.০৮
- ০.০৮৩
- ০.১৫
- ০.২৫
একটি model প্রতিটি অর্ডারকে ০.২ বলে, আর আসল ফেরতের হারও ০.২. Murphy-র ভাঙনে তার Brier score আর অংশগুলো কী?
- Brier ০, কারণ model পুরোপুরি calibrated
- REL ০, RES ০.১৬, Brier ০
- REL ০, RES ০, UNC = Brier = ০.১৬
- REL ০, RES ০, Brier ০.২
মাত্র ২০০টি calibration নমুনা আছে, আর reliability diagram একটি মসৃণ S-আকার দেখায়। কোন পদ্ধতি সবচেয়ে যুক্তিসঙ্গত?
- Isotonic regression, কারণ এটি যেকোনো আকার ধরতে পারে
- Platt scaling (sigmoid)
- Training ডেটায় isotonic, কারণ সেখানে নমুনা বেশি
- কিছুই না, কারণ S-আকার মানে model calibrated
একজন একটি random forest-এর isotonic calibrator শেখালেন সেই একই train সারিগুলোর predict_proba দিয়ে, যেগুলোতে forest শিখেছিল। নতুন ডেটায় সবচেয়ে সম্ভাব্য ফল কী?
- Calibration আরও ভালো হবে, কারণ train ডেটা বেশি
- ক্রম ভালো হবে, AUC বাড়বে
- কোনো প্রভাব পড়বে না
- সম্ভাবনা অতি-চরম হবে, নতুন ডেটায় ECE অনেক বাড়বে
একটি calibrated model শেখানো হয়েছিল যখন ফেরতের হার ১০%; এখন হার ৩০%, আর ফেরত-অর্ডারের চেহারা বদলায়নি। Model একটি অর্ডারে ০.২০ বলছে। Prior-সংশোধিত সম্ভাবনা প্রায় কত?
- ০.২০, কারণ model-এর অনুমান বদলায় না
- প্রায় ০.৪৯
- ০.৬০
- ০.৩০, নতুন সামগ্রিক হার
একটি সন্দেহজনক অর্ডার আটকালে, অর্ডারটি সৎ হলে ১০০ টাকা ক্ষতি; না আটকালে আর অর্ডারটি প্রতারণা হলে ৫০০ টাকা ক্ষতি; সঠিক সিদ্ধান্তে কোনো খরচ নেই। Calibrated সম্ভাবনা p-এর কোন সীমার ওপরে অর্ডার আটকানো উচিত?
- ০.৫
- ০.২০
- প্রায় ০.১৬৭
- প্রায় ০.৮৩৩
একটি multiclass neural network-এ temperature scaling (সব logit-কে একটি T > ১ দিয়ে ভাগ) প্রয়োগের পর কোনটি সত্য?
- Accuracy একই থাকে, সম্ভাবনাগুলো কম চরম হয়
- Accuracy বাড়ে, কারণ ভুল শ্রেণির সম্ভাবনা কমে
- সম্ভাবনাগুলো আরও চরম হয়
- Network-এর সব ওজন নতুন করে শেখানো হয়
শব্দকোষ
লেখার মধ্যে ডটেড দাগ দেওয়া শব্দে মাউস রাখুন বা চাপুন — অর্থ দেখাবে। এই পর্বের সব নতুন শব্দ এখানে একসাথে:
মনে রাখুন
- Calibration ≠ discrimination: “০.৭ বলা অর্ডারের ৭০% ঘটে” বনাম ভালো ক্রম (AUC). একঘেয়ে calibration ক্রম বদলায় না, শুধু সংখ্যা সৎ করে।
- মাপ: reliability diagram (uniform আর quantile ঝুড়ি, ঝুড়ির গণনাসহ), ECE = ∑(nb/N)|ōb − p̄b|, আর Brier = REL − RES + UNC (+ ঝুড়ির ভেতরের পদ)।
- কারণ: Naive Bayes জড়ানো প্রমাণ বারবার গোনে, SVM-এর score সম্ভাবনা নয়, resampling prior বদলায়, overfitting অতি-আত্মবিশ্বাস আনে।
- সারানো: আলাদা ডেটায় Platt σ(a·s + b) (কম ডেটায়) বা isotonic PAV (বেশি ডেটায়);
CalibratedClassifierCV(cv=5), আগে শেখানো model-এFrozenEstimator; অনেক শ্রেণিতে temperature. Train ডেটায় কখনো নয়। - ব্যবহার: threshold t* = cFP/(cFP + cFN) (সঠিক সিদ্ধান্তে খরচ শূন্য হলে), বাজেট = সম্ভাবনার যোগফল, আর prior বদলালে odds × [π′/(১ − π′)]/[π/(১ − π)].
আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ
- পর্ব ২৭ · Support Vector Machine — margin, support vector আর hard marginপরবর্তী পর্বসবচেয়ে চওড়া margin, support vector আর KKT দিয়ে SVM-এর শুরু।
- মেশিন লার্নিং · কোর্স হোম৭৭টি পর্ব১৪টি মডিউলের পুরো রোডম্যাপ; পর্ব ২৭ (Support Vector Machine) এখান থেকে খুলবেন।
- পর্ব ০২ · সমস্যা থেকে ML taskএই কোর্সProper scoring rule, hinge বনাম log loss, আর খরচ দেখে সিদ্ধান্ত।
- পর্ব ১৮ · Maximum likelihood আর MAPএই কোর্সLog loss কেন likelihood, আর separation-এ অতি-আত্মবিশ্বাস।
- AI-এর ভিত্তি · পর্ব ৫৯ · Logistic regressionআগের ভিত্তিSigmoid, threshold আর calibration-এর প্রথম দেখা।
- AI-এর ভিত্তি · পর্ব ৫১ · Naive Bayesআগের ভিত্তিস্বাধীনতার অনুমান, যা সম্ভাবনাকে চরমে ঠেলে।
- AI-এর ভিত্তি · পর্ব ৫৪ · অনিশ্চয়তায় সিদ্ধান্তআগের ভিত্তিExpected value আর utility, যার জন্য সৎ সম্ভাবনা লাগে।