এই পর্বে যা শিখবেন
- Conformal-এর নিশ্চয়তা ঠিক কী বলে আর কী বলে না, আর exchangeability কেন তার একমাত্র বড় শর্ত
- Split conformal হাতে আর NumPy-তে: score, ⌈(n + ১)(১ − α)⌉ সূচক, interval, আর বহু split-এ coverage যাচাই
- HistGradientBoosting-এর quantile loss দিয়ে CQR, আর উপদলে coverage মেপে conditional coverage-এর সীমা দেখা
- Multiclass classification-এ LAC prediction set, APS-এর ধারণা আর শ্রেণিভিত্তিক (Mondrian) coverage
- সময়ের drift-এ coverage পড়ে যাওয়া, rolling recalibration, আর jackknife+, adaptive conformal ও MAPIE কোথায় লাগে
পর্ব ২৪-এ quantile regression দিয়ে ১০–৯০ পরিসর বানিয়ে held-out ডেটায় coverage মেপেছেন, আর দেখেছেন যে ৮০% আসে শুধু model ঠিক থাকলে। পর্ব ২১-এ bootstrap দিয়ে অনিশ্চয়তা মেপেছেন, পর্ব ৪৬-এ Bayesian পরিসর দেখেছেন, আর পর্ব ২৬-এ সম্ভাবনা calibrate করেছেন। সবগুলোর একটি দুর্বলতা আছে: model-এর অনুমান ভুল হলে পরিসরও ভুল। এই পর্বের পদ্ধতি সেই নির্ভরতা কাটায়। ডেটা ভাগ করার নিয়ম (AI-এর ভিত্তি কোর্সের পর্ব ৫৬) আর মূল্যায়নের মাপ (একই কোর্সের পর্ব ৬০) ধরে নিচ্ছি। চারটি চালানো যায় এমন ব্লক পাতাতেই চলে (ব্রাউজারের Python, NumPy, pandas, scikit-learn আর matplotlib); প্রথমবার scikit-learn নামতে প্রায় দশ সেকেন্ড লাগে।
১ · একটি সংখ্যা নয়, একটি প্রতিশ্রুতি — conformal-এর মূল ধারণা
পরীক্ষার খাতা দেখার কথা ভাবুন। নতুন একজন পরীক্ষক কতটা কড়া, তা জানতে প্রধান পরীক্ষক তাঁকে আগে থেকে নম্বর জানা কুড়িটি খাতা দেন। পরীক্ষকের দেওয়া নম্বর আর আসল নম্বরের ফারাকগুলো সাজিয়ে প্রধান পরীক্ষক বলেন: “আপনার দেওয়া নম্বরের ±৪-এর মধ্যে আসল নম্বর প্রায় সবসময় থাকে।” পরীক্ষক কীভাবে নম্বর দেন, সেই নিয়ম জানার দরকার পড়েনি; দরকার পড়েছে শুধু আগের খাতায় তাঁর ভুলের মাপ, আর এই শর্ত যে নতুন খাতাগুলো আগের খাতার মতোই।
Conformal prediction ঠিক এই কাজ করে। যেকোনো model নিন: linear, boosting, neural network. আলাদা একটি calibration set-এ মাপুন, model-এর ভুল কত বড় হয়। সেই ভুলগুলোর একটি নির্দিষ্ট ক্রমের মান দিয়ে নতুন উদাহরণের চারপাশে পরিসর বানান। ফলাফল একটি prediction interval (regression-এ) বা একটি prediction set (classification-এ), সঙ্গে একটি গাণিতিক প্রতিশ্রুতি:
P( Yনতুন ∈ C(Xনতুন) ) ≥ ১ − α
এখানে C(x) হলো x-এর জন্য বানানো পরিসর বা সেট, আর α হলো আপনি কতটা ভুল মেনে নিতে রাজি (α = ০.১ মানে লক্ষ্য ৯০%). সম্ভাবনাটি নেওয়া হয় calibration ডেটা আর নতুন উদাহরণ, দুটির এলোমেলোতা মিলিয়ে। একমাত্র বড় শর্ত exchangeability: calibration-এর উদাহরণগুলো আর নতুন উদাহরণটির ক্রম বদলালে যৌথ বণ্টন বদলায় না। i.i.d. ডেটা exchangeable, কিন্তু শর্তটি তার চেয়েও একটু দুর্বল। Model ঠিক, ভুল normal, বা নমুনা বড়, এর কোনোটিই লাগে না। Model খারাপ হলে প্রতিশ্রুতি ভাঙে না; শুধু পরিসর চওড়া হয়, অর্থাৎ কম কাজের হয়।
Split conformal-এর চারটি ধাপ
নীল অংশে model শেখে, হলুদ অংশে ভুল মাপা হয়, সবুজ অংশ নতুন অর্ডার
ভুলের মাপকে বলে nonconformity score: একটি উদাহরণ model-এর চোখে কতটা “বেমানান”। Regression-এ সবচেয়ে সরল score ∣y − ŷ∣; classification-এ ১ − p̂(আসল শ্রেণি)। Score যত বড়, উদাহরণ তত অস্বাভাবিক। পুরো পদ্ধতির ধার কোন score বাছছেন তার ওপর: ভালো score মানে সরু পরিসর, খারাপ score মানে চওড়া পরিসর; কিন্তু দুই ক্ষেত্রেই coverage-এর প্রতিশ্রুতি একই।
২ · Split conformal হাতে — score, ⌈(n + ১)(১ − α)⌉ আর interval
Split conformal (inductive conformal নামেও পরিচিত) সবচেয়ে প্রচলিত রূপ। ধাপগুলো ছবির মতোই: train ভাগে model fit, calibration ভাগে n টি score s১, …, sn, তারপর
k = ⌈(n + ১)(১ − α)⌉, q̂ = সাজানো score-এর k-তম মান, C(x) = [ŷ(x) − q̂, ŷ(x) + q̂]
⌈ ⌉ মানে ওপরের দিকে পূর্ণসংখ্যায় তোলা (ceiling). কেন n নয়, n + ১? নতুন উদাহরণের score-টিকে n টি calibration score-এর সঙ্গে মিলিয়ে মোট n + ১টি সংখ্যা ভাবুন। Exchangeable হলে নতুন score-টি এই n + ১টির মধ্যে যেকোনো স্থানে বসার সম্ভাবনা সমান, প্রতিটি ১/(n + ১)। তাই সে প্রথম k টি স্থানের মধ্যে থাকার সম্ভাবনা অন্তত k/(n + ১) ≥ ১ − α. নিচের stepper নয়টি score-এ পুরো হিসাবটি করে।
- Score. Train ভাগে শেখা model-কে calibration-এর ৯টি অর্ডার দেখানো হয়েছে; প্রতিটির আসল আর অনুমিত সময়ের ফারাক এক একটি score.
- সাজানো। ছোট থেকে বড়: ০.২ সবচেয়ে ভালো অনুমান, ৩.৮ সবচেয়ে খারাপ। ক্রম-সংখ্যাই পরের ধাপের চাবি।
- সূচক k. α = ০.২ হলে (৯ + ১) × ০.৮ = ৮, তাই ৮ম ছোট score, q̂ = ২.৯. সাধারণ ৮০% quantile (interpolation করে ২.৫৪) একটু ছোট; সেটি নিলে coverage ৮০%-এর নিচে নামতে পারে।
- পরিসর। নতুন অর্ডারের অনুমান ১৪.৫ ঘণ্টা, তাই পরিসর [১১.৬, ১৭.৪]। প্রস্থ সব অর্ডারে একই, ৫.৮ ঘণ্টা।
- কেন n + ১. নতুন অর্ডারের score আর ৯টি পুরোনো score মিলিয়ে ১০টি। সবাই exchangeable হলে নতুনটির ক্রম ১ থেকে ১০-এর যেকোনোটি, সমান সম্ভাবনায়। ক্রম ৮ বা তার কম হলেই সে পরিসরের ভেতরে: সম্ভাবনা ৮/১০.
- কঠোর লক্ষ্য। α = ০.১-এ k = ৯, সবচেয়ে বড় score, পরিসর [১০.৭, ১৮.৩]। α = ০.০৫-এ k = ১০, যা n-এর বেশি: ৯টি নমুনা দিয়ে ৯৫% প্রতিশ্রুতি দেওয়া যায় না, তাই পরিসর অসীম। ছোট calibration set-এ কঠোর α চাইলে এমনই হয়।
এখন একই নিয়ম আসল আকারে। নিচের module বাজারঘরের (কাল্পনিক দোকান) তিন রকম ডেটা seed দিয়ে বানায়, কোনো আসল দোকানের নয়। delivery-তে ডেলিভারির সময় দূরত্ব, বৃষ্টি আর চর-হাওরের মতো দূরবর্তী এলাকার (remote, প্রায় ২০% অর্ডার) ওপর নির্ভর করে, আর ছড়ানো দূরত্বের সঙ্গে বাড়ে; দূরবর্তী এলাকায় ছড়ানো আরও আড়াই গুণ। অর্থাৎ ডেটা heteroscedastic. returns ফেরত দেওয়া পণ্যের চারটি কারণ বানায়, আর monthly আট মাসের অর্ডার, যার ষষ্ঠ মাস থেকে বর্ষা।
# বাজারঘর (কাল্পনিক দোকান): seed দিয়ে বানানো ডেলিভারি আর ফেরতের ডেটা
import numpy as np
import pandas as pd
def delivery(n=3000, seed=58):
rng = np.random.default_rng(seed)
km = rng.uniform(2, 80, n).round(1)
rain = rng.binomial(1, 0.3, n)
remote = rng.binomial(1, 0.2, n) # চর/হাওর এলাকা: সময়ের ছড়ানো বেশি
sd = (0.5 + 0.06 * km) * (1 + 1.5 * remote)
hours = 6 + 0.25 * km + 3 * rain + 2 * remote + sd * rng.standard_normal(n)
X = pd.DataFrame({"km": km, "rain": rain, "remote": remote})
return X, np.maximum(hours, 0.5).round(2)
REASONS = ["size", "damaged", "late", "wrong_item"] # ফেরতের চারটি কারণ
def returns(n=4000, seed=58):
rng = np.random.default_rng(seed)
cat = rng.choice(3, n, p=[0.5, 0.3, 0.2]) # fashion, electronics, home
hours = rng.gamma(3, 8, n).round(1) # ডেলিভারিতে কত ঘণ্টা
items = rng.integers(1, 6, n) # অর্ডারে কয়টি পণ্য
logit = np.column_stack([
1.0 + 2.5 * (cat == 0) - 1.5 * (cat == 1),
2.8 * (cat == 1) + 1.2 * (cat == 2),
-2.2 + 0.09 * hours,
-2.6 + 0.8 * items])
p = np.exp(logit) / np.exp(logit).sum(1, keepdims=True)
y = (p.cumsum(1) > rng.random((n, 1))).argmax(1)
X = np.column_stack([cat == 0, cat == 1, hours / 24, items]).astype(float)
return X, y
def monthly(per_month=300, seed=58, monsoon_from=6):
rng = np.random.default_rng(seed)
month = np.repeat(np.arange(1, 9), per_month)
km = rng.uniform(2, 80, month.size).round(1)
rain = rng.binomial(1, 0.3, month.size)
wet = month >= monsoon_from # বর্ষা: দূরের রাস্তায় দেরি
sd = (0.5 + 0.06 * km) * np.where(wet, 1.6, 1.0)
hours = 6 + 0.25 * km + 3 * rain + 3 * wet * (km > 40) + sd * rng.standard_normal(month.size)
return pd.DataFrame({"month": month, "km": km, "rain": rain,
"hours": np.maximum(hours, 0.5).round(2)})প্রথম ব্লক ২,০০০টি অর্ডার থেকে ১,০০০টি train, ৫০০টি calibration আর ৫০০টি test নেয়, LinearRegression শেখায়, আর উপরের নিয়মে পরিসর বানায়। তারপর একই কাজ ২০০টি আলাদা এলোমেলো ভাগে করে প্রতিবারের test coverage গোনে। ছবির লেখা ইংরেজিতে, কারণ পাতার matplotlib বাংলা অক্ষর ঠিকমতো আঁকে না।
import numpy as np
import pandas as pd # bazar_conformal module-এর জন্য লাগে
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression
from bazar_conformal import delivery
X, y = delivery(n=2000)
X, alpha = X.to_numpy(), 0.1
def split_conformal(seed, n_cal=500):
idx = np.random.default_rng(seed).permutation(len(y))
tr, cal, te = idx[:1000], idx[1000:1000 + n_cal], idx[1000 + n_cal:]
model = LinearRegression().fit(X[tr], y[tr])
scores = np.abs(y[cal] - model.predict(X[cal])) # residual score
k = int(np.ceil((n_cal + 1) * (1 - alpha))) # কততম ছোট score
q = np.sort(scores)[k - 1]
pred = model.predict(X[te]) # interval: pred ± q
return k, q, np.mean(np.abs(y[te] - pred) <= q)
k, q, cov = split_conformal(seed=0)
print(f"n_cal=500 k={k} q_hat={q:.2f} hours test coverage={cov:.3f}")
covs = np.array([split_conformal(s)[2] for s in range(200)])
print(f"200 splits: mean={covs.mean():.4f} sd={covs.std():.4f} "
f"min={covs.min():.3f} max={covs.max():.3f}")
print(f"theory: mean in [{1 - alpha:.4f}, {k / 501:.4f}]")
print("splits below 0.88:", int((covs < 0.88).sum()), "of 200")
fig, ax = plt.subplots(figsize=(6, 3.4))
fig.subplots_adjust(bottom=0.17)
ax.hist(covs, bins=20, color="tab:blue", alpha=0.8)
ax.axvline(0.9, color="r", ls="--", label="target 1 - alpha = 0.9")
ax.set_xlabel("test coverage of one split"); ax.set_ylabel("number of splits")
ax.legend(fontsize=8); plt.show()আসল আউটপুট (ব্রাউজারের Python; histogram ব্লকের নিচে আঁকা হয়):
n_cal=500 k=451 q_hat=7.09 hours test coverage=0.904
200 splits: mean=0.8991 sd=0.0181 min=0.840 max=0.948
theory: mean in [0.9000, 0.9002]
splits below 0.88: 29 of 200
প্রথম ভাগে ৫০০টি score-এর ৪৫১তম মান ৭.০৯ ঘণ্টা, তাই প্রতিটি অর্ডারের পরিসর ŷ ± ৭.০৯; test-এ ৯০.৪% ধরা পড়েছে। ২০০টি ভাগে গড় coverage ০.৮৯৯১. তত্ত্ব বলে প্রত্যাশিত মান ০.৯০০০ থেকে ০.৯০০২-এর মধ্যে (score-এ সমান মান না থাকলে ঠিক k/(n + ১) = ৪৫১/৫০১); ২০০টি ভাগের গড়ের নিজের ভুল প্রায় ০.০১৮১/√২০০ ≈ ০.০০১৩, তাই ০.৮৯৯১ তত্ত্বের সঙ্গে মেলে। একটি ভাগে কিন্তু ৮৪% থেকে ৯৪.৮% পর্যন্ত যেকোনো কিছু আসতে পারে: ২০০টির ২৯টিতে ৮৮%-এর নিচে। প্রতিশ্রুতি “গড়ে অন্তত ৯০%”, “প্রতিটি test set-এ ৯০%” নয়। এই ছড়ানোর এক অংশ calibration set থেকে আসে, এক অংশ ৫০০টি test অর্ডারের নিজের এলোমেলোতা থেকে।
একই ডেটা দুবার নয়: Calibration ভাগ model-এর training-এ ঢুকলে score গুলো কৃত্রিমভাবে ছোট হয় (model সেগুলো মুখস্থ করেছে), আর পরিসর বিপজ্জনকভাবে সরু হয়। একই কারণে calibration ভাগে hyperparameter বা α বাছাই করবেন না। Calibration-এর পর train আর calibration মিলিয়ে model আবার fit করলে নিশ্চয়তা আর আগের প্রমাণে চলে না।
৩ · “৯০% coverage” ঠিকভাবে পড়া — marginal, প্রতিটি ক্রেতার নয়
Conformal-এর প্রতিশ্রুতি marginal coverage: সব x আর সব calibration ভাগ মিলিয়ে গড়ে অন্তত ১ − α. এটি conditional coverage নয়, অর্থাৎ “এই নির্দিষ্ট দূরত্বের, এই এলাকার অর্ডারের জন্য ৯০%” নয়। দুটি প্রশ্ন আলাদা, আর ভুল পড়লে সবচেয়ে বেশি ঠকেন সংখ্যালঘু দলের ক্রেতারা। নিচের stepper একটি সরল মিশ্রণ দিয়ে কথাটি পরিষ্কার করে।
- সম্ভাবনা কিসের ওপর। ৯০% হলো দুই রকম এলোমেলোতার গড়: কোন নতুন অর্ডার এল, আর কোন উদাহরণগুলো calibration-এ পড়ল। কোনো একটি অর্ডার বা একটি ক্রেতাকে ধরে রেখে এই সংখ্যা বলা যায় না।
- দুই দল। কাল্পনিক একটি পরিস্থিতি: কাছের এলাকার অর্ডার ৮০%, সেখানে পরিসর ৯৫% ধরে; দূরবর্তী এলাকার অর্ডার ২০%, সেখানে মাত্র ৭০% ধরে, কারণ সেখানে ছড়ানো বেশি অথচ পরিসরের প্রস্থ একই।
- গড়ে ঠিক ৯০%. ০.৮ × ০.৯৫ + ০.২ × ০.৭০ = ০.৯০. Marginal প্রতিশ্রুতি পুরোপুরি রক্ষা হয়েছে, অথচ দূরের প্রতি দশজন ক্রেতার তিনজন প্রতিশ্রুতির বাইরে।
- একটি calibration ভাগে। ভাগটি স্থির ধরলে ভবিষ্যতের coverage একটি Beta(k, n + ১ − k) বণ্টন মানে। n = ৫০০-তে গড় ০.৯০০২, SD প্রায় ০.০১৩৪: একটি ভাগ দুর্ভাগ্যক্রমে ৮৮%-ও দিতে পারে। বড় n এই ছড়ানো কমায়।
- দুই সীমা আর একটি নিষেধ। Coverage অন্তত ০.৯০, আর score-এ সমান মান না থাকলে বড়জোর ০.৯০২: conformal অযথা চওড়াও নয়। কিন্তু “x জেনে এই অর্ডারটি ৯০% সম্ভাবনায় পরিসরে” কথাটি এই প্রতিশ্রুতি থেকে আসে না।
কোনো model-নির্ভরতা ছাড়া প্রতিটি x-এর জন্য conditional coverage দেওয়া সম্ভব কি না, এর উত্তর গবেষণায় মোটামুটি স্থির: সাধারণভাবে না। Vovk (২০১২), Lei আর Wasserman (২০১৪), আর পরে Foygel Barber ও সহকর্মীরা (২০২১) দেখান, বণ্টন-মুক্ত পদ্ধতিতে সঠিক conditional coverage চাইলে সাধারণ পরিস্থিতিতে পরিসর অসীম চওড়া হয়ে যায়। বাস্তবের পথ দুটি: score এমনভাবে বাছা যাতে প্রস্থ ঝুঁকির সঙ্গে বদলায় (অংশ ৪), আর জানা দলগুলোর জন্য আলাদা calibration (অংশ ৫-এর Mondrian).
৪ · Conformalized quantile regression — প্রস্থ যেখানে দরকার
∣y − ŷ∣ score-এর পরিসর সব অর্ডারে একই চওড়া। Heteroscedastic ডেটায় তাই কাছের অর্ডারে অযথা চওড়া, দূরের অর্ডারে সরু। পর্ব ২৪-এর quantile regression প্রস্থকে ঝুঁকির সঙ্গে বদলায়, কিন্তু coverage-এর নিশ্চয়তা দেয় না। Conformalized quantile regression (CQR; Romano, Patterson আর Candès, ২০১৯) দুটিকে মেলায়:
- Train ভাগে দুটি quantile model শেখান: q̂lo(x) (৫তম percentile) আর q̂hi(x) (৯৫তম)। পর্ব ৩৫-এর মতো
HistGradientBoostingRegressor(loss="quantile")এ কাজ করে, pinball loss কমিয়ে। - Calibration-এ score Ei = max(q̂lo(xi) − yi, yi − q̂hi(xi)). y ব্যান্ডের ভেতরে থাকলে E ঋণাত্মক (নিকটতম সীমা থেকে কত ভেতরে), বাইরে থাকলে ধনাত্মক (কত বাইরে)।
- আগের মতো q̂ = E-এর k-তম ছোট মান, আর পরিসর [q̂lo(x) − q̂, q̂hi(x) + q̂]। q̂ ধনাত্মক হলে ব্যান্ড চওড়া হয়, ঋণাত্মক হলে সরু।
Quantile model ভালো হলে q̂ ছোট, আর প্রস্থ মূলত model-এর নিজের। Model খারাপ হলেও marginal coverage রক্ষা পায়, কারণ যুক্তিটি অংশ ২-এর ক্রমের যুক্তিই। নিচের ব্লক একই ডেটায় সাধারণ split conformal (HistGradientBoosting-এর গড়-model আর ∣y − ŷ∣) আর CQR পাশাপাশি চালায়, তারপর তিনটি দলে coverage আর গড় প্রস্থ মাপে: কাছে (৪০ km পর্যন্ত), দূরে, আর দূরবর্তী এলাকা (remote).
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.ensemble import HistGradientBoostingRegressor as HGB
from bazar_conformal import delivery
X, y = delivery(n=3000)
tr, cal, te = np.split(np.random.default_rng(1).permutation(3000), [1500, 2250])
k = int(np.ceil((len(cal) + 1) * 0.9)) # alpha = 0.1
kth = lambda s: np.sort(s)[k - 1]
fit = lambda **kw: HGB(random_state=0, **kw).fit(X.iloc[tr], y[tr])
mean = fit() # সাধারণ split conformal
q1 = kth(np.abs(y[cal] - mean.predict(X.iloc[cal])))
m = mean.predict(X.iloc[te]); lo1, hi1 = m - q1, m + q1
qlo = fit(loss="quantile", quantile=0.05) # CQR: দুই quantile model
qhi = fit(loss="quantile", quantile=0.95)
E = np.maximum(qlo.predict(X.iloc[cal]) - y[cal], y[cal] - qhi.predict(X.iloc[cal]))
q2 = kth(E)
lo2, hi2 = qlo.predict(X.iloc[te]) - q2, qhi.predict(X.iloc[te]) + q2
yt, Xt = y[te], X.iloc[te]
grp = np.where(Xt.remote == 1, "remote", np.where(Xt.km > 40, "far", "near"))
res = pd.DataFrame({"split_cov": (yt >= lo1) & (yt <= hi1), "split_w": hi1 - lo1,
"cqr_cov": (yt >= lo2) & (yt <= hi2), "cqr_w": hi2 - lo2})
tab = res.groupby(grp).mean()
tab.loc["all"] = res.mean()
tab["n"] = pd.Series(grp).value_counts().reindex(tab.index).fillna(len(te)).astype(int)
print(f"q_split={q1:.2f} q_cqr={q2:.2f}"); print(tab.round(3))
fig, ax = plt.subplots(figsize=(6, 3.4)); fig.subplots_adjust(bottom=0.17)
for r, c in [(0, "tab:blue"), (1, "tab:orange")]:
s = (Xt.remote == r).to_numpy()
ax.scatter(Xt.km[s], (hi2 - lo2)[s], s=8, c=c, label=f"CQR, remote={r}")
ax.axhline(2 * q1, color="k", ls="--", label="split conformal (constant)")
ax.set_xlabel("distance from hub (km)"); ax.set_ylabel("interval width (hours)")
ax.legend(fontsize=8); plt.show()আসল আউটপুট (ব্রাউজারের Python; ছবিটি ব্লকের নিচে আঁকা হয়):
q_split=7.59 q_cqr=0.88
split_cov split_w cqr_cov cqr_w n
far 0.939 15.173 0.890 13.354 310
near 1.000 15.173 0.910 7.121 290
remote 0.727 15.173 0.880 22.790 150
all 0.920 15.173 0.896 12.831 750
সব মিলিয়ে দুটি পদ্ধতিই প্রতিশ্রুতি রেখেছে (৯২% আর ৮৯.৬%; ৭৫০টি test অর্ডারে এটুকু ওঠানামা স্বাভাবিক)। দলে ভাগ করলে ছবি বদলায়। সাধারণ split conformal সবাইকে ১৫.১৭ ঘণ্টার একই পরিসর দেয়: কাছের অর্ডারে ১০০% (অযথা চওড়া), দূরবর্তী এলাকায় মাত্র ৭২.৭%. CQR কাছের অর্ডারে প্রস্থ প্রায় অর্ধেক করেছে (৭.১২), দূরবর্তী এলাকায় বাড়িয়েছে (২২.৭৯), আর তিন দলেই coverage ৮৮–৯১%. গড় প্রস্থও কম, ১২.৮৩ বনাম ১৫.১৭. q_cqr = ০.৮৮ ধনাত্মক: দুটি quantile model training-এর পর একটু বেশি আত্মবিশ্বাসী ছিল, conformal ধাপ ব্যান্ডের দুই পাশে ০.৮৮ ঘণ্টা যোগ করে তা সারিয়েছে। ছবিতে CQR-এর প্রস্থ দূরত্বের সঙ্গে বাড়ে, আর কমলা বিন্দুগুলো (দূরবর্তী এলাকা) নীলদের ওপরে; ভাঙা রেখা সাধারণ split conformal-এর ধ্রুব প্রস্থ।
সতর্কতা: CQR দলভিত্তিক coverage-এর নিশ্চয়তা দেয় না। এখানে ৮৮% এসেছে কারণ quantile model দূরবর্তী এলাকার ছড়ানো মোটামুটি শিখেছে। Model কোনো দলের ছড়ানো না শিখলে (feature নেই, বা দলটি খুব ছোট) সেই দল আবার কম coverage পাবে। তাই সবসময় গুরুত্বপূর্ণ দলে আলাদা করে coverage মাপুন; দরকারে সেই দলের জন্য আলাদা calibration করুন।
৫ · Classification-এ prediction set — LAC, APS আর Mondrian
বাজারঘরের ফেরত-দল প্রতিটি ফেরতের কারণ আগেভাগে অনুমান করতে চায়: মাপ মেলেনি (size), ভাঙা বা নষ্ট (damaged), দেরি (late), নাকি ভুল পণ্য (wrong_item). এটি একটি multiclass classification (পর্ব ২৫)। একটি শ্রেণির বদলে conformal একটি সেট দেয়: “কারণটি {size, damaged}-এর মধ্যে, অন্তত ৯০% নিশ্চয়তায়।” সেট ছোট মানে model নিশ্চিত, বড় মানে দ্বিধায়; সেটের আকার নিজেই অনিশ্চয়তার মাপ।
সবচেয়ে সরল score LAC (least ambiguous set-valued classifier; Sadinle, Lei আর Wasserman, ২০১৯): s = ১ − p̂(আসল শ্রেণি)। Calibration-এ q̂ বের করার পর নতুন উদাহরণের সেট = যেসব শ্রেণির p̂ ≥ ১ − q̂. গড় সেটের আকার এতে যতটা সম্ভব ছোট হয়, কিন্তু সহজ উদাহরণে বেশি আর কঠিন (অনিশ্চিত) উদাহরণে কম coverage দেওয়ার প্রবণতা থাকে। APS (adaptive prediction sets; Romano, Sesia আর Candès, ২০২০) অন্যভাবে ভাবে: সম্ভাবনা বড় থেকে ছোট সাজিয়ে যোগ করতে থাকুন যতক্ষণ না আসল শ্রেণি আসে; সেই যোগফলই score. তাতে সেটের আকার উদাহরণের অনিশ্চয়তার সঙ্গে আরও মানানসই হয়, বিনিময়ে গড় সেট একটু বড়।
| ধাপ | |
| p̂ | |
| হিসাব | |
| সেট |
- Calibration score. একটি calibration অর্ডারের আসল কারণ late, model তাকে মাত্র ০.১৫ দিয়েছিল: score ১ − ০.১৫ = ০.৮৫, বেশ বেমানান। এমন সব score-এর k-তম মান q̂.
- সীমা। q̂ = ০.৭৫ হলে নতুন অর্ডারে যে কারণের p̂ অন্তত ০.২৫, সে সেটে ঢোকে। শর্তটি আসলে “score ≤ q̂”-এর অন্য রূপ।
- অর্ডার A. size (০.৫২) আর damaged (০.৩০) সীমা পেরোয়; সেট {size, damaged}. Top-1 উত্তর size হতো, কিন্তু model ততটা নিশ্চিত নয়।
- অর্ডার B. size ০.৮৮, বাকিরা ০.০৭-এর নিচে: সেটে একটি কারণ। এই অর্ডার স্বয়ংক্রিয়ভাবে ঠিক বিভাগে পাঠানো যায়।
- অর্ডার C. তিনটি কারণ ০.২৫-এর ওপরে: সেটের আকার ৩. বড় সেট একটি সংকেত: এই ফেরত একজন মানুষের দেখা দরকার।
- APS. সম্ভাবনা বড় থেকে যোগ করে ০.৮০-এর সীমা ছোঁয়া পর্যন্ত নেওয়া হয়: ০.৫২, তারপর ০.৮২. সেট আবার {size, damaged}. (প্রচলিত বাস্তবায়নে শেষ শ্রেণিতে কিছু এলোমেলোতা যোগ হয়, যাতে coverage বেশি না হয়।)
Marginal coverage এখানেও শ্রেণিগুলোর মধ্যে অসমান হতে পারে: বিরল শ্রেণির উদাহরণ সাধারণত কম সম্ভাবনা পায়, তাই তাদের score বড়, আর একটি সাধারণ q̂ তাদের প্রায়ই বাদ দেয়। প্রতিকার Mondrian conformal: প্রতিটি শ্রেণির জন্য আলাদা q̂, শুধু সেই শ্রেণির calibration উদাহরণ থেকে। তাতে প্রতিটি শ্রেণি নিজের ১ − α প্রতিশ্রুতি পায়, যদি প্রতিটি শ্রেণিতে যথেষ্ট calibration উদাহরণ থাকে। একই ভাবনা regression-এর দলেও খাটে (কাছে, দূরে, দূরবর্তী এলাকা)। নিচের ব্লক LogisticRegression দিয়ে দুটিই চালায়; ডেটায় কারণগুলোর ভাগ অসমান (class imbalance).
import numpy as np
import pandas as pd
from sklearn.linear_model import LogisticRegression
from bazar_conformal import returns, REASONS
X, y = returns(n=4000)
tr, cal, te = np.split(np.random.default_rng(4).permutation(len(y)), [2000, 3000])
clf = LogisticRegression(max_iter=1000).fit(X[tr], y[tr])
P_cal, P_te = clf.predict_proba(X[cal]), clf.predict_proba(X[te])
def qhat(s, alpha=0.1):
k = int(np.ceil((len(s) + 1) * (1 - alpha)))
return np.inf if k > len(s) else np.sort(s)[k - 1]
s_cal = 1 - P_cal[np.arange(len(cal)), y[cal]] # LAC score = 1 - p(আসল শ্রেণি)
q = qhat(s_cal)
sets = P_te >= 1 - q # প্রতি সারিতে কোন শ্রেণি থাকবে
hit = sets[np.arange(len(te)), y[te]]
print(f"q_hat={q:.3f} -> keep reasons with p >= {1 - q:.3f}")
print("top-1 accuracy:", round((P_te.argmax(1) == y[te]).mean(), 3),
"| set coverage:", round(hit.mean(), 3))
print("set size counts:", pd.Series(sets.sum(1)).value_counts().sort_index().to_dict())
q_c = np.array([qhat(s_cal[y[cal] == c]) for c in range(4)]) # Mondrian
sets_m = P_te >= 1 - q_c
hit_m = sets_m[np.arange(len(te)), y[te]]
tab = pd.DataFrame({"reason": np.array(REASONS)[y[te]], "LAC": hit,
"Mondrian": hit_m, "size_M": sets_m.sum(1)})
out = tab.groupby("reason").agg(n=("LAC", "size"), LAC=("LAC", "mean"),
Mondrian=("Mondrian", "mean"), size_M=("size_M", "mean"))
print(out.round(3)); print("Mondrian thresholds:", np.round(1 - q_c, 3))আসল আউটপুট (ব্রাউজারের Python):
q_hat=0.876 -> keep reasons with p >= 0.124
top-1 accuracy: 0.772 | set coverage: 0.91
set size counts: {1: 669, 2: 220, 3: 90, 4: 21}
n LAC Mondrian size_M
reason
damaged 327 0.957 0.917 2.260
late 82 0.622 0.915 2.220
size 532 0.979 0.906 1.957
wrong_item 59 0.424 0.864 2.288
Mondrian thresholds: [0.391 0.306 0.024 0.034]
Top-1 accuracy ৭৭.২%, কিন্তু সেট ৯১% ক্ষেত্রে আসল কারণ ধরে। ১,০০০টি test অর্ডারের ৬৬৯টিতে সেটে একটি কারণ, অর্থাৎ বেশির ভাগ ফেরত সরাসরি পাঠানো যায়; ১১১টিতে তিন বা চারটি কারণ, সেগুলো মানুষের হাতে। শ্রেণি ধরে দেখলে সাধারণ LAC-এর ৯১% আসলে বড় দুই শ্রেণির ৯৫.৭% আর ৯৭.৯%, আর বিরল দুটির ৬২.২% আর ৪২.৪%-এর গড়: ভুল পণ্যের অর্ধেকের বেশি ফেরত সেটের বাইরে। Mondrian প্রতিটি শ্রেণির সীমা আলাদা করে (late আর wrong_item-এর সীমা মাত্র ০.০২৪ আর ০.০৩৪), তাই চার শ্রেণির coverage ৮৬–৯২%; দাম গড় সেটের আকার, প্রায় ২ থেকে ২.৩. wrong_item-এর ৮৬.৪% লক্ষ্যের নিচে, কিন্তু সেখানে test-এ মাত্র ৫৯টি অর্ডার আর calibration-এও প্রায় ষাটটি। একই ডেটার আটটি আলাদা ভাগে এই শ্রেণির Mondrian coverage ০.৭৭ থেকে ০.৯৮৫ পর্যন্ত ঘুরেছে (একটি স্থানীয় run): ছোট দলে প্রতিশ্রুতি গড়ে ঠিক থাকে, একটি ভাগে অনেক ওঠানামা করে।
৬ · Exchangeability ভাঙলে — সময়, drift আর rolling recalibration
পুরো প্রতিশ্রুতি একটি শর্তের ওপর দাঁড়িয়ে: calibration আর নতুন ডেটা একই রকম। সময়ের ডেটায় এটি প্রায়ই সত্য নয়। বর্ষায় দূরের রাস্তা ডুবে যায়, নতুন কুরিয়ার আসে, ঈদের ভিড় বাড়ে। Input-এর বণ্টন বদলানো (data drift) বা input আর উত্তরের সম্পর্ক বদলানো (concept drift) হলে পুরোনো মাসের score নতুন মাসের ভুলের প্রতিনিধি থাকে না। এই shift-গুলো ধরা আর সামলানোর পূর্ণ আলোচনা পরের পর্ব ৫৯ (Distribution shift — covariate, label আর concept shift ধরা ও সামলানো)-এর বিষয়; এখানে দেখব coverage-এর কী হয়।
নিচের ব্লকে model শেখে মাস ১–৩-এ। “স্থির” পদ্ধতি একবার মাস ৪ দিয়ে calibrate করে আর পরের সব মাসে সেই q̂ রাখে। “Rolling” পদ্ধতি প্রতিটি মাসের শুরুতে আগের মাসের (যার আসল সময় এখন জানা) score দিয়ে আবার calibrate করে; model একই থাকে। মাস ৬ থেকে বর্ষা: ছড়ানো ১.৬ গুণ, আর ৪০ km-এর বেশি দূরের অর্ডারে গড়ে ৩ ঘণ্টা বাড়তি।
import numpy as np
import pandas as pd
from sklearn.linear_model import LinearRegression
from bazar_conformal import monthly
df = monthly() # ৮ মাস × ৩০০ অর্ডার, মাস ৬ থেকে বর্ষা
cols = ["km", "rain"]
old = df[df.month <= 3]
model = LinearRegression().fit(old[cols], old.hours)
df["score"] = np.abs(df.hours - model.predict(df[cols]))
score = lambda m: df.score[df.month == m].to_numpy()
def qhat(s, alpha=0.1):
k = int(np.ceil((len(s) + 1) * (1 - alpha)))
return np.sort(s)[k - 1]
q_static = qhat(score(4)) # একবার, মাস ৪ দিয়ে calibrate
rows = []
for m in range(5, 9):
q_roll = qhat(score(m - 1)) # প্রতি মাসে আগের মাস দিয়ে আবার calibrate
rows.append([m, np.mean(score(m) <= q_static), np.mean(score(m) <= q_roll),
2 * q_static, 2 * q_roll])
cols_out = ["test_month", "static_cov", "rolling_cov", "static_w", "rolling_w"]
print(pd.DataFrame(rows, columns=cols_out).round(3).to_string(index=False))
far = df.km > 40
for name, mask in [("near (<=40 km)", ~far), ("far (>40 km)", far)]:
s8 = df.score[(df.month == 8) & mask]
print(f"month 8 {name}: rolling coverage = {np.mean(s8 <= qhat(score(7))):.3f}")আসল আউটপুট (ব্রাউজারের Python):
test_month static_cov rolling_cov static_w rolling_w
5 0.867 0.867 9.877 9.877
6 0.693 0.743 9.877 10.959
7 0.683 0.857 9.877 18.094
8 0.670 0.927 9.877 21.648
month 8 near (<=40 km): rolling coverage = 1.000
month 8 far (>40 km): rolling coverage = 0.862
মাস ৫-এ দুটি পদ্ধতি এক (দুটিই মাস ৪ দিয়ে calibrate), coverage ৮৬.৭%: ৩০০টি অর্ডারে এটুকু নিচে নামা স্বাভাবিক ওঠানামার মধ্যে। বর্ষা শুরু হতেই স্থির পরিসর (প্রস্থ ৯.৮৮ ঘণ্টা) ৬৯% থেকে ৬৭%-এ নামে, আর আর ওঠে না: প্রতিশ্রুতি চুপচাপ ভেঙেছে, কোনো error আসেনি। Rolling মাস ৬-এ নিজেও ধরা খায় (৭৪.৩%), কারণ সে তখনও বর্ষার আগের মাস দিয়ে calibrate করছে; মাস ৭ থেকে বর্ষার score দেখে প্রস্থ ১৮–২২ ঘণ্টায় বাড়ায়, আর coverage ৮৫.৭% ও ৯২.৭%-এ ফেরে। অর্থাৎ recalibration এক ধাপ পিছিয়ে চলে। শেষ দুই লাইন দেখায়, মাস ৮-এ গড় ঠিক হলেও কাছের অর্ডারে ১০০% আর দূরের অর্ডারে ৮৬.২%: drift একটি দলকে বেশি আঘাত করেছে, আর একটি প্রস্থ দিয়ে সবাইকে ঢাকা অংশ ৩-এর সমস্যাই আবার।
এই সমস্যার জন্য কয়েকটি গবেষণা-পথ আছে। Adaptive conformal inference (ACI; Gibbs আর Candès, ২০২১) প্রতিটি নতুন উত্তরের পর α-কে নিজেই সমন্বয় করে: αt+1 = αt + γ(α − errt), যেখানে errt = ১ যদি শেষ উত্তর পরিসরের বাইরে পড়ে। বেশি ভুল হলে α ছোট হয়, পরিসর চওড়া হয়; দীর্ঘমেয়াদে গড় ভুল α-র কাছে থাকে, এমনকি বণ্টন বদলালেও। Covariate shift জানা থাকলে weighted conformal (Tibshirani, Barber, Candès আর Ramdas, ২০১৯) calibration score-কে নতুন বণ্টনের অনুপাতে ওজন দেয়। আর time series-এর জন্য পর্ব ৫২-এর backtest-এর ভুল দিয়ে band বানানো আসলে এই rolling ভাবনার কাছাকাছি। কোনোটিই i.i.d.-র মতো শক্ত নিশ্চয়তা দেয় না; সব ক্ষেত্রে coverage-এর নজরদারি চালু রাখুন।
৭ · ডেটা বাঁচানোর রূপ আর MAPIE — একটি সত্যিকারের run
Split conformal-এর দাম ডেটা: calibration ভাগ model শেখায় না। ডেটা কম হলে তিনটি বিকল্প আছে। Full conformal (মূল রূপ) প্রতিটি সম্ভাব্য y-এর জন্য model আবার fit করে; প্রতিশ্রুতি একই, কিন্তু খরচ বিশাল। Jackknife+ (Barber, Candès, Ramdas আর Tibshirani, ২০২১) leave-one-out model আর তাদের residual মিলিয়ে পরিসর বানায়; তার প্রমাণিত নিশ্চয়তা ১ − ২α, যদিও বাস্তবে সাধারণত ১ − α-এর কাছে থাকে। CV+ আর cross-conformal একই কাজ K-fold দিয়ে করে, কম খরচে। এগুলো বোঝার জন্য পর্ব ২১-এর jackknife মনে রাখাই যথেষ্ট।
পাতার Python-এ MAPIE নেই, তাই একটি আলাদা ফোল্ডারে uv দিয়ে ছোট project বানিয়ে আসল run করা হয়েছে। লেখার সময়ে Python 3.13.5, MAPIE 1.6.0, scikit-learn 1.8.0. MAPIE 1.x-এর API আগের 0.x থেকে অনেক বদলেছে (পুরোনো MapieRegressor আর alpha-এর জায়গায় এখন SplitConformalRegressor আর confidence_level), তাই পুরোনো টিউটোরিয়াল বা AI-এর দেওয়া কোড মিলিয়ে নিন।
$ uv init --vcs none --author-from none bazarghar-conformal
$ cd bazarghar-conformal
$ uv add scikit-learn==1.8.0 mapie
…
+ mapie==1.6.0
+ scikit-learn==1.8.0
…
from mapie.regression import SplitConformalRegressor
from mapie.classification import SplitConformalClassifier
# একই ডেটা আর একই ভাগ (seed 0 আর 4), model আগে থেকেই fit করা
scr = SplitConformalRegressor(model, confidence_level=0.9, prefit=True)
scr.conformalize(X[cal], y[cal])
pred, iv = scr.predict_interval(X[te]) # iv: (n, 2, 1)
scc = SplitConformalClassifier(clf, confidence_level=0.9,
conformity_score="lac", prefit=True)
scc.conformalize(Xc[cal], yc[cal])
_, sets = scc.predict_set(Xc[te]) # sets: (n, 4, 1), True/Falseসত্যিকারের run (ডেস্কটপ, uv run python mapie_check.py):
mapie 1.6.0 | scikit-learn 1.8.0
interval shape: (500, 2, 1) | half-width: 7.09
coverage: 0.904
sets shape: (1000, 4) | coverage: 0.91 | size counts: [0, 669, 220, 90, 21]
অর্ধেক প্রস্থ ৭.০৯ আর coverage ০.৯০৪, ঠিক অংশ ২-এর প্রথম ভাগের হাতে-লেখা ফলের সমান; সেটের আকারের গণনা (০টি খালি, ৬৬৯, ২২০, ৯০, ২১) অংশ ৫-এর সঙ্গে হুবহু মেলে। চার দশমিকে দেখলে MAPIE-র q̂ ৭.০৮৬২, আমাদের ৪৫১তম score-এর সমান। Library সুবিধা দেয় (CQR, jackknife+, CV+, APS, কয়েকটি α একসঙ্গে), কিন্তু মূল নিয়মটি নিজে হাতে একবার মিলিয়ে নেওয়াই যাচাইয়ের সেরা পথ।
আরও গভীরে: তত্ত্বের পূর্ণ রূপ Vovk, Gammerman আর Shafer-এর বই Algorithmic Learning in a Random World (২০০৫; দ্বিতীয় সংস্করণ ২০২২)। আধুনিক ML-এ জনপ্রিয় হওয়ার পেছনে Lei ও সহকর্মীদের ২০১৮ সালের JASA প্রবন্ধ আর Angelopoulos ও Bates-এর “A Gentle Introduction to Conformal Prediction and Distribution-Free Uncertainty Quantification” (arXiv ২০২১) বড় ভূমিকা রাখে বলে ধরা হয়। Conformal risk control (Angelopoulos ও সহকর্মীরা) coverage-এর বদলে যেকোনো সীমিত loss-এর প্রত্যাশা নিয়ন্ত্রণ করে, যেমন ভুল-বাদ পড়া শ্রেণির অনুপাত।
পরীক্ষা ও ইন্টারভিউতে: (১) n = ১৯, α = ০.১: কততম score? ⌈২০ × ০.৯⌉ = ১৮তম ছোট। (২) Conformal কোন শর্তে কাজ করে? Calibration আর নতুন ডেটা exchangeable; model-এর কোনো শর্ত নেই। (৩) ৯০% coverage মানে কি প্রতিটি ক্রেতার জন্য ৯০%? না, marginal: গড়ে, সব x আর calibration ভাগ মিলিয়ে। (৪) CQR-এর score? max(q̂lo − y, y − q̂hi); q̂lo = ১০, q̂hi = ২০, y = ২৩ হলে ৩. (৫) LAC-এ q̂ = ০.৭ হলে কোন শ্রেণি সেটে? যাদের p̂ ≥ ০.৩.
৮ · AI-এর যুগে — conformal কোড যাচাই
“আমার model-এ ৯০% prediction interval দাও” বললে AI assistant প্রায়ই চলনসই কোড দেয়, কিন্তু এই বিষয়ের ভুলগুলো চুপচাপ থাকে। নিচের ভুলগুলো বারবার দেখা যায়।
| AI প্রায়ই যা করে | কেন সমস্যা | কীভাবে ধরবেন |
|---|---|---|
np.quantile(scores, 0.9) নেয় | n + ১-এর সংশোধন বাদ; ছোট n-এ coverage লক্ষ্যের নিচে | k = ⌈(n + ১)(১ − α)⌉, তারপর সাজানো score-এর k-তম; ছোট উদাহরণে হাতে মেলান |
| Training ডেটার residual দিয়ে calibrate করে | মুখস্থ করা ডেটার ভুল ছোট; পরিসর সরু, প্রতিশ্রুতি নেই | Calibration ভাগ আলাদা, model কখনো দেখেনি |
পুরোনো MAPIE API লেখে (MapieRegressor, alpha=) | MAPIE 1.x-এ নাম আর অর্থ বদলেছে; confidence_level = ১ − α | নিজের version-এর docs; ফলকে হাতে-লেখা q̂-এর সঙ্গে মেলান |
| “প্রতিটি অর্ডারের জন্য ৯০% নিশ্চিত” লেখে | নিশ্চয়তা marginal; কিছু দলে অনেক কম হতে পারে | দলভিত্তিক coverage মাপুন; দরকারে Mondrian বা CQR |
| সময়ের ডেটা এলোমেলো ভাগ করে calibrate করে | ভবিষ্যৎ calibration-এ ঢোকে; drift-এ coverage চুপচাপ পড়ে | সময় ধরে ভাগ; মাসে মাসে coverage নজরে রাখুন, rolling recalibration |
| Calibration ভাগে α বা model বাছে, তারপর একই ভাগে coverage দেখায় | Calibration-এর তথ্য দুবার ব্যবহার; রিপোর্ট করা coverage আশাবাদী | বাছাই আলাদা validation-এ; চূড়ান্ত coverage তালা দেওয়া test-এ |
AI-কে শুধু কোড নয়, অনুমান আর যাচাইও চাইতে বলুন:
AI-এর দেওয়া conformal কোড হাতে পেলে — যাচাইয়ের চেকলিস্ট
ভাবনার প্রশ্ন
প্রতিটি প্রশ্ন নিয়ে নিজে কিছুক্ষণ ভাবুন — তারপর “→ উত্তর” চাপুন।
প্র ০১Conformal prediction-এর ধারণা নব্বইয়ের দশকের শেষে জন্মেছিল, অথচ ML-এর মূলধারায় এসেছে প্রায় দুই দশক পরে। এই দেরির কারণ কী হতে পারে, আর কী বদলালো?
Conformal prediction-এর শিকড় লন্ডনের Royal Holloway-তে Alexander Gammerman, Vladimir Vovk আর তাঁদের সহকর্মীদের কাজে। ১৯৯৮ সালে Gammerman, Vovk আর Vladimir Vapnik-এর “Learning by Transduction” প্রবন্ধে প্রাথমিক রূপ দেখা যায়, আর ২০০৫ সালে Vovk, Gammerman ও Glenn Shafer-এর বই Algorithmic Learning in a Random World তত্ত্বটিকে পূর্ণ রূপ দেয়। মূল ধারণা তখনই ছিল: exchangeability থেকে ক্রমের যুক্তি দিয়ে সসীম নমুনায় নিশ্চয়তা।
দেরির একটি বড় কারণ সম্ভবত খরচ। প্রথম রূপ, যাকে এখন full conformal বলে, প্রতিটি নতুন উদাহরণ আর প্রতিটি সম্ভাব্য উত্তরের জন্য model আবার শেখায়। SVM বা ছোট model-এ তা চলে, বড় model-এ নয়। ২০০২ সালে Papadopoulos ও সহকর্মীরা inductive বা split রূপ প্রস্তাব করেন, যা একবার fit করে; কিন্তু সেটিও বহু বছর একটি বিশেষজ্ঞ সম্প্রদায়ের মধ্যে ছিল।
দ্বিতীয় কারণ সংস্কৃতি। ২০১০-এর দশকে ML-এর মনোযোগ ছিল accuracy-তে, benchmark-এর একটি সংখ্যায়। অনিশ্চয়তার প্রশ্ন উঠত মূলত Bayesian পরিসরে। পরিসংখ্যানে Jing Lei, Larry Wasserman, Ryan Tibshirani ও সহকর্মীদের কাজ (২০১৮ সালের JASA প্রবন্ধ) পদ্ধতিটিকে regression-এর ভাষায় পরিষ্কার করে, আর Emmanuel Candès-এর দলের CQR, APS, weighted conformal এবং ACI বাস্তব সমস্যার সঙ্গে জোড়ে। Angelopoulos আর Bates-এর সহজ ভূমিকা (২০২১) আর MAPIE-র মতো library ব্যবহারকারীর কাছে পথ খুলে দেয়।
তৃতীয় কারণ চাহিদা। চিকিৎসা, ঋণ আর স্বয়ংক্রিয় সিদ্ধান্তে ML যত ঢুকেছে, “model কতটা নিশ্চিত” প্রশ্নটি তত জরুরি হয়েছে, আর বড় neural network-এর softmax সম্ভাবনা প্রায়ই অতি-আত্মবিশ্বাসী বলে দেখা গেছে। তখন এমন পদ্ধতির দরকার পড়ে যা model-এর ভেতর না জেনেই কাজ করে। কোন কারণটি কতটা ভূমিকা রেখেছে, তা নিয়ে মত ভিন্ন হতে পারে; ইতিহাসটি এক কারণের নয়।
মূল উপলব্ধি: একটি ভালো ধারণা ছড়াতে দরকার সস্তা একটি রূপ (split), পরিচিত ভাষায় ব্যাখ্যা, সহজ টুল, আর এমন একটি সমস্যা যা সবাই অনুভব করছে।
প্র ০২“Model-নির্ভরতা ছাড়া প্রতিটি x-এর জন্য ৯০% পরিসর” কেন সাধারণভাবে অসম্ভব? এই সীমা মেনে নিয়ে একজন practitioner কী করতে পারেন?
Conditional coverage মানে প্রতিটি নির্দিষ্ট x-এর জন্য P(Y ∈ C(x) ∣ X = x) ≥ ১ − α. ধরুন x একটি অবিচ্ছিন্ন সংখ্যা, যেমন দূরত্ব। ঠিক ৩৭.২ km-এর অর্ডার training-এ হয়তো একটিও নেই। সেই বিন্দুতে y-এর বণ্টন সম্পর্কে ডেটা থেকে কিছু জানতে হলে ধরে নিতে হয় যে কাছাকাছি x-এর বণ্টন মসৃণভাবে বদলায়; এটি একটি model-অনুমান। কোনো অনুমান না নিলে বণ্টনটি ৩৭.২ km-এ হঠাৎ অদ্ভুত হতে পারে, আর তা ধরা অসম্ভব।
Vladimir Vovk ২০১২ সালে inductive conformal-এর conditional বৈধতা নিয়ে লেখেন, Jing Lei আর Larry Wasserman ২০১৪ সালে দেখান যে বণ্টন-মুক্ত পদ্ধতিতে সসীম নমুনায় সঠিক conditional coverage চাইলে অবিচ্ছিন্ন x-এ পরিসর সাধারণত অসীম দৈর্ঘ্যের হতে হয়। Rina Foygel Barber ও সহকর্মীরা ২০২১ সালে এই সীমা আরও স্পষ্ট করেন, আর দেখান যে একটি মাঝামাঝি পথ আছে: আগে থেকে ঠিক করা, যথেষ্ট বড় দলের ওপর coverage চাওয়া যায়।
তাই practitioner-এর কাজ তিন স্তরে। প্রথমত, score-এর নকশা: CQR বা residual-কে আনুমানিক ছড়ানো দিয়ে ভাগ করা score (normalised score) প্রস্থকে ঝুঁকির সঙ্গে বদলায়, ফলে conditional coverage-এর কাছাকাছি যায়, যদিও নিশ্চয়তা দেয় না। দ্বিতীয়ত, দলভিত্তিক calibration: যে দলগুলো ব্যবসা বা ন্যায্যতার দিক থেকে গুরুত্বপূর্ণ (এলাকা, পণ্যের ধরন, শ্রেণি), তাদের জন্য Mondrian ভাগ, যতক্ষণ প্রতিটি দলে যথেষ্ট calibration উদাহরণ থাকে। তৃতীয়ত, মাপা আর রিপোর্ট করা: দলে দলে coverage, তার নমুনা-আকারসহ।
ন্যায্যতার প্রশ্নও এখানে আসে। Marginal ৯০% দেখতে ভালো, কিন্তু সংখ্যালঘু একটি দলের coverage যদি ৭০% হয়, ক্ষতির বোঝা সেই দলের ওপর পড়ে। কোন দলে নিশ্চয়তা চাই, তা প্রযুক্তিগত নয়, নীতিগত সিদ্ধান্ত; সেটি পর্ব ৬০ (ML-এ ন্যায্যতা — pre-, in- আর post-processing প্রতিকার)-এর আলোচনার সঙ্গে জড়িয়ে।
মূল উপলব্ধি: প্রতিটি x-এর নিশ্চয়তা অনুমান ছাড়া পাওয়া যায় না; কোন দলে নিশ্চয়তা চাই তা আগে ঠিক করুন, আর বাকিটা মাপুন।
প্র ০৩Gaussian process বা Bayesian regression-এর পরিসর, quantile regression, bootstrap আর conformal — চারটির মধ্যে কোনটি কখন বেছে নেবেন? এ নিয়ে পরিসংখ্যানের সম্প্রদায়ে কী মতভেদ আছে?
চারটি পদ্ধতি চারটি আলাদা প্রশ্নের উত্তর দেয়। Bayesian পরিসর (পর্ব ৪৫, পর্ব ৪৬) বলে: model আর prior সত্য হলে, ডেটা দেখার পর y-এর বিশ্বাসের বণ্টন কী। এটি প্রতিটি x-এর জন্য conditional উত্তর দেয়, ডেটার বাইরে গেলে স্বাভাবিকভাবে চওড়া হয়, আর prior জ্ঞান ঢোকানো যায়। দুর্বলতা: model ভুল হলে (ভুল kernel, ভুল noise) পরিসর আত্মবিশ্বাসের সঙ্গে ভুল।
Quantile regression (পর্ব ২৪) সরাসরি শর্তসাপেক্ষ quantile শেখে, ছড়ানো বদলালে খাপ খায়, কিন্তু coverage আসে শুধু model ঠিক আর নমুনা বড় হলে। Bootstrap (পর্ব ২১) মূলত অনুমানের অনিশ্চয়তা মাপে, যেমন গড় বা coefficient-এর; একটি নতুন উদাহরণের পরিসর পেতে তার সঙ্গে noise-এর একটি model জুড়তে হয়। Conformal কোনো model-অনুমান ছাড়াই marginal coverage দেয়, কিন্তু শুধু marginal, আর exchangeability ধরে।
বাস্তবে এগুলো প্রতিদ্বন্দ্বী নয়, সঙ্গী। CQR quantile regression-কে conformal দিয়ে মোড়ে; Bayesian model-এর predictive বণ্টনকেও score বানিয়ে conformalize করা যায়। তখন model ঠিক হলে প্রায় conditional coverage আর সরু পরিসর পাওয়া যায়, আর model ভুল হলেও marginal নিশ্চয়তা বাঁচে।
মতভেদ আছে দর্শনে। Bayesian ঘরানার অনেকে বলেন, marginal coverage সিদ্ধান্তের জন্য যথেষ্ট নয়: একজন রোগীর জন্য সিদ্ধান্ত নিতে তাঁর x-এর ওপর শর্তসাপেক্ষ বিশ্বাস দরকার। Frequentist আর বণ্টন-মুক্ত ঘরানার অনেকে বলেন, ভুল model-এর conditional উত্তরের চেয়ে সৎ marginal নিশ্চয়তা ভালো, বিশেষত যখন model একটি জটিল black box. দুই পক্ষই আংশিক ঠিক; কোনটি বেশি জরুরি তা নির্ভর করে ডেটার পরিমাণ, model-এ আস্থা আর ভুলের খরচের ওপর।
মূল উপলব্ধি: Model-এ আস্থা থাকলে Bayesian বা quantile, না থাকলে conformal; আর প্রায়ই সেরা পথ দুটিকে মেলানো।
প্র ০৪বাজারঘর ডেলিভারির পরিসর দেখাতে চায় ক্রেতার অ্যাপে। Exchangeability-র শর্ত বাস্তবে কোথায় কোথায় ভাঙতে পারে, আর একটি টেকসই নকশা কেমন হবে?
Exchangeability বলে: calibration-এর অর্ডার আর নতুন অর্ডার একই উৎস থেকে, ক্রম বদলালে কিছু বদলায় না। বাস্তবে অন্তত চার জায়গায় এটি ভাঙে। (১) মৌসুম: বর্ষা, ঈদ বা হরতালে ডেলিভারির সময়ের বণ্টন বদলায়; পুরোনো মাসের ভুল নতুন মাসের প্রতিনিধি থাকে না, যা অংশ ৬-এর run-এ coverage ৬৭%-এ নামিয়েছে। (২) নতুন এলাকা: বাজারঘর নতুন জেলায় গেলে সেই জেলার কোনো অর্ডার calibration-এ নেই। (৩) Feedback: পরিসর দেখে ক্রেতা সময়ে বাড়ি থাকেন বা কুরিয়ার তাড়াহুড়া করেন, তাতে আসল সময়ই বদলায়। (৪) Label-এর দেরি: কোনো অর্ডার এখনো পৌঁছায়নি, আর শুধু দ্রুত পৌঁছানো অর্ডার দিয়ে calibrate করলে score কম দেখায় (censoring, পর্ব ৫৫-এর বিষয়)।
টেকসই নকশার কয়েকটি অংশ। প্রথমত, ভাগ সময় ধরে: train পুরোনো মাসে, calibration সাম্প্রতিক একটি জানালায়, test তার পরে। দ্বিতীয়ত, rolling recalibration: প্রতিদিন বা প্রতি সপ্তাহে শেষ কয়েক সপ্তাহের পৌঁছানো অর্ডার দিয়ে q̂ হালনাগাদ; জানালা ছোট হলে দ্রুত খাপ খায় কিন্তু q̂ বেশি নড়ে, বড় হলে স্থির কিন্তু ধীর। তৃতীয়ত, ACI-এর মতো অনলাইন সমন্বয়, যা ভুল বাড়লে নিজেই পরিসর চওড়া করে। চতুর্থত, দলভিত্তিক calibration: এলাকা আর মৌসুম ধরে Mondrian ভাগ, যতক্ষণ দলে যথেষ্ট অর্ডার থাকে; নতুন জেলায় প্রথম কয়েক সপ্তাহ বেশি চওড়া, রক্ষণশীল পরিসর।
নজরদারি এই নকশার কেন্দ্রে। প্রতিদিন দলে দলে আসল coverage আর গড় প্রস্থ একটি dashboard-এ থাকুক, আর coverage একটি সীমার নিচে নামলে সতর্কবার্তা আসুক। ক্রেতাকে দেখানো ভাষাও সাবধানে বাছতে হয়: “সাধারণত ১৮ থেকে ২৬ ঘণ্টার মধ্যে পৌঁছায়” সৎ, “৯০% নিশ্চিত আপনার পার্সেল” প্রতিশ্রুতির ভুল ব্যাখ্যা।
মূল উপলব্ধি: Conformal-এর নিশ্চয়তা ল্যাবে প্রমাণিত, বাস্তবে নজরদারি দিয়ে রক্ষা করতে হয়; সময়, এলাকা আর feedback তিনটিই exchangeability ভাঙে।
প্র ০৫Prediction set-এর আকার কি মানুষ আর যন্ত্রের মধ্যে কাজ ভাগ করার একটি উপায় হতে পারে? কোথায় এর সীমা?
অংশ ৫-এর ফেরত-দলের উদাহরণে সেটের আকার একটি স্বাভাবিক রাউটিং নিয়ম দেয়: আকার ১ হলে স্বয়ংক্রিয়ভাবে ঠিক বিভাগে, আকার ২ হলে দুটি বিভাগের সাধারণ সারিতে, ৩ বা ৪ হলে একজন কর্মীর কাছে। চিকিৎসা-ইমেজিং বা নথি-শ্রেণিকরণের গবেষণায় এমন প্রস্তাব এসেছে যে set-valued উত্তর মানুষকে বিকল্পগুলো দেখায় আর ভুল এক-উত্তরের ওপর অন্ধ আস্থা কমায়। কিছু পরীক্ষায় দেখা গেছে, সেট দেখালে মানুষের সিদ্ধান্তের মান বাড়তে পারে, যদিও ফল কাজ আর উপস্থাপনার ওপর নির্ভর করে; এ বিষয়ে প্রমাণ এখনো সীমিত, তাই সাধারণীকরণ করা উচিত নয়।
সীমা কয়েকটি। প্রথমত, coverage marginal: আকার ১-এর সেটগুলো একসঙ্গে ৯০%-এর বেশি ঠিক হতে পারে, আর বড় সেটগুলো কম; “আকার ১ মানে নিশ্চিত” ধরে নিলে বিরল শ্রেণির ভুল চোখ এড়ায়, যেমন LAC-এ wrong_item-এর ৪২% coverage. দ্বিতীয়ত, α বাছাই একটি ব্যবসার সিদ্ধান্ত: α ছোট করলে সেট বড় হয়, কর্মীর কাজ বাড়ে; বড় করলে স্বয়ংক্রিয়তা বাড়ে, ভুলও বাড়ে। এই বিনিময় খরচের হিসাবে ঠিক করতে হয়, calibration ডেটা দেখে টেনে নয়। তৃতীয়ত, খালি সেট: LAC-এ সব শ্রেণির সম্ভাবনা সীমার নিচে হলে সেট খালি আসতে পারে; সেটি “model কিছুই জানে না” সংকেত, আর তার জন্য আলাদা নিয়ম রাখা ভালো।
বড় ভাষা-model-এর যুগে একই ভাবনা নতুন রূপ নিচ্ছে: একাধিক উত্তর তৈরি করে conformal ধাঁচে এমন সেট রাখা, যার মধ্যে অন্তত একটি গ্রহণযোগ্য উত্তর থাকার নিশ্চয়তা আছে, বা conformal risk control দিয়ে ভুল-তথ্যের হার সীমিত রাখা। এগুলো সক্রিয় গবেষণা; প্রতিশ্রুতিগুলো এখানেও exchangeability আর “গ্রহণযোগ্য” কে ঠিক করছে তার ওপর নির্ভর করে।
মূল উপলব্ধি: সেটের আকার অনিশ্চয়তার কাজের সংকেত, কিন্তু নিশ্চয়তা marginal; রাউটিং-এর নিয়ম দলে দলে coverage মেপে আর খরচ হিসাব করে বানাতে হয়।
অনুশীলন
হিসাবগুলো খাতায় করুন, তারপর উত্তর মেলান। চাইলে পাতার ব্লকগুলোতে সংখ্যা বদলে যাচাই করুন।
-
পূর্ণ numerical: ১৯টি calibration score (ঘণ্টা, সাজানো): ০.৩, ০.৫, ০.৬, ০.৮, ০.৯, ১.১, ১.২, ১.৪, ১.৫, ১.৭, ১.৯, ২.০, ২.২, ২.৬, ২.৯, ৩.১, ৩.৫, ৪.২, ৬.০. (ক) α = ০.১, ০.২ আর ০.০৫-এর জন্য k আর q̂ বের করুন। (খ) নতুন অর্ডারের ŷ = ১৬ হলে α = ০.১-এর পরিসর কত? (গ) CQR-এ q̂lo = ১০, q̂hi = ২০; y = ২৩ আর y = ১৪ হলে score কত? (ঘ) একটি classification-এর calibration উদাহরণে আসল শ্রেণির p̂ = ০.২; LAC score কত?
(ক) n = ১৯, n + ১ = ২০. α = ০.১: ২০ × ০.৯ = ১৮ → k = ১৮, q̂ = ৪.২. α = ০.২: ২০ × ০.৮ = ১৬ → q̂ = ৩.১. α = ০.০৫: ২০ × ০.৯৫ = ১৯ → k = ১৯, সবচেয়ে বড় score, q̂ = ৬.০ (একটি score কম থাকলে এটি অসীম হতো)। (খ) [১৬ − ৪.২, ১৬ + ৪.২] = [১১.৮, ২০.২] ঘণ্টা। (গ) y = ২৩: max(১০ − ২৩, ২৩ − ২০) = max(−১৩, ৩) = ৩, অর্থাৎ ব্যান্ডের ৩ ঘণ্টা বাইরে। y = ১৪: max(−৪, −৬) = −৪, ভেতরে, নিকটতম সীমা থেকে ৪ ঘণ্টা দূরে। (ঘ) ১ − ০.২ = ০.৮.
-
সমালোচনা ও নকশা: একজন বিশ্লেষক লিখেছেন: “দুই বছরের অর্ডার এলোমেলো করে ৮০% train আর ২০% calibration করেছি। Calibration ভাগে তিনটি model-এর মধ্যে যার পরিসর সবচেয়ে সরু, সেটি বেছেছি, আর একই ভাগে coverage ৯০.৩% পেয়েছি। তারপর পুরো ডেটায় model আবার fit করে অ্যাপে লিখেছি: ‘আপনার পার্সেল ৯০% নিশ্চিতভাবে এই সময়ের মধ্যে আসবে।’” কী কী সমস্যা, আর আপনি কীভাবে নকশা করবেন?
সমস্যা পাঁচটি। (১) সময়ের ডেটা এলোমেলো করে ভাগ: ভবিষ্যতের অর্ডার calibration-এ, তাই মৌসুম আর drift-এর প্রভাব লুকিয়েছে। (২) Calibration ভাগে model বাছাই, আর একই ভাগে coverage: তথ্য দুবার ব্যবহার, রিপোর্ট আশাবাদী। (৩) পুরো ডেটায় আবার fit: নতুন model-এর score আর পুরোনো q̂ মেলে না, প্রমাণ আর খাটে না। (৪) “আপনার পার্সেল ৯০% নিশ্চিত”: নিশ্চয়তা marginal, প্রতিটি ক্রেতার নয়। (৫) দলভিত্তিক coverage নেই।
নকশা: সময় ধরে train → validation (model বাছাই) → calibration (সাম্প্রতিক কয়েক সপ্তাহ) → test (তালা দেওয়া, তার পরের সময়)। Heteroscedasticity থাকলে CQR. এলাকা আর মৌসুম ধরে coverage, দরকারে Mondrian. প্রতি সপ্তাহে rolling recalibration আর coverage-এর নজরদারি। অ্যাপের ভাষা: “সাধারণত … থেকে … ঘণ্টার মধ্যে পৌঁছায়।”
-
আউটপুট অনুমান করুন: চালানোর আগে পাঁচটি লাইন লিখুন।
import numpy as np s = np.array([2.1, 0.4, 3.3, 1.0, 0.7, 2.8, 1.6, 0.2, 4.5]) alpha = 0.2 k = int(np.ceil((len(s) + 1) * (1 - alpha))) print(k, np.sort(s)[k - 1]) print(np.quantile(s, 1 - alpha)) print(np.quantile(s, k / len(s), method="higher")) print(np.quantile(s, k / len(s), method="inverted_cdf")) p = np.array([0.55, 0.25, 0.15, 0.05]) print(np.flatnonzero(p >= 1 - 0.8))সত্যিকারের run (ডেস্কটপ, NumPy 2.5.4):
8 3.3 3.0 4.5 3.3 [0 1]সাজানো s = ০.২, ০.৪, ০.৭, ১.০, ১.৬, ২.১, ২.৮, ৩.৩, ৪.৫; k = ⌈১০ × ০.৮⌉ = ৮, ৮ম মান ৩.৩. সাধারণ
np.quantile(s, 0.8)অবস্থান ০.৮ × ৮ = ৬.৪-এ interpolation করে ২.৮ আর ৩.৩-এর মাঝে ৩.০ দেয়: ছোট, তাই coverage কম।method="higher"আর স্তর k/n = ৮/৯ অবস্থান ৭.১১ থেকে ওপরে গিয়ে ৯ম মান ৪.৫ দেয়: দরকারের চেয়ে বড়।method="inverted_cdf"আর স্তর k/n ঠিক k-তম মান দেয়। শেষ লাইন: সীমা ১ − ০.৮ = ০.২, তাই ০.৫৫ আর ০.২৫-এর শ্রেণি, সূচক ০ আর ১. শিক্ষা: “quantile নাও” বললে সূচক নিজে হাতে মেলান। -
কোডিং: একটি function
aci(scores, alpha=0.1, gamma=0.01)লিখুন: স্কোরগুলো সময়ের ক্রমে আসে; প্রতিটি ধাপে আগের ২০০টি score থেকে ১ − αt স্তরের k-তম মান নিয়ে নতুন score ঢাকা পড়ল কি না দেখুন, তারপর αt+1 = αt + γ(α − errt) দিয়ে হালনাগাদ করুন। অংশ ৬-এরmonthly()-এর score-এ মাস ৬ থেকে ৮-এর coverage স্থির পদ্ধতির সঙ্গে তুলনা করুন।import numpy as np from sklearn.linear_model import LinearRegression from bazar_conformal import monthly def aci(scores, alpha=0.1, gamma=0.01, window=200): a_t, hits = alpha, [] for t in range(window, len(scores)): past = np.sort(scores[t - window:t]) # শেষ ২০০টি score k = int(np.ceil((window + 1) * (1 - a_t))) q = np.inf if k > window else past[max(k, 1) - 1] err = int(scores[t] > q) hits.append(1 - err) a_t += gamma * (alpha - err) # ভুল হলে alpha কমে return np.array(hits) df = monthly() old = df[df.month <= 3] model = LinearRegression().fit(old[["km", "rain"]], old.hours) s = np.abs(df.hours - model.predict(df[["km", "rain"]])).to_numpy() month = df.month.to_numpy() hits = aci(s[month >= 4]) # মাস ৪-এর ৩০০টির প্রথম ২০০টি শুধু ইতিহাস m_aci = month[month >= 4][200:] q_static = np.sort(s[month == 4])[int(np.ceil(301 * 0.9)) - 1] for m in (6, 7, 8): print(m, "ACI:", round(hits[m_aci == m].mean(), 3), "static:", round(np.mean(s[month == m] <= q_static), 3))সত্যিকারের run (ডেস্কটপ, একই ডেটা):
6 ACI: 0.883 static: 0.693 7 ACI: 0.907 static: 0.683 8 ACI: 0.9 static: 0.67বর্ষার তিন মাসে স্থির q̂-এর coverage ৬৭–৬৯%, আর ACI-এর ৮৮.৩%, ৯০.৭% আর ৯০%. দুটি জিনিস একসঙ্গে কাজ করছে: শেষ ২০০টি score-এর চলমান জানালা প্রতিটি নতুন অর্ডারের পর হালনাগাদ হয় (মাসে একবার নয়), আর পরপর ভুল হলে αt কমে গিয়ে পরিসর আরও চওড়া হয়। মাস ৬-এর শুরুতে ACI-ও কিছুদিন ভুল করে, তাই সেই মাসে ৯০%-এর একটু নিচে। γ বড় করলে দ্রুত খাপ খায় কিন্তু পরিসর বেশি কাঁপে; এটি একটি স্থানীয় run, অন্য ডেটায় ফল আলাদা হবে।
নিজেকে যাচাই করুন
ভুল হলে কারণসহ ব্যাখ্যা পাবেন, আবার চেষ্টাও করতে পারবেন।
ক্রমSplit conformal দিয়ে একটি regression পরিসর বানানোর ধাপগুলো সঠিক ক্রমে সাজান (▲▼ চেপে সরান)
- ডেটাকে train আর calibration ভাগে আলাদা করা
- শুধু train ভাগ দিয়ে model শেখানো
- Calibration-এর প্রতিটি উদাহরণে score ∣y − ŷ∣ হিসাব করা
- Score সাজিয়ে ⌈(n + ১)(১ − α)⌉-তম মান q̂ নেওয়া
- নতুন উদাহরণের জন্য [ŷ − q̂, ŷ + q̂] দেওয়া
Split conformal-এ ১৯টি calibration score আছে, লক্ষ্য ৯০% (α = ০.১)। q̂ হিসেবে সাজানো score-এর কততম মান নিতে হবে?
- ১৭তম
- ১৯তম
- ১৮তম
- ৯০তম percentile, interpolation করে
একটি conformal পদ্ধতি exchangeable ডেটায় “৯০% coverage” দেয়। কথাটির সঠিক অর্থ কোনটি?
- প্রতিটি ক্রেতার জন্য আলাদাভাবে ৯০% সম্ভাবনা
- বহু নতুন উদাহরণ আর calibration ভাগ মিলিয়ে গড়ে অন্তত ৯০% উদাহরণ পরিসরের ভেতরে
- প্রতিটি test set-এ ঠিক ৯০%
- Model-এর accuracy ৯০%
চার শ্রেণির একটি classifier-এ LAC conformal-এর q̂ = ০.৭. একটি উদাহরণের সম্ভাবনা (০.৫০, ০.৩৫, ০.১০, ০.০৫)। Prediction set-এ কয়টি শ্রেণি থাকবে?
- ১টি
- ৩টি
- ০টি
- ২টি
Conformalized quantile regression-এ একটি calibration উদাহরণের q̂lo = ১০, q̂hi = ২০ আর আসল y = ২৩. তার score কত?
- ৩
- −১৩
- ১৩
- ০
একটি ডেলিভারি model মাস ১–৪-এর ডেটায় calibrate করা। বর্ষার মাসে ডেলিভারির সময়ের ছড়ানো অনেক বেড়েছে। একই q̂ রাখলে কী আশা করা উচিত?
- Coverage ৯০% থাকবে, কারণ conformal model-নির্ভর নয়
- Coverage ৯০%-এর বেশি হবে
- Coverage লক্ষ্যের নিচে নামতে পারে, আর কোনো error ছাড়াই
- পরিসর নিজে থেকেই চওড়া হবে
একটি অসম ডেটায় (একটি শ্রেণি মাত্র ৬%) সাধারণ LAC সেট মোট ৯০% coverage দেয়, কিন্তু বিরল শ্রেণিতে মাত্র ৪২%. Mondrian (শ্রেণিভিত্তিক) conformal কী করে?
- বিরল শ্রেণিকে বাদ দিয়ে বাকিদের coverage বাড়ায়
- প্রতিটি শ্রেণির জন্য আলাদা q̂ নিয়ে প্রতিটি শ্রেণিতে গড়ে অন্তত ৯০% coverage দেয়
- Model-কে class weight দিয়ে আবার শেখায়
- সব সেটের আকার ১-এ নামিয়ে আনে
শব্দকোষ
লেখার মধ্যে ডটেড দাগ দেওয়া শব্দে মাউস রাখুন বা চাপুন — অর্থ দেখাবে। এই পর্বের সব নতুন শব্দ এখানে একসাথে:
মনে রাখুন
- প্রতিশ্রুতি: exchangeable ডেটায় P(Yনতুন ∈ C(Xনতুন)) ≥ ১ − α, model যেমনই হোক; খারাপ model মানে চওড়া পরিসর, ভাঙা প্রতিশ্রুতি নয়।
- Split conformal: আলাদা calibration ভাগে score, k = ⌈(n + ১)(১ − α)⌉, q̂ = k-তম ছোট score, পরিসর ŷ ± q̂. k > n হলে পরিসর অসীম।
- Marginal, conditional নয়: গড়ে ১ − α; দলে দলে অনেক কম হতে পারে। একটি ভাগের coverage-ও ওঠানামা করে (Beta(k, n + ১ − k)).
- ভালো score, ভালো পরিসর: CQR-এর score max(q̂lo − y, y − q̂hi) প্রস্থকে ঝুঁকির সঙ্গে বদলায়; classification-এ LAC (১ − p̂) বা APS দিয়ে সেট, আর Mondrian দিয়ে প্রতিটি শ্রেণির নিশ্চয়তা।
- সময় নিয়ম ভাঙে: drift-এ coverage চুপচাপ পড়ে; সময় ধরে ভাগ, rolling recalibration বা ACI, আর দলে দলে coverage-এর নজরদারি।
আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ
- পর্ব ৫৯ · Distribution shift — covariate, label আর concept shift ধরা ও সামলানোপরবর্তী পর্বPSI, domain classifier, importance weight আর BBSE দিয়ে shift ধরা ও সামলানো।
- মেশিন লার্নিং · কোর্স হোম৭৭টি পর্ব১৪টি মডিউলের পুরো রোডম্যাপ; মডিউল ১১-এর বাকি পর্বগুলো এখান থেকে খুলবেন।
- পর্ব ২৪ · Robust আর quantile regression — outlier আর অনুমানের পরিসরআগের ভিত্তিPinball loss, quantile regression আর held-out ডেটায় coverage মাপা।
- পর্ব ২৬ · Probability calibration — Platt, isotonic আর reliability diagramআগের ভিত্তিCalibration set আর সম্ভাবনার নির্ভরযোগ্যতা: prediction set-এর আগের ধাপ।
- পর্ব ৪৬ · Gaussian process — kernel দিয়ে অনিশ্চয়তাসহ অনুমানআগের ভিত্তিModel-নির্ভর Bayesian পরিসর, conformal-এর সঙ্গে তুলনার জন্য।
- পর্ব ৫২ · ML দিয়ে forecasting — lag feature, backtesting আর অনেক series একসঙ্গেআগের ভিত্তিসময় ধরে ভাগ আর backtest: exchangeability ভাঙলে কাজের পথ।
- AI-এর ভিত্তি · পর্ব ৫৬ · Train, validation আর testআগের ভিত্তিডেটা ভাগ আর leakage-এর নিয়ম, যা calibration ভাগেও খাটে।
- AI-এর ভিত্তি · পর্ব ৭২ · দায়িত্বশীল AI-এর অভ্যাসপাশের ট্র্যাকদলভিত্তিক মাপ আর deploy-এর পরের নজরদারি।
- System Designপাশের ট্র্যাকনজরদারি আর সতর্কবার্তার নকশা, যা rolling recalibration-এর জন্য লাগে।