এই পর্বে যা শিখবেন
- Model বাছাই, overfitting, imbalance আর calibration-এর প্রশ্নে প্রমাণ আর সংখ্যাসহ উত্তর দেওয়া
- ব্যাখ্যা, অনিশ্চয়তা, ন্যায্যতা আর drift-এর প্রশ্নে সীমা আর trade-off বলা
- Causal আর predictive প্রশ্ন আলাদা করা, আর A/B test-এর পরিচিত ফাঁদ চেনা
- ৪৫ মিনিটে একটি পূর্ণ ML system নকশা করা, rubric জেনে, ফলো-আপ সামলে
- নিজের প্রকল্পের ঘটনা STAR কাঠামোয়, দুর্বল সংখ্যাসহ সৎভাবে বলা
এই পাতা সম্পর্কে: প্রশ্নগুলো কোনো নির্দিষ্ট প্রতিষ্ঠান, পরীক্ষা বা নিয়োগ থেকে নেওয়া নয়; data scientist বা ML engineer-এর আলাপে এ ধরনের প্রশ্ন প্রায়ই আসে। বাজারঘর কাল্পনিক দোকান; সব ডেটা seed দেওয়া কোডে বানানো, আর mock-এর সংখ্যাগুলো ধরে নেওয়া। ব্লকের আউটপুট সত্যিই চালিয়ে নেওয়া (ব্রাউজারের Python; NumPy 2.4.6, pandas 3.0.2, scikit-learn 1.8.0); প্রথমবার scikit-learn নামতে প্রায় ১০ সেকেন্ড লাগে। মৌলিক প্রশ্ন (base rate, leakage-এর প্রথম রূপ, precision আর recall) AI-এর ভিত্তি কোর্সের পর্ব ৭৯ · AI-এর ভিত্তির ইন্টারভিউ আর তার MCQ, numerical ও লিখিত-মৌখিক পাতায় আছে; এখানে সেগুলো আবার নেই। এই মডিউলের পাশের পাতা: পর্ব ৭৩ (Numerical সমস্যার অনুশীলন), পর্ব ৭৪ (MCQ প্রশ্নব্যাংক), পর্ব ৭৫ (লিখিত ও মৌখিক প্রশ্ন) আর পর্ব ৭৬ (ML coding ইন্টারভিউ)।
অভিজ্ঞ ডাক্তারকে কেউ জিজ্ঞেস করেন না “জ্বর কাকে বলে”; জিজ্ঞেস করা হয়, “রিপোর্ট ভালো, অথচ রোগী ভালো নেই; কোন পরীক্ষা আগে দেবেন?” উন্নত ML ইন্টারভিউও তেমন: দেখা হয় আপনি একটি সংখ্যা দেখে সন্দেহ করতে পারেন কি না, দাম দেখে দুটি পথের মধ্যে বাছতে পারেন কি না, আর একটি পুরো ব্যবস্থা সাজাতে পারেন কি না।
কঠিনতার চিহ্ন: (সহজ), (মাঝারি), (কঠিন). প্রতিটি উত্তরের শেষে “রিভিশন”-এর পর্বে পূর্ণ ব্যাখ্যা আর আসল run আছে।
১ · Model বাছাই আর trade-off
রিভিশন: পর্ব ০২, পর্ব ৩৮ · Tabular ডেটায় model বাছাই
প্র ১বাজারঘরের ২০ হাজার ক্রেতার ৩০টি কলামের টেবিল থেকে churn অনুমান করতে হবে। প্রথম model কোনটি, আর কেন? (সহজ)
দুর্বল উত্তর: “একটি deep neural network, কারণ এটি সবচেয়ে শক্তিশালী।” কেন দুর্বল: শক্তির দাবি আছে, তুলনা নেই; tabular ডেটায় এটি প্রায়ই প্রথম পছন্দ নয়।
শক্ত উত্তর: “আগে দুটি baseline: সবাইকে গড় হার বলা আর একটি সরল নিয়ম, যেমন recency. তারপর regularized logistic regression, তারপর gradient boosting, সবাই একই fold-এ, একই metric-এ। Boosting-এ scaling লাগে না আর interaction নিজে ধরে; linear model ব্যাখ্যা আর calibration-এ সস্তা। পার্থক্য fold-এর ওঠানামার মধ্যে থাকলে সরলটি নেব।” এরপর বাজেটের কথা বলুন: tuning-এ কত সময়, latency কত, কে ব্যাখ্যা চাইবেন। ক্যাপস্টোনে ঠিক এটাই ঘটেছিল: চারটি সময়-ক্রমের fold-এ logistic-এর গড় AUC ০.৭৭৫, HistGradientBoosting-এর ০.৭৭২, তাই logistic. রিভিশন: পর্ব ৩৮, পর্ব ৭২.
প্র ২ব্যবসার দল বলছেন, “সবচেয়ে নির্ভুল model চাই, কিন্তু প্রতিটি সিদ্ধান্তের কারণও দেখাতে হবে।” ব্যাখ্যা আর নির্ভুলতার দ্বন্দ্ব কীভাবে সামলাবেন? (মাঝারি)
দুর্বল উত্তর: “Boosting নেব আর SHAP দিয়ে ব্যাখ্যা দেখাব, তাহলে দুটোই হলো।” কেন দুর্বল: দ্বন্দ্বটি আসল কি না মাপা হয়নি, আর post-hoc ব্যাখ্যা model-এর একটি আনুমানিক ছবি, নিয়ম নয়।
শক্ত উত্তর: প্রথম প্রশ্ন, দ্বন্দ্বটি কি সত্যি? একই fold-এ জোড়া ধরে দুটি model মাপুন; অনেক tabular সমস্যায় পার্থক্য noise-এর ভেতরে থাকে। দ্বিতীয় প্রশ্ন, কে কোন ব্যাখ্যা চান: গ্রাহক চান “কেন আমি”, নিয়ন্ত্রক চান নিয়মের নিশ্চয়তা, data scientist চান debugging. পথ তিনটি: সরল কাচের-বাক্স model (logistic, ছোট tree, GAM); নিয়ন্ত্রিত জটিল model, যেমন boosting-এ monotonic constraint, যাতে “বেশি দেরি মানে বেশি ঝুঁকি” কখনো উল্টে না যায়; আর জটিল model-এর পাশে SHAP, সীমা লিখে। নিয়মের বাধ্যবাধকতা থাকলে প্রথম পথ, কারণ post-hoc ব্যাখ্যা কখনো কখনো model-এর আসল কারণ থেকে সরে যায়। রিভিশন: পর্ব ৫৬, পর্ব ৫৭, পর্ব ২২.
২ · Overfitting, validation আর model-এর তুলনা
রিভিশন: পর্ব ০৩ · শেখার তত্ত্ব, পর্ব ১৭, পর্ব ২২, পর্ব ৫২; মৌলিক রূপ: AI-এর ভিত্তি কোর্সের পর্ব ৬১
প্র ৩একটি decision tree-র training accuracy ১.০০০, validation ০.৮২৭. সমস্যা কোথায়, আর আরও ডেটা কি সাহায্য করবে? (মাঝারি)
দুর্বল উত্তর: “Overfitting, তাই আরও ডেটা আনব।” কেন দুর্বল: ডেটা আনা দামি; আগে দেখা দরকার আরও ডেটায় ফাঁক কমছে কি না, আর অন্য সস্তা পথ আছে কি না।
শক্ত উত্তর: “বড় ফাঁক মানে variance বেশি, overfitting. প্রমাণের জন্য learning curve: কয়েকটি training আকারে train আর validation score. Validation ধীরে উঠতে থাকলে ডেটায় লাভ আছে; সাথে সাথে regularization (গভীরতা, পাতার ন্যূনতম সারি) চেষ্টা করব। উল্টো ছবি, দুটিই নিচু আর কাছাকাছি, মানে underfitting; তখন ডেটা নয়, নমনীয় model বা ভালো feature.” নিচের ব্লক তিনটি ছবিই দেখায়। রিভিশন: পর্ব ০৩, পর্ব ৩২.
import numpy as np
from sklearn.datasets import make_classification
from sklearn.model_selection import learning_curve, StratifiedKFold
from sklearn.tree import DecisionTreeClassifier
from sklearn.linear_model import LogisticRegression
# Synthetic churn-like data (seeded): 2,000 rows, 20 columns, 6 informative, 8% label noise
X, y = make_classification(n_samples=2000, n_features=20, n_informative=6,
n_redundant=2, flip_y=0.08, random_state=42)
cv = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)
models = {"deep tree": DecisionTreeClassifier(random_state=0),
"tree, depth 4": DecisionTreeClassifier(max_depth=4, random_state=0),
"logistic": LogisticRegression(max_iter=1000)}
for name, model in models.items():
n, tr, va = learning_curve(model, X, y, train_sizes=[100, 400, 1600],
cv=cv, scoring="accuracy")
print(name)
for k in range(len(n)):
t, v = tr[k].mean(), va[k].mean()
print(f" n={n[k]:4d} train {t:.3f} val {v:.3f} gap {t - v:.3f}")আসল আউটপুট (ব্রাউজারের Python):
deep tree
n= 100 train 1.000 val 0.744 gap 0.256
n= 400 train 1.000 val 0.782 gap 0.218
n=1600 train 1.000 val 0.827 gap 0.173
tree, depth 4
n= 100 train 0.976 val 0.748 gap 0.228
n= 400 train 0.905 val 0.814 gap 0.091
n=1600 train 0.876 val 0.855 gap 0.021
logistic
n= 100 train 0.822 val 0.764 gap 0.058
n= 400 train 0.817 val 0.789 gap 0.028
n=1600 train 0.815 val 0.804 gap 0.011
তিনটি ছবি। গভীর tree সবসময় train-এ ১.০০০, আর ফাঁক ০.২৫৬ থেকে ০.১৭৩-এ নামে: ডেটায় লাভ আছে, কিন্তু ধীরে। Logistic-এর ফাঁক মাত্র ০.০১১, অথচ validation ০.৮০৪-এ আটকে: এটি high bias, আরও ডেটায় তেমন লাভ নেই। গভীরতা ৪-এর tree দুটির মাঝখানে, ১,৬০০ সারিতে validation ০.৮৫৫, তিনটির মধ্যে সেরা, ফাঁক ০.০২১. শিক্ষা: “আরও ডেটা” না “অন্য model”, তা learning curve-এর আকার বলে দেয়। ৮% সারির label এলোমেলো বসানো, যার প্রায় অর্ধেক দৈবক্রমে ঠিক হয়, তাই কোনো model-এর প্রায় ০.৯৬-এর বেশি পাওয়ার কথা নয়।
প্র ৪Cross-validation-এ AUC ০.৮৮, চালুর এক মাস পরে মাপা AUC ০.৭১. Validation-এর নকশায় কোথায় ভুল খুঁজবেন? (মাঝারি)
দুর্বল উত্তর: “Production-এর ডেটা খারাপ।” কেন দুর্বল: দোষ বাইরে ঠেলে দেওয়া; আগে নিজের validation-কে সন্দেহ করা উচিত।
শক্ত উত্তর: চারটি প্রশ্ন, ক্রমে। (১) ভাগের একক কি production-এর একক? একই ক্রেতার অনেক সারি দুই দিকে পড়লে model মানুষ চেনে, ধাঁচ নয়; তখন group ধরে ভাগ। (২) সময় কি মানা হয়েছে? এলোমেলো ভাগ ভবিষ্যৎ দিয়ে অতীত অনুমান করায়; দরকার rolling origin, মাঝে label-এর জানালার সমান ফাঁক রেখে। (৩) Feature কি অনুমানের মুহূর্তে জানা ছিল? “গত ৩০ দিনের ফেরত” training-এ ভবিষ্যৎসহ হিসাব হলে তা leakage. (৪) একই কোড কি দুই জায়গায় চলে? না হলে training-serving skew. চারটি ঠিক থাকলে তবেই drift-এর প্রশ্ন (অংশ ৫)। রিভিশন: পর্ব ৫২, পর্ব ৭১, AI-এর ভিত্তি কোর্সের পর্ব ৫৬.
প্র ৫আপনি ১২টি সেটিং চেষ্টা করে সেরাটি বেছেছেন, যা baseline-এর চেয়ে ০.০১ ভালো। এই পার্থক্য আসল কি না কীভাবে বলবেন? (কঠিন)
দুর্বল উত্তর: “দুটি score-এর ওপর t-test চালাব।” কেন দুর্বল: একই fold-এর score স্বাধীন নয়, আর ১২টি চেষ্টার কথা ভুলে গেছেন।
শক্ত উত্তর: তিনটি স্তর। এক, জোড়া তুলনা: একই fold-এ দুই model, fold-ভিত্তিক পার্থক্যের গড় আর ছড়ানো। Fold-গুলো train ডেটা ভাগ করে, তাই সাধারণ t-test আশাবাদী; Nadeau ও Bengio-র corrected resampled t-test variance-এ ntest/ntrain যোগ করে। একই test সারিতে দুটি classifier হলে McNemar. দুই, বহু তুলনা: ১২টির সেরাটি বাছাই নিজেই আশাবাদ আনে; সব তুলনার p-value থাকলে Holm, আর সৎ সংখ্যার জন্য nested CV বা কখনো-না-দেখা test. তিন, ব্যবহারিক গুরুত্ব: ০.০১ AUC টাকায় কত, আর তা মেটানোর খরচ কত। রিভিশন: পর্ব ২২, পর্ব ৩৮.
প্র ৬VC dimension আর PAC-এর bound কি বাস্তবে কোনো কাজে আসে? ২,০০০ সারির একটি তালাবন্ধ test-এ ভুলের হার কতটা নিশ্চিত? (কঠিন)
দুর্বল উত্তর: “না, ওগুলো শুধু তত্ত্ব।” কেন দুর্বল: অতিসরল; অন্তর্দৃষ্টি আর একটি bound সত্যিই কাজের।
শক্ত উত্তর: বড় model-এ VC-ভিত্তিক bound প্রায়ই সংখ্যা হিসেবে অর্থহীন রকম ঢিলে, কিন্তু অন্তর্দৃষ্টি কাজের: ক্ষমতা বাড়লে generalisation gap বাড়ে, ডেটা বাড়লে কমে। ব্যবহারযোগ্য bound: test না-দেখা একটি স্থির model-এর ভুলের হার। Hoeffding-এর অসমতায় সম্ভাবনা ১ − δ নিয়ে |আসল − মাপা| ≤ √(ln(২/δ) ÷ ২n). n = ২,০০০, δ = ০.০৫ হলে ε ≈ ০.০৩০; n = ৫০০-তে ০.০৬১. অর্থাৎ ছোট test-এ ০.০২-এর পার্থক্য নিয়ে বড় দাবি চলে না। শর্তটি বলুন: test দেখে model বদলালে bound আর খাটে না। রিভিশন: পর্ব ০৩.
৩ · Imbalance, ব্যবসার metric আর calibration
রিভিশন: পর্ব ০২, পর্ব ২৬ · Probability calibration, পর্ব ৫০ · Imbalanced ডেটা; মৌলিক রূপ: AI-এর ভিত্তি কোর্সের পর্ব ৬০
প্র ৭৩% ভুয়া অর্ডারের ডেটায় একজন class_weight="balanced" দিলেন। এখন model গড়ে ২২% সম্ভাবনা বলে আর অনেক বেশি অর্ডার আটকায়। কী হয়েছে, আর ঠিক পথ কী? একটি ভুয়া ছাড়ার দাম ৳১৫০০, একটি সৎ অর্ডার আটকানোর ৳১০০. (মাঝারি)
দুর্বল উত্তর: “Imbalance-এ সবসময় balanced weight দিতে হয়, ফল ঠিক আছে।” কেন দুর্বল: weight দেওয়া মানে ধরে নেওয়া base rate বদলে ফেলা; সম্ভাবনা আর আসল ঝুঁকি থাকে না।
শক্ত উত্তর: “Class weight positive-এর odds n0/n1 গুণ বাড়ায়, যেন ডেটা ৫০-৫০. Ranking প্রায় একই থাকে, কিন্তু সম্ভাবনা ফুলে যায়, তাই ০.৫-এ বেশি অর্ডার আটকায়। ঠিক পথ: সাধারণ fit বা weight-এর পরে odds-কে n1/n0 দিয়ে গুণ করে ফেরানো, তারপর দাম থেকে threshold: t* = CFP ÷ (CFP + CFN) = ১০০ ÷ ১৬০০ = ০.০৬২৫.” নিচের ব্লক চারটি পথ টাকায় মাপে। রিভিশন: পর্ব ৫০, পর্ব ২৬.
import numpy as np
from sklearn.datasets import make_classification
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import roc_auc_score, brier_score_loss
# Fictional fraud data (seeded): about 3% positive
X, y = make_classification(n_samples=20000, n_features=8, n_informative=4,
weights=[0.97], flip_y=0, class_sep=0.8, random_state=7)
Xtr, Xte, ytr, yte = X[:10000], X[10000:], y[:10000], y[10000:]
plain = LogisticRegression(max_iter=1000).fit(Xtr, ytr)
bal = LogisticRegression(max_iter=1000, class_weight="balanced").fit(Xtr, ytr)
p_plain = plain.predict_proba(Xte)[:, 1]
p_bal = bal.predict_proba(Xte)[:, 1]
r = ytr.mean() / (1 - ytr.mean()) # undo the weights: odds x n1/n0
odds = p_bal / (1 - p_bal) * r
p_fix = odds / (1 + odds)
print(f"test base rate {yte.mean():.4f}")
for name, p in [("plain", p_plain), ("balanced", p_bal), ("balanced+fix", p_fix)]:
print(f"{name:13s} mean p {p.mean():.4f} AUC {roc_auc_score(yte, p):.4f}"
f" Brier {brier_score_loss(yte, p):.4f} flagged@0.5 {(p >= 0.5).mean():.4f}")
C_FN, C_FP = 1500, 100 # Tk: miss a fraud, block an honest order
t_star = C_FP / (C_FP + C_FN)
for name, p, t in [("plain @0.5", p_plain, 0.5), ("plain @t*", p_plain, t_star),
("balanced @0.5", p_bal, 0.5), ("fixed @t*", p_fix, t_star)]:
flag = p >= t
cost = C_FN * ((~flag) & (yte == 1)).sum() + C_FP * (flag & (yte == 0)).sum()
print(f"{name:14s} t={t:.4f} cost Tk {cost:,}")আসল আউটপুট (ব্রাউজারের Python):
test base rate 0.0304
plain mean p 0.0292 AUC 0.9284 Brier 0.0207 flagged@0.5 0.0109
balanced mean p 0.2254 AUC 0.9326 Brier 0.1015 flagged@0.5 0.1639
balanced+fix mean p 0.0298 AUC 0.9326 Brier 0.0217 flagged@0.5 0.0122
plain @0.5 t=0.5000 cost Tk 334,100
plain @t* t=0.0625 cost Tk 209,900
balanced @0.5 t=0.5000 cost Tk 194,300
fixed @t* t=0.0625 cost Tk 196,100
Base rate ০.০৩০৪; সাধারণ model-এর গড় অনুমান ০.০২৯২, কাছাকাছি। Balanced model-এর গড় ০.২২৫৪, আসল হারের প্রায় সাত গুণ, Brier ০.০২০৭ থেকে ০.১০১৫-এ খারাপ, আর ০.৫-এ ১৬.৪% অর্ডার আটকায়; অথচ AUC প্রায় একই (০.৯২৮৪ বনাম ০.৯৩২৬)। Odds ফেরালে গড় ০.০২৯৮, Brier ০.০২১৭: সম্ভাবনা আবার অর্থবহ। টাকায়: সাধারণ model ০.৫-এ ৳৩,৩৪,১০০, একই model t*-এ ৳২,০৯,৯০০. Balanced-এর ০.৫ (৳১,৯৪,৩০০) আর ফেরানো সম্ভাবনার t* (৳১,৯৬,১০০) প্রায় সমান: weight আসলে threshold-কে ঘুরপথে সরিয়েছে। পার্থক্য হলো ফেরানো পথে সংখ্যাটি একটি সত্যিকারের সম্ভাবনা, যা দাম বদলালে নতুন t* বা প্রত্যাশিত ক্ষতির হিসাবে সরাসরি কাজে লাগে। একটি seed আর একটি ভাগের ফল; সাধারণ সত্য দাবি নয়।
প্র ৮“Churn কমাতে হবে” — এই লক্ষ্য থেকে কোন metric-এ model বিচার করবেন? (মাঝারি)
দুর্বল উত্তর: “AUC, কারণ এটি threshold ছাড়া মাপে।” কেন দুর্বল: AUC ক্রম মাপে, সিদ্ধান্ত নয়; যিনি চলেই যাবেন আর কোনো কুপনে ফিরবেন না, তাঁকে চেনাও “ঠিক” ক্রম।
শক্ত উত্তর: তিন স্তর, আগে থেকে লেখা। সিদ্ধান্তের মাপ: যাঁদের নিয়ম বাছে, তাঁদের এলোমেলো holdout-এর তুলনায় প্রতি জনে net margin, কুপনের খরচ বাদে; এটিই north star. Model-এর মাপ, যা launch-এর আগে পাওয়া যায়: AUC, calibration (ECE), আর শীর্ষ ৩০%-এ কত churner ধরা পড়ে। Guardrail: অভিযোগ, unsubscribe, জেলাভেদে কুপনের হার। একটি সতর্কতা যোগ করুন: যে সংখ্যাকে লক্ষ্য বানানো হয়, তা চাপে বিকৃত হয় (Goodhart-এর নীতি); “কুপন-পাওয়াদের churn কম” দেখাতে model এমন মানুষ বাছবে, যাঁরা এমনিই থাকতেন। রিভিশন: পর্ব ০২, পর্ব ৬৫, পর্ব ৭২.
প্র ৯Platt না isotonic? আর ECE ০.০২ মানে কি model সবার জন্য calibrated? (কঠিন)
দুর্বল উত্তর: “Isotonic সবসময় ভালো, কারণ বেশি নমনীয়।” কেন দুর্বল: নমনীয়তার দাম overfitting.
শক্ত উত্তর: Platt দুটি parameter-এর sigmoid: কম ডেটায় নিরাপদ, কিন্তু অন্য আকারের ভুল ধরে না। Isotonic যেকোনো একঘেয়ে আকার ধরে, কিন্তু কয়েকশো সারিতে overfit করে। দুটিই training-এর বাইরের ডেটায় শেখে। ECE-র তিন সতর্কতা: ঝুড়ির সংখ্যায় মান বদলায়; এটি গড়, তাই দলভিত্তিক calibration আলাদা মাপুন; আর base rate বদলালে (ঈদের মৌসুম) calibration ভাঙে, যা P(x | y) একই থাকলে odds-কে নতুন ও পুরোনো prior odds-এর অনুপাতে গুণ করে ঠিক হয়। রিভিশন: পর্ব ২৬, পর্ব ৫৯.
৪ · ব্যাখ্যা, অনিশ্চয়তা আর ন্যায্যতা
রিভিশন: পর্ব ৫৬, পর্ব ৫৭, পর্ব ৫৮ · Conformal prediction, পর্ব ৬০ · ML-এ ন্যায্যতা
প্র ১০ডেলিভারির সময়ের model-এ km_map কলামের permutation importance প্রায় শূন্য। কলামটি বাদ দেবেন? (মাঝারি)
দুর্বল উত্তর: “হ্যাঁ, importance শূন্য মানে তথ্য নেই।” কেন দুর্বল: Permutation importance বলে model এই কলামের ওপর কতটা ভর করে, অন্য কলামগুলো থাকা অবস্থায়; কলামে তথ্য আছে কি না, তা বলে না।
শক্ত উত্তর: “আগে দেখব এর কোনো প্রায়-যমজ কলাম আছে কি না। দুটি কলাম প্রায় একই তথ্য দিলে model একটির ওপর ভর করে, অন্যটির importance ছোট দেখায়, আর কোনটি পাবে তা প্রায় এলোমেলো। একটি কলাম এলোমেলো করলে সম্পর্কও ভাঙে, তাই অবাস্তব সারি তৈরি হয়। সমাধান: সম্পর্কিত কলামগুলোকে দল ধরে একসাথে এলোমেলো করা, অথবা একটি বাদ দিয়ে আবার fit করে দেখা।” বাদ দেওয়ার সিদ্ধান্তের যুক্তি অন্য: multicollinearity, feature-এর খরচ আর কোনটি production-এ নির্ভরযোগ্যভাবে পাওয়া যায়। রিভিশন: পর্ব ৫৬.
import numpy as np
from sklearn.linear_model import Ridge
from sklearn.inspection import permutation_importance
# Fictional delivery data (seeded): two almost-identical distance columns
rng = np.random.default_rng(3)
n = 3000
km = rng.gamma(2, 10, n) # road distance
km_map = km + rng.normal(0, 1.0, n) # map distance: nearly a copy
rain = rng.binomial(1, 0.2, n)
noise_col = rng.normal(0, 1, n) # no signal at all
hours = 4 + 0.5 * km + 6 * rain + rng.normal(0, 3, n)
X = np.c_[km, km_map, rain, noise_col]
names = ["km", "km_map", "rain", "noise_col"]
tr, te = slice(0, 2000), slice(2000, None)
def show(cols, title):
m = Ridge(alpha=1.0).fit(X[tr][:, cols], hours[tr])
pi = permutation_importance(m, X[te][:, cols], hours[te], n_repeats=10,
random_state=0, scoring="r2")
print(title, f"(test R2 {m.score(X[te][:, cols], hours[te]):.3f})")
for c, mu, coef in zip(cols, pi.importances_mean, m.coef_):
print(f" {names[c]:9s} coef {coef:6.3f} R2 drop {mu:.3f}")
print(f"corr(km, km_map) = {np.corrcoef(km, km_map)[0, 1]:.3f}")
show([0, 1, 2, 3], "all four columns")
show([1, 2, 3], "km dropped")আসল আউটপুট (ব্রাউজারের Python):
corr(km, km_map) = 0.998
all four columns (test R2 0.861)
km coef 0.460 R2 drop 1.313
km_map coef 0.040 R2 drop 0.012
rain coef 6.152 R2 drop 0.163
noise_col coef -0.129 R2 drop 0.000
km dropped (test R2 0.855)
km_map coef 0.498 R2 drop 1.545
rain coef 6.145 R2 drop 0.162
noise_col coef -0.126 R2 drop 0.000
দুই দূরত্বের correlation ০.৯৯৮. চারটি কলাম থাকলে km-এর R² পতন ১.৩১৩, km_map-এর মাত্র ০.০১২. km বাদ দিলে km_map একাই ১.৫৪৫ পায়, আর test R² ০.৮৬১ থেকে মাত্র ০.৮৫৫-এ নামে: তথ্যটি দুটিতেই ছিল। R² পতন ১-এর বেশি হওয়া সম্ভব, কারণ এলোমেলো করার পর অনুমান গড়ের চেয়েও খারাপ হয়, R² ঋণাত্মক হয়। noise_col-এর coefficient −০.১২৯, শূন্য নয়, কিন্তু importance ০.০০০: coefficient-এর আকার দেখে গুরুত্ব বলা যায় না।
প্র ১১একজন ম্যানেজার SHAP chart দেখে বললেন, “দেরির ভাগ কমালে churn কমবে।” কী বলবেন? (মাঝারি)
দুর্বল উত্তর: “ঠিক, SHAP দেখিয়েছে দেরিই কারণ।” কেন দুর্বল: SHAP একটি model-এর অনুমান ভাগ করে; জগতের কারণ ভাগ করে না।
শক্ত উত্তর: “SHAP বলে এই model অনুমান করতে দেরির কলামের ওপর কতটা ভর করে। দেরি নিজে churn ঘটায় কি না, তা আলাদা প্রশ্ন: দেরি হয়তো দূরের জেলার চিহ্ন, আর দূরের ক্রেতারা অন্য কারণেও কম কেনেন (confounding). কারণ জানতে হলে একটি পরীক্ষা, যেমন কিছু এলাকায় ডেলিভারি দ্রুত করে এলোমেলো তুলনা, বা ধারণা লিখে causal পদ্ধতি।” তবু SHAP কোথায় পরীক্ষা চালানো যায়, তার সূত্র দেয়। রিভিশন: পর্ব ৫৭, পর্ব ৬৪.
প্র ১২একটি সংখ্যার বদলে অনুমানের পরিসর দিতে চান। Conformal prediction কী নিশ্চয়তা দেয়, আর কী দেয় না? (কঠিন)
দুর্বল উত্তর: “৮০% পরিসর মানে প্রতিটি ক্রেতার জন্য ৮০% নিশ্চিত।” কেন দুর্বল: নিশ্চয়তাটি গড়ের, ব্যক্তির নয়।
শক্ত উত্তর: Split conformal একটি আলাদা calibration অংশে ভুলের score-এর quantile নেয়, আর নতুন সারির পরিসর বানায়। শর্ত শুধু exchangeability: calibration আর নতুন ডেটা একই উৎসের, ক্রম বদলালেও বণ্টন একই। তখন গড়ে অন্তত ৮০% পরিসর আসল মান ধরে, model যত খারাপই হোক; খারাপ model শুধু চওড়া পরিসর দেয়। যা দেয় না: প্রতিটি দলে বা প্রতিটি মানুষে ৮০% (তার জন্য দলভিত্তিক conformal), আর সময়ের সঙ্গে শর্ত ক্ষয়ে গেলে নিশ্চয়তা। ক্যাপস্টোনে আপেক্ষিক ভুলের score দিয়ে CLV-র ৮০% পরিসর test-এ ৮২.৯% ধরেছিল। বিকল্প: quantile regression (নিশ্চয়তা নেই, কিন্তু শর্তসাপেক্ষ আকার ভালো ধরে) আর Bayesian পথ। রিভিশন: পর্ব ৫৮, পর্ব ৪৫.
প্র ১৩Fairness-এর কোন মাপ বাছবেন? সবগুলো একসাথে মেটানো যায় না কেন? (কঠিন)
দুর্বল উত্তর: “জেলা কলাম মুছে দিলেই model ন্যায্য।” কেন দুর্বল: ঠিকানা, ডেলিভারির দিন বা দেরির হার জেলার proxy হয়ে থাকে।
শক্ত উত্তর: আগে ক্ষতির ধরন: সিদ্ধান্তটি সুবিধা (কুপন) না বোঝা (অগ্রিম টাকা চাওয়া)? সুবিধায় equal opportunity: যাঁদের সত্যিই দরকার, দুই দলে তাঁদের একই ভাগ সুবিধা পান। দলের base rate আলাদা হলে, নিখুঁত নয় এমন model-এ, দুই দলে calibration আর সমান FPR ও FNR একসাথে সাধারণত মেলে না; এটি Kleinberg ও সহকর্মীদের (২০১৬) আর Chouldechova-র (২০১৭) পরিচিত ফল। তাই বাছাই একটি মূল্যবোধের সিদ্ধান্ত, লিখে রাখার মতো। ক্যাপস্টোনে metro-র বাইরের churner-রা ঝুঁকির তালিকায় বেশি এসেছিলেন: recall-এর ফাঁক ০.০৯৪, ৯৫% CI [০.০৩৯, ০.১৪৩]. প্রতিকার তিন স্তরে: ডেটা (reweighing), training (constraint), আর সিদ্ধান্ত (দলভিত্তিক threshold, যা চালুর সময় দলের তথ্য চায়)। রিভিশন: পর্ব ৬০, পর্ব ৭২.
৫ · Drift, নজরদারি, serving আর scale
রিভিশন: পর্ব ৫৯ · Distribution shift, পর্ব ৬৮, পর্ব ৬৯, পর্ব ৭০, পর্ব ৭১
প্র ১৪Covariate shift, label shift আর concept shift: কীভাবে আলাদা করবেন, আর কোনটি সবচেয়ে বিপজ্জনক? (মাঝারি)
দুর্বল উত্তর: “সবই drift, retrain করলেই হয়।” কেন দুর্বল: তিনটির প্রতিকার আলাদা, আর একটি label ছাড়া ধরাই যায় না।
শক্ত উত্তর: Covariate shift-এ P(x) বদলায়, P(y | x) একই: নতুন জেলায় বেশি ক্রেতা, কিন্তু একই ধরনের ক্রেতার আচরণ একই। Label shift-এ P(y) বদলায়, P(x | y) একই: ঈদের আগে ভুয়া অর্ডারের ভাগ বাড়ে। Concept shift-এ P(y | x) নিজেই বদলায়: প্রতারকেরা কৌশল বদলান, একই feature-এর মানে বদলে যায়। প্রথম দুটি label ছাড়াই অনেকটা ধরা যায় (input-এর বণ্টন, domain classifier); তৃতীয়টি শুধু label বা হাতে যাচাই করা নমুনায়, তাই সবচেয়ে বিপজ্জনক: dashboard সবুজ, অথচ model ভুল। রিভিশন: পর্ব ৫৯.
প্র ১৫একটি feature-এ PSI ০.১২-এর alert এসেছে। কী করবেন? (মাঝারি)
দুর্বল উত্তর: “০.১-এর বেশি, তাই সাথে সাথে retrain.” কেন দুর্বল: PSI বলে বণ্টন সরেছে; model খারাপ হয়েছে কি না, বলে না।
শক্ত উত্তর: চারটি প্রশ্ন। এক, নমুনা কত বড়? ছোট নমুনায় কোনো সরা ছাড়াই PSI ওঠানামা করে। দুই, সরাটি কি আসল, না pipeline-এর ভুল (একক বদল, নতুন default মান, ফাঁকা কলাম)? তিন, এই feature model-এর কাছে কতটা জরুরি (importance)? চার, অনুমানের বণ্টন আর পাওয়া label-এ মান কি বদলেছে? ০.১ আর ০.২৫ প্রচলিত হাতের নিয়ম, কোনো পরিসংখ্যানের পরীক্ষা নয়। নিচের ব্লক দেখায় কতটা সরলে PSI কত হয়, আর ছোট নমুনায় কী হয়। রিভিশন: পর্ব ৫৯, পর্ব ৬৯.
import numpy as np
def psi(ref, cur, bins=10):
"""Population Stability Index with decile edges taken from the reference sample"""
edges = np.quantile(ref, np.linspace(0, 1, bins + 1))[1:-1]
e = np.bincount(np.searchsorted(edges, ref), minlength=bins) / len(ref)
a = np.bincount(np.searchsorted(edges, cur), minlength=bins) / len(cur)
e, a = np.clip(e, 1e-4, None), np.clip(a, 1e-4, None)
return np.sum((a - e) * np.log(a / e))
rng = np.random.default_rng(59)
ref = rng.normal(0, 1, 20000) # training-time feature (standardised)
cases = {"same distribution, n=20000": rng.normal(0, 1, 20000),
"same distribution, n=200": rng.normal(0, 1, 200),
"mean +0.25 sd": rng.normal(0.25, 1, 20000),
"mean +0.5 sd": rng.normal(0.5, 1, 20000),
"spread x1.5, same mean": rng.normal(0, 1.5, 20000)}
for name, cur in cases.items():
print(f"{name:27s} PSI {psi(ref, cur):.3f}")
# How often does a sample of 200 from the SAME distribution cross 0.1?
small = [psi(ref, rng.normal(0, 1, 200)) for _ in range(500)]
print(f"n=200, no shift: PSI >= 0.1 in {np.mean(np.array(small) >= 0.1):.1%} of 500 draws")আসল আউটপুট (ব্রাউজারের Python):
same distribution, n=20000 PSI 0.001
same distribution, n=200 PSI 0.026
mean +0.25 sd PSI 0.062
mean +0.5 sd PSI 0.236
spread x1.5, same mean PSI 0.202
n=200, no shift: PSI >= 0.1 in 2.6% of 500 draws
গড় ০.২৫ standard deviation সরলে PSI মাত্র ০.০৬২, অর্থাৎ ০.১-এর সতর্কতা বাজে না; ০.৫ সরলে ০.২৩৬. গড় একই রেখে ছড়ানো দেড় গুণ হলে ০.২০২: PSI শুধু গড় নয়, আকারও দেখে। একই বণ্টনের ২০০ সারির নমুনায় PSI ০.০২৬, আর ৫০০ বার টানলে ২.৬% ক্ষেত্রে ০.১ পেরোয়, কোনো সরা ছাড়াই। অনেক feature একসাথে নজরে থাকলে এমন ভুয়া alert প্রায় নিশ্চিত, তাই সতর্কতার পাশে নমুনার আকার আর importance লিখুন।
প্র ১৬ভুয়া অর্ডারের label আসে দুই থেকে সাত দিন পরে, আর যে অর্ডার আটকানো হয় তার label কখনো আসে না। নজরদারি কীভাবে সাজাবেন? (কঠিন)
দুর্বল উত্তর: “প্রতি সপ্তাহে label এলে precision আর recall দেখব।” কেন দুর্বল: আটকানো অর্ডারের label নেই, তাই recall-এর হিসাবই পক্ষপাতদুষ্ট; আর এক সপ্তাহ অন্ধ থাকা।
শক্ত উত্তর: দুটি সমস্যা আলাদা করুন। দেরির জন্য সস্তা থেকে দামি সংকেত: service (latency, ত্রুটি, fallback-এর হার), input-এর বণ্টন, অনুমানের বণ্টন (আটকানোর হার হঠাৎ দ্বিগুণ হলে প্রায়ই input ভাঙা), তারপর label এলে মান। আর আটকানো অর্ডারের label না আসা হলো selective labels: model যা দেখায়, ডেটা শুধু তা-ই শেখে, আর সেই ডেটায় পরের model শেখে, একটি feedback loop. প্রতিকার একটি ছোট এলোমেলো holdout, যেখানে model কাউকে আটকায় না; সেখানকার label সৎ, মূল্যায়ন আর training সেখান থেকে। পর্ব ৭১-এর ETA-র simulation-এ holdout ছাড়া ছয় দফায় প্রতিশ্রুতি ২৭.৮ থেকে ৩৯.৭ ঘণ্টা হয়েছিল, অথচ “সময়মতো”-র হার বেড়ে দেখাচ্ছিল ৮৭%. রিভিশন: পর্ব ৭১, পর্ব ৬৯.
প্র ১৭Batch না online serving? আর model মাঝে মাঝে দুই সেকেন্ড আটকে গেলে কী করবেন? (মাঝারি)
দুর্বল উত্তর: “সবসময় real-time API.” কেন দুর্বল: online serving-এর দাম আছে: latency-র সীমা আর সবসময় চালু থাকা।
শক্ত উত্তর: প্রশ্ন দুটি: input কি আগে জানা, আর কেউ কি অপেক্ষায় আছেন? আগে জানা আর অপেক্ষা নেই (প্রতিদিনের churn তালিকা) হলে batch: সস্তা, আবার চালানো যায়। মুহূর্তে জানা আর কেউ অপেক্ষায় (checkout) হলে online, একটি latency budget-সহ। মাঝে মাঝে আটকে যাওয়া গড় latency-তে দেখা যায় না, দেখা যায় p99-এ। প্রতিকার timeout আর একই প্রশ্নের সরল উত্তর: পর্ব ৭১-এ ৬০ ms timeout আর zone-এর নিয়ম p99-কে প্রায় ২,০০৮ থেকে ৬১ ms-এ নামিয়েছিল, অথচ simulated ব্যবসার ফল প্রায় একই ছিল (৭৮৪.৩ বনাম ৭৮৩.৬)। ডেটা memory ছাড়ালে training-এর জন্য out-of-core বা incremental learning. রিভিশন: পর্ব ৬৮, পর্ব ৭০, পর্ব ৭১.
৬ · Causal বনাম predictive, আর A/B test
রিভিশন: পর্ব ৬২ · A/B test-এর পরিকল্পনা, পর্ব ৬৩, পর্ব ৬৪ · Causal inference, পর্ব ৬৫
প্র ১৮পুরোনো ডেটায় কুপন-পাওয়া ক্রেতাদের churn ৩৬%, না-পাওয়াদের ১৩%. কেউ বললেন, “কুপন ক্ষতি করছে, বন্ধ করুন।” কী বলবেন? (মাঝারি)
দুর্বল উত্তর: “ডেটা স্পষ্ট, কুপন বন্ধ।” কেন দুর্বল: কুপন এলোমেলোভাবে দেওয়া হয়নি; কারা পেয়েছেন, সেটাই পার্থক্যের কারণ হতে পারে।
শক্ত উত্তর: “কুপন কারা পেয়েছিলেন? ঝুঁকিপূর্ণদের বেশি দেওয়া হলে ঝুঁকিই একটি confounder: এটি কুপন পাওয়া আর churn দুটিকেই বাড়ায়। ঝুঁকির দল ধরে তুলনা করলে ছবি উল্টে যেতে পারে (Simpson-এর ধাঁধা)।” নিচের stepper আর ব্লক হিসাবটি দেখায়। রিভিশন: পর্ব ৬৪.
| কুপন পাওয়া দলের churn | |
| না-পাওয়া দলের churn | |
| কুপন-দলে উচ্চ-ঝুঁকির ভাগ | |
| উচ্চ-ঝুঁকি: কুপন − না | |
| নিম্ন-ঝুঁকি: কুপন − না | |
| সমন্বিত প্রভাব |
- সরল তুলনা। কুপন পাওয়া দলের churn ০.৩৬১, না-পাওয়াদের ০.১৩৪: পার্থক্য +০.২২৬. দেখে মনে হয় কুপন ক্ষতিকর।
- কারা পেয়েছেন। উচ্চ-ঝুঁকির ৮০% আর নিম্ন-ঝুঁকির ১০% কুপন পেয়েছেন: কুপন-দলের প্রায় ৭৭% উচ্চ-ঝুঁকির, না-পাওয়া দলে প্রায় ৯%.
- উচ্চ-ঝুঁকির দলের ভেতরে। কুপনে ০.৪৫৩, ছাড়া ০.৫০৩: কুপন churn ৫ বিন্দু কমায়।
- নিম্ন-ঝুঁকির দলের ভেতরে। ০.০৫০ বনাম ০.১০০: এখানেও ৫ বিন্দু কম। দুই দলেই উপকার, অথচ মোট ছবিতে ক্ষতি।
- সমন্বয়। দলের ভেতরের পার্থক্য, পুরো জনগোষ্ঠীতে দলের ভাগ (০.৩ আর ০.৭) দিয়ে ওজন করে: −০.০৫, simulation-এ বসানো আসল প্রভাবের সমান।
- সীমা। এখানে ঝুঁকিই একমাত্র confounder, আর তা মাপা ছিল। অমাপা কারণ থাকলে ভরসা এলোমেলো পরীক্ষা।
import numpy as np
import pandas as pd
# Fictional history: staff gave coupons mostly to customers they thought were at risk
rng = np.random.default_rng(64)
n = 100_000
high = rng.random(n) < 0.3 # 30% high-risk customers
coupon = rng.random(n) < np.where(high, 0.8, 0.1) # NOT random: depends on risk
p_churn = np.where(high, 0.50, 0.10) - 0.05 * coupon # true effect: -5 points for all
churn = rng.random(n) < p_churn
df = pd.DataFrame({"risk": np.where(high, "high", "low"), "coupon": coupon, "churn": churn})
naive = df.groupby("coupon").churn.mean()
print("naive churn rate:", naive.round(3).to_dict(),
"| difference", round(naive[True] - naive[False], 3))
by = df.groupby(["risk", "coupon"]).churn.mean().unstack()
print(by.round(3))
diff = by[True] - by[False]
w = df.risk.value_counts(normalize=True) # standardise to the whole population
print("within-risk differences:", diff.round(3).to_dict(),
"| adjusted effect", round((diff * w).sum(), 3))আসল আউটপুট (ব্রাউজারের Python):
naive churn rate: {False: 0.134, True: 0.361} | difference 0.226
coupon False True
risk
high 0.503 0.453
low 0.100 0.050
within-risk differences: {'high': -0.05, 'low': -0.05} | adjusted effect -0.05
সরল পার্থক্য +০.২২৬, অথচ ঝুঁকির দুই দলেই পার্থক্য −০.০৫, আর সমন্বিত প্রভাব −০.০৫. একই কোডে n = ২০,০০০ দিলে দলভেদে −০.০২৭ আর −০.০৩৯ আসে: বিরল ঘরে (উচ্চ-ঝুঁকি, কুপন নেই) সারি কম, তাই এমন হিসাবের পাশে CI দিন।
প্র ১৯Churn model-এর শীর্ষ ঝুঁকির ক্রেতাদের কুপন দিলেই কি সবচেয়ে বেশি লাভ? (কঠিন)
দুর্বল উত্তর: “হ্যাঁ, যাঁদের চলে যাওয়ার সম্ভাবনা সবচেয়ে বেশি, তাঁদেরই কুপন দরকার।” কেন দুর্বল: ঝুঁকি একটি predictive প্রশ্ন; কুপনে কে বদলাবেন, তা causal প্রশ্ন।
শক্ত উত্তর: ক্রেতা চার ধরনের: কুপন ছাড়াই থাকবেন, কুপনেও যাবেন, কুপনে থাকবেন (persuadable), আর কুপনে বিরক্ত হয়ে যাবেন। লাভ আসে শুধু তৃতীয় দল থেকে, তাই দরকার uplift: কুপনে churn কতটা কমে, তা এলোমেলো পরীক্ষা থেকে। সিদ্ধান্ত টাকায়: লাভ = u × CLV − কুপনের খরচ × কুপন ব্যবহারের সম্ভাবনা। ক্যাপস্টোনে পুরোনো পরীক্ষায় সর্বোচ্চ ঝুঁকির ভাগে uplift সবচেয়ে বেশি ছিল (০.২৭৯), কিন্তু নিয়মটি ঝুঁকি নয়, uplift আর CLV দুটিই দেখে: প্রত্যাশিত লাভ ৳৪৮.৬ হাজার, সবাইকে দিলে ৳১.৫ হাজার। রিভিশন: পর্ব ৬৫, পর্ব ৭২.
প্র ২০A/B test-এ রোজ ফল দেখে প্রথম significant দিনে থামালে কী সমস্যা? আর দুই দলের আকার ১০,২৪০ বনাম ৯,৭৬০ হলে? (মাঝারি)
দুর্বল উত্তর: “p < ০.০৫ এলেই ফল নিশ্চিত, আর দলের আকারে সামান্য পার্থক্য স্বাভাবিক।” কেন দুর্বল: বারবার দেখলে ভুয়া জয়ের সম্ভাবনা ৫% থাকে না; আর ৪৮০-র পার্থক্য “সামান্য” কি না, তা হিসাব বলে।
শক্ত উত্তর: “Peeking: প্রতিটি দেখা একটি নতুন সুযোগ, তাই Type I error জমে। সমাধান আগে থেকে ঠিক করা আকার আর সময় (fixed horizon), বা group-sequential সীমা। আর পরিকল্পনা ৫০/৫০ হলে আকারের পার্থক্য chi-square দিয়ে যাচাই: এটি sample ratio mismatch, যা সাধারণত পরীক্ষার কাঠামোর ভুল (redirect-এ হারানো, bot ছাঁটাই এক দলে)। SRM হলে ফল বিশ্বাস করা যায় না, আগে কারণ।” নিচের ব্লক দুটিই মাপে। রিভিশন: পর্ব ৬২, পর্ব ৬৩.
import numpy as np
from scipy import stats
# A/A tests: both arms have the SAME 5% conversion, so every "win" is a false positive
rng = np.random.default_rng(62)
sims, days, per_day, p = 4000, 14, 500, 0.05
a = rng.binomial(per_day, p, (sims, days)).cumsum(axis=1) # cumulative conversions
b = rng.binomial(per_day, p, (sims, days)).cumsum(axis=1)
n = per_day * np.arange(1, days + 1) # visitors per arm so far
pool = (a + b) / (2 * n)
z = (b - a) / n / np.sqrt(pool * (1 - pool) * 2 / n) # two-proportion z each day
sig = np.abs(z) > 1.96
print(f"look once on day {days}: false positive {sig[:, -1].mean():.3f}")
print(f"look every day, stop at win: false positive {sig.any(axis=1).mean():.3f}")
first = np.argmax(sig, axis=1)[sig.any(axis=1)] + 1
print("median day of the fake win:", int(np.median(first)))
# Sample ratio mismatch: planned 50/50, observed counts
obs = np.array([10240, 9760])
chi2, pval = stats.chisquare(obs)
print(f"SRM check: chi2 = {chi2:.2f}, p = {pval:.5f}")আসল আউটপুট (ব্রাউজারের Python):
look once on day 14: false positive 0.053
look every day, stop at win: false positive 0.227
median day of the fake win: 4
SRM check: chi2 = 11.52, p = 0.00069
দুই দলের হার আসলে সমান, তাই প্রতিটি “জয়” ভুয়া। একবার, ১৪তম দিনে দেখলে ভুয়া জয় ৫.৩%, প্রায় α. রোজ দেখে প্রথম জয়ে থামলে ২২.৭%, চার গুণের বেশি; আর ভুয়া জয়ের মাঝামাঝি দিন ৪, অর্থাৎ শুরুর অস্থির দিনগুলোতে। SRM-এ χ² = ১১.৫২, p = ০.০০০৬৯: ৫০/৫০ পরিকল্পনায় এত বড় পার্থক্য দৈবক্রমে প্রায় আসে না। ৪,০০০টি A/A simulation একটি seed-এর ফল; সঠিক হার দেখার সংখ্যা আর দিনের আকারের ওপর নির্ভর করে।
প্র ২১নতুন model offline-এ সব metric-এ ভালো, কিন্তু A/B test-এ ব্যবসার কোনো লাভ নেই। কেন হতে পারে? (কঠিন)
দুর্বল উত্তর: “A/B test ভুল হয়েছে, আবার চালাই।” কেন দুর্বল: ফল পছন্দ না হলে পরীক্ষা বারবার চালানো নিজেই peeking-এর আরেক রূপ।
শক্ত উত্তর: পাঁচটি সম্ভাব্য কারণ। (১) Offline metric ভুল জিনিস মাপছে: পর্ব ৭১-এর simulation-এ সবচেয়ে কম MAE-র median model প্রতি ১,০০০ checkout-এ প্রায় ৭৬২টি সম্পন্ন অর্ডার দিয়েছিল, বেশি MAE-র ০.৮-quantile model প্রায় ৭৮৬টি। (২) পরীক্ষার power কম; p বড় মানে “প্রভাব নেই” নয়, CI দেখুন, আর আগের সময়ের মাপ দিয়ে variance কমাতে CUPED. (৩) Offline ডেটা model-এর নিজের feedback-এ তৈরি, তাই নতুন জগতে আচরণ আলাদা। (৪) Interference: দুই দলের ক্রেতা একই মজুদ বা একই courier ভাগ করেন। (৫) Novelty বা অভ্যাসের প্রভাব, যা সময়ে বদলায়। রিভিশন: পর্ব ৬৩, পর্ব ৭১.
৭ · ML system design ইন্টারভিউ — কাঠামো, rubric আর red flag
রিভিশন: পর্ব ৭১ · ML system design; সাধারণ নকশার mock: System Design · Mock ইন্টারভিউ
ML system design-এর আলাপ সাধারণত ৪৫ থেকে ৬০ মিনিট, প্রশ্ন ইচ্ছা করে অস্পষ্ট। দেখা হয় আপনি প্রশ্ন করে সমস্যা সংকুচিত করেন কি না, আর model-এর বাইরের অংশ (label, metric, serving, নজরদারি) সমান গুরুত্ব পায় কি না। পর্ব ৭১-এর দশ ধাপই কাঠামো; সময়ের মোটা ভাগ:
- চাহিদা আর পরিধি (৫–৭ মিনিট): কোন সিদ্ধান্ত, কে নেন, কত দ্রুত, ভুলের দাম কী, কী বাদ।
- Framing আর label (৫ মিনিট): ML task, unit, অনুমানের মুহূর্ত, label কখন আর কতটা বিশ্বাসযোগ্য।
- Metric (৫ মিনিট): offline, online আর guardrail, আগে থেকে লেখা।
- ডেটা আর feature (৮ মিনিট): অনুমানের মুহূর্তে কী জানা যায়; leakage আর skew.
- Baseline আর model (৫ মিনিট): ML ছাড়া উত্তর আগে, তারপর প্রথম model আর কেন।
- Serving আর scale (৫–৮ মিনিট): batch না online, অনুরোধের হার, latency, fallback.
- মূল্যায়ন আর নজরদারি (৮ মিনিট): shadow, canary, A/B, drift, feedback loop, retrain.
Scoring rubric — নিজেকে বা বন্ধুকে নম্বর দিন
নিচের rubric এই কোর্সের শেখানোর জন্য বানানো; কোনো প্রতিষ্ঠানের আসল নম্বর-পদ্ধতি নয়। প্রতিটি ক্ষেত্রে ১ থেকে ৪; ২৮-এর মধ্যে ২০ বা বেশি মোটামুটি শক্ত আলাপ।
| ক্ষেত্র | ১ · দুর্বল | ৪ · শক্ত |
|---|---|---|
| চাহিদা আর পরিধি | সরাসরি model-এর নাম বলেন | সিদ্ধান্ত, ভুলের দাম, সংখ্যা আর বাদের তালিকা আগে |
| Framing আর label | “label আছে” ধরে নেন | unit, অনুমানের মুহূর্ত, label-এর দেরি আর পক্ষপাত বলেন |
| Metric | শুধু accuracy বা AUC | টাকায় লক্ষ্য, offline proxy, guardrail, লঞ্চের নিয়ম |
| ডেটা আর feature | সব কলাম feature | প্রতিটি feature-এর “কখন জানা যায়”, skew-এর প্রতিকার |
| Model আর baseline | সবচেয়ে জটিল model প্রথমে | নিয়ম বা সরল baseline, তারপর কারণসহ model |
| Serving আর ব্যর্থতা | শুধু “API বানাব” | অনুরোধের হার, p99, timeout, fallback, মানুষের সুইচ |
| মূল্যায়ন আর নজরদারি | “accuracy কমলে retrain” | shadow, A/B, চার স্তরের নজরদারি, feedback loop-এর holdout |
সব mock-এ খাটে এমন red flag
- প্রশ্ন ছাড়াই প্রথম দুই মিনিটে model বা টুলের নাম।
- Label কোথা থেকে আসবে, কত দেরিতে, কোনো উল্লেখ নেই।
- এলোমেলো train-test ভাগ, যেখানে সময় বা গ্রাহক জরুরি।
- Training-এর সময় পাওয়া যায় কিন্তু অনুমানের মুহূর্তে পাওয়া যায় না, এমন feature.
- Model বন্ধ হলে কী হবে, আর model-এর সিদ্ধান্ত পরের label কীভাবে বদলায়, তার কোনো কথা নেই।
- ইঙ্গিত শুনেও নকশা না বদলানো, বা প্রতিটি আপত্তিতে পুরো নকশা ছেড়ে দেওয়া।
৮ · Mock ১ — ক্যাশ-অন-ডেলিভারির ফেরত ঠেকানো
রিভিশন: পর্ব ৭১, পর্ব ৫০, পর্ব ৪৩, পর্ব ৬০
“বাজারঘরে অনেক ক্যাশ-অন-ডেলিভারি (COD) অর্ডার দরজায় গিয়ে ফেরত আসে: ক্রেতা নেন না, ফোন ধরেন না। প্রতিটিতে দুই দিকের ডেলিভারির খরচ যায়। একটি ML ব্যবস্থা নকশা করুন।”
নিচে একজন শক্ত প্রার্থীর উত্তর, ধাপে ধাপে। সংখ্যাগুলো ধরে নেওয়া; ইন্টারভিউতে এগুলো প্রশ্ন করে জানবেন, না পেলে নিজের অনুমান স্পষ্ট বলে এগোবেন।
ধাপ ১ · চাহিদা আর সিদ্ধান্ত
সিদ্ধান্ত তিনটি: COD চলবে, অগ্রিম মোবাইল-পেমেন্ট চাওয়া, বা পাঠানোর আগে ফোনে যাচাই; checkout-এর মুহূর্তে, তাই online. ভুলের দাম দুই দিকে: ফেরতে প্রায় ৳১৫০; সৎ ক্রেতার কাছে অগ্রিম চাইলে কেউ কেউ অর্ডার ছাড়েন। পরিধির বাইরে: courier বাছাই, প্রতারক চক্রের তদন্ত।
ধাপ ২ · Framing, label আর একটি ফাঁদ
Unit একটি COD অর্ডার; label “দরজায় ফেরত”, জানা যায় দুই থেকে সাত দিন পরে। আসল প্রশ্নটি এরপর: যাঁদের কাছে অগ্রিম চাওয়া হবে, তাঁদের COD-এর ফল আর কখনো জানা যাবে না। এটি selective labels; তাই প্রথম দিন থেকেই একটি ৫% এলোমেলো holdout, যেখানে কাউকে আটকানো হয় না। সেই অংশই সৎ মূল্যায়ন আর ভবিষ্যৎ training-এর ভিত্তি। Model শেখে ফেরতের সম্ভাবনা p; সিদ্ধান্ত হয় p × ৳১৫০ বনাম সৎ ক্রেতা হারানোর প্রত্যাশিত দামের তুলনায়।
ধাপ ৩ · খামের পেছনের হিসাব
# Back-of-the-envelope for a fictional COD-refusal model at Bazarghar (all inputs assumed)
orders_day = 50_000 # orders per day
cod_share = 0.60 # share paid as cash on delivery
refuse_rate = 0.04 # COD parcels refused at the door
cost_refuse = 150 # Tk lost per refusal (two-way delivery, handling)
attempts = 1.3 # "place order" clicks per completed order (scored each time)
peak, sale = 3, 5 # evening peak x3, sale day x5 on top
holdout = 0.05 # random share never blocked, so its labels stay honest
cod = orders_day * cod_share
print(f"COD orders/day {cod:,.0f}")
print(f"refusals/day {cod * refuse_rate:,.0f} -> Tk {cod * refuse_rate * cost_refuse:,.0f} lost/day")
rps = orders_day * attempts / 86_400
print(f"scoring req/s avg {rps:.2f}, peak {rps * peak:.1f}, sale peak {rps * peak * sale:.1f}")
print(f"labels/week {cod * 7:,.0f} COD outcomes, {cod * refuse_rate * 7:,.0f} refusals")
print(f"honest labels/week {cod * holdout * 7:,.0f} holdout orders, "
f"{cod * holdout * refuse_rate * 7:,.0f} refusals among them")
print(f"holdout cost/day at most Tk {cod * holdout * refuse_rate * cost_refuse:,.0f} "
"(if the model would have stopped every refusal in it)")
log_gb = orders_day * attempts * 2_000 * 365 / 1e9 # ~2 KB per scored request
print(f"prediction logs {log_gb:.1f} GB/year")আসল আউটপুট (ব্রাউজারের Python):
COD orders/day 30,000
refusals/day 1,200 -> Tk 180,000 lost/day
scoring req/s avg 0.75, peak 2.3, sale peak 11.3
labels/week 210,000 COD outcomes, 8,400 refusals
honest labels/week 10,500 holdout orders, 420 refusals among them
holdout cost/day at most Tk 9,000 (if the model would have stopped every refusal in it)
prediction logs 47.5 GB/year
দিনে ৩০,০০০ COD অর্ডারে ১,২০০টি ফেরত, ধরে নেওয়া দামে দিনে ৳১,৮০,০০০: সমস্যাটি টাকায় বড়, তাই কাজের যোগ্য। অনুরোধ খুব কম, sale-এর ভিড়েও সেকেন্ডে প্রায় ১১টি; কঠিন অংশ latency নয়, label. সপ্তাহে প্রায় ৮,৪০০টি ফেরত training-এর জন্য যথেষ্ট, কিন্তু সৎ holdout-এ মাত্র ৪২০টি, তাই holdout-এ মাপা recall-এর CI চওড়া হবে; holdout-এর দাম দিনে সর্বোচ্চ ৳৯,০০০.
ধাপ ৪ · Feature, baseline আর model
Feature, প্রতিটির “কখন জানা যায়” লিখে: ক্রেতার আগের COD-এর ফল (শুধু যেগুলোর label পেকেছে), ফোন নম্বরের বয়স, ঠিকানার ধরন, অর্ডারের টাকা, রাতের অর্ডার কি না, একই ফোন বা ঠিকানায় গত এক ঘণ্টার অর্ডার। “এই অর্ডার কি courier-এর কাছে পৌঁছেছে” training-এ সহজে পাওয়া যায়, কিন্তু checkout-এ নয়: leakage. Baseline একটি নিয়ম: নতুন ক্রেতা আর বড় অর্ডারে ফোনে যাচাই। প্রথম model: gradient boosting, calibration-সহ; নতুন ক্রেতার জন্য cold start (আগের ইতিহাস নেই), তাই নিয়মটি fallback হিসেবেও থাকে। নতুন ধরনের প্রতারণার জন্য পাশে একটি anomaly score, শুধু মানুষের যাচাইয়ে।
COD-ফেরত ঠেকানোর ব্যবস্থা — অনলাইন পথ আর শেখার চক্র
Online path at checkout (top) and the learning loop with an honest holdout (bottom)
ধাপ ৫ · Serving, মূল্যায়ন আর নজরদারি
Online scoring, ৬০ ms budget, timeout হলে নিয়ম, প্রতিটি অনুমান version-সহ লগ। চালু হবে shadow-এ, তারপর canary; লঞ্চের নিয়ম আগে লেখা: মূল মাপ প্রতি ১,০০০ COD অর্ডারে ফেরতের খরচ আর হারানো অর্ডারের দাম মিলিয়ে নিট টাকা; guardrail অর্ডার-রূপান্তরের হার, অভিযোগ আর জেলাভেদে অগ্রিম চাওয়ার হার। নজরদারি চার স্তরে, ঈদের সপ্তাহের জন্য আলাদা reference.
| মিনিট | |
| আপনি | |
| সম্ভাব্য ফলো-আপ |
- চাহিদা। সিদ্ধান্ত আর দাম আগে। “সব অর্ডারে কেন নয়?”: prepaid অর্ডারে ফেরতের সমস্যা নেই।
- Label. দেরি আর selective labels নিজে থেকে তুলুন।
- Metric. টাকায় লক্ষ্য; AUC সৎ ক্রেতা হারানোর দাম মাপে না।
- Feature. প্রতিটির পাশে “কখন জানা যায়”; নতুন ক্রেতায় নিয়ম আর ফোন যাচাই।
- Model. নিয়ম baseline, তারপর boosting আর calibration; tabular আর কম latency-তে deep learning-এর বিশেষ কারণ নেই।
- Serving আর holdout. “holdout-এ তো টাকা যায়” শুনলে হিসাবটি দিন: দিনে সর্বোচ্চ ৳৯,০০০, বিনিময়ে সৎ label আর feedback loop থেকে মুক্তি।
- শেষ। সারাংশ, তারপর ঝুঁকি: কৌশল বদল (concept shift), জেলাভেদে বোঝা, holdout-এ ছোট n.
প্র ২২ফলো-আপ: “গ্রামের জেলায় COD বেশি আর ফেরতও বেশি। Model কি তাঁদের সবার কাছে অগ্রিম চাইবে?” (কঠিন)
দুর্বল উত্তর: “ডেটা যা বলে, model তা-ই করবে।” কেন দুর্বল: একটি দলের ওপর বোঝা চাপানোর ঝুঁকি আর তার ব্যবসায়িক ও নৈতিক দাম উপেক্ষা।
শক্ত উত্তর: “জেলা feature-এ না থাকলেও ঠিকানা আর ডেলিভারির দিন proxy হবে। তাই জেলাভেদে অগ্রিম চাওয়ার হার আর holdout-এ সৎ ক্রেতাদের মধ্যে ভুল flag-এর হার (FPR) আলাদা মাপব। বোঝাটি কমাতে নরম পথ আগে: অগ্রিমের বদলে ফোনে যাচাই। আর কারণ খুঁজব: ফেরত বেশি হয়তো দেরির ডেলিভারির ফল, ক্রেতার নয়; তখন সমাধান ডেলিভারিতে।” ক্যাপস্টোনেও একই ধাঁচ দেখা গিয়েছিল: দেরির কারণে metro-র বাইরের ক্রেতার CLV কম অনুমান হয়েছিল, আর খারাপ সেবা পাওয়া দল কম সুবিধা পাচ্ছিল। রিভিশন: পর্ব ৬০, পর্ব ৭২.
এই mock-এর red flag: holdout ছাড়া শুধু আটকানো-না-হওয়া অর্ডারে retrain; “accuracy ৯৬%” (ফেরত ৪%, তাই সবাইকে COD দিলেই ৯৬%); আর অগ্রিম চাওয়ায় হারানো সৎ ক্রেতার দাম হিসাবে না রাখা।
৯ · Mock ২ ও ৩ — গুদামের চাহিদা আর বাংলা পণ্য-খোঁজা
রিভিশন: পর্ব ৫১, পর্ব ৫২ · ML দিয়ে forecasting, পর্ব ২৪, পর্ব ৫৩, পর্ব ৫৫
“বাজারঘরের পাঁচটি জেলা গুদামে প্রায় ৩,০০০ পণ্য। প্রতি সোমবার পরের সপ্তাহের মজুদ ঠিক হয়। একটি চাহিদা-পূর্বাভাসের ব্যবস্থা নকশা করুন।”
চাহিদা আর framing. সিদ্ধান্ত মজুদের সংখ্যা, সপ্তাহে একবার, তাই batch; latency প্রায় অপ্রাসঙ্গিক। প্রায় ১৫,০০০টি series (৫ গুদাম × ৩,০০০ পণ্য), অনেকগুলো বিরল বিক্রির। শক্ত প্রার্থী প্রথমেই বলেন, গড় অনুমান ভুল লক্ষ্য: মজুদ ফুরালে বিক্রি হারায় (প্রতি একক ৳১২০ margin ধরে), বেশি থাকলে জায়গা আর নষ্ট হওয়ার খরচ (৳৪০)। এটি newsvendor সমস্যা: সেরা মজুদ হলো চাহিদার Cu ÷ (Cu + Co) quantile, যেখানে Cu কম রাখার আর Co বেশি রাখার একক-দাম। তাই model শিখবে quantile, loss pinball.
| Cu, Co | |
| critical ratio | |
| মজুদ | |
| প্রত্যাশিত খরচ | |
| বিক্রির রেকর্ড |
- দুই দাম। একটি বিক্রি হারানো ৳১২০, একটি একক বেশি থাকা ৳৪০. দাম সমান নয়, তাই গড় বা median ঠিক উত্তর নয়।
- Critical ratio. ১২০ ÷ (১২০ + ৪০) = ০.৭৫: চাহিদার ৭৫% quantile পর্যন্ত মজুদ।
- সংখ্যা। Normal বণ্টনে ৭৫% quantile = গড় + ০.৬৭৪ × SD = ২০০ + ২৭ = ২২৭ একক।
- যাচাই। Simulation-এ প্রত্যাশিত খরচ: গড়ের সমান ২০০ রাখলে ৳২,৫৫১, ২২৭-এ ৳২,০৩১, বেশি সাবধানী ২৬০-এ ৳২,৫৮৮. Quantile-ই সবচেয়ে সস্তা।
- লুকোনো ফাঁদ। মজুদ ফুরালে রেকর্ডে বিক্রি = মজুদ, চাহিদা নয়। ২১০ মজুদে রেকর্ডের গড় ১৮৮.৬, অথচ আসল চাহিদা ২০০: এই ডেটায় শিখলে model কম অনুমান করে, পরের বার আরও কম মজুদ, আবার কম বিক্রি।
import numpy as np
from scipy import stats
# Newsvendor: how many units of one product to stock at one district warehouse
c_under, c_over = 120, 40 # Tk: lost margin per missed sale, cost per unsold unit
ratio = c_under / (c_under + c_over)
mu, sd = 200, 40 # forecast for next week's demand (assumed normal)
q = stats.norm.ppf(ratio, mu, sd)
print(f"critical ratio {ratio:.3f} -> stock the {ratio:.0%} quantile = {q:.1f} units")
rng = np.random.default_rng(52)
demand = rng.normal(mu, sd, 200_000).clip(0)
for stock in [200, 227, 260]:
short = np.clip(demand - stock, 0, None).mean()
left = np.clip(stock - demand, 0, None).mean()
cost = c_under * short + c_over * left
print(f"stock {stock}: expected cost Tk {cost:,.0f} "
f"(stock-out {np.mean(demand > stock):.1%} of weeks)")
# Censored demand: when a product sells out, sales = stock, not demand
sales = np.minimum(demand, 210)
print(f"true mean demand {demand.mean():.1f} vs mean of recorded sales {sales.mean():.1f}")আসল আউটপুট (ব্রাউজারের Python):
critical ratio 0.750 -> stock the 75% quantile = 227.0 units
stock 200: expected cost Tk 2,551 (stock-out 50.0% of weeks)
stock 227: expected cost Tk 2,031 (stock-out 24.9% of weeks)
stock 260: expected cost Tk 2,588 (stock-out 6.7% of weeks)
true mean demand 200.0 vs mean of recorded sales 188.6
সূত্রের ২২৭.০ আর simulation-এর সবচেয়ে কম খরচ মেলে; ২২৭-এ মজুদ ফুরায় প্রায় ২৪.৯% সপ্তাহে, যা ইচ্ছাকৃত: দাম অসমান বলে মাঝে মাঝে ফুরানো সস্তা। শেষ লাইনটি mock-এর সবচেয়ে বড় ফলো-আপ: বিক্রি আর চাহিদা এক নয়। এই censored demand সামলাতে মজুদ-শূন্য দিনগুলো চিহ্নিত করে বাদ দিন বা censoring ধরে এমন পদ্ধতি নিন (পর্ব ৫৫-এর survival-এর মতো যুক্তি)।
ডেটা, model আর মূল্যায়ন. Feature: lag আর rolling গড় (শুধু অতীত), calendar (ঈদ, sale), দাম, মজুদ-শূন্য চিহ্ন। Baseline: seasonal naive আর গত চার সপ্তাহের গড়। প্রথম model: সব series-এ একটি global gradient boosting, quantile loss-এ; বিরল বিক্রির পণ্যে সরল পদ্ধতি; মোট আর ভাগ মেলাতে hierarchical সমন্বয়। মূল্যায়ন rolling-origin backtest-এ, সাথে টাকায় খরচ আর মজুদ-ফুরানোর হার; ঈদের সপ্তাহ আলাদা slice.
ফলো-আপ: “ঈদের আগের সপ্তাহে ভুল তিন গুণ কেন?” (ঈদের তারিখ চাঁদের হিসাবে প্রতি বছর প্রায় ১১ দিন সরে, তাই সাধারণ বার্ষিক seasonality ধরে না; calendar feature লাগে)। “৩,০০০টি আলাদা model কেন নয়?” (রক্ষণাবেক্ষণ, আর বিরল series-এ শেখার ডেটা নেই; global model অন্য পণ্য থেকে ধার নেয়)। Red flag: MAPE দিয়ে বিচার, যেখানে বহু সপ্তাহে বিক্রি শূন্য (ভাগে শূন্য); এলোমেলো CV; বিক্রিকে চাহিদা ধরে নেওয়া।
“বাজারঘরের search box-এ ক্রেতারা বাংলা, ইংরেজি আর Banglish-এ লেখেন (‘ইলিশ’, ‘ilish mach’, ‘hilsa’). খোঁজার ফল সাজানোর ব্যবস্থা নকশা করুন।”
কাঠামো. দুই ধাপ, পর্ব ৭১-এর সুপারিশের মতো: প্রথমে কয়েকশো প্রার্থী (শব্দ মেলানো, বানানের ভুল সহ্য, দরকারে embedding-এর কাছাকাছি), তারপর ranking model (gradient boosting, কেনার সম্ভাবনা)। Query আগে এক রূপে: Unicode NFC, বাংলা অঙ্ক, আর Banglish থেকে বাংলায় প্রতিবর্ণের অভিধান। Offline মাপ NDCG@10 আর “কোনো ফল নেই”-এর হার, ভাষা ধরে আলাদা; online মাপ প্রতি search session-এ কেনা।
প্রায় নিশ্চিত ফলো-আপ: “click-এ শেখালে কী ভুল?” ওপরের ঘরে click এমনিই বেশি (position bias), আর না-দেখানো পণ্যের label নেই। প্রতিকার: অবস্থানকে feature করে শেখানো আর অনুমানে স্থির মান বসানো, অল্প অংশে ক্রম এলোমেলো করা, আর দুই ranker-এর ফল মিশিয়ে দেখানোর interleaving. বাংলা লেখার গভীর NLP পরের NLP কোর্সের বিষয়। Red flag: শুধু ইংরেজি query-তে মাপা, আর latency ও খরচ না ভেবে “একটি বড় language model দিয়ে সব”।
১০ · ক্যাপস্টোন নিয়ে আচরণগত প্রশ্ন, শেষ সপ্তাহ আর পরের পথ
রিভিশন: পর্ব ৭২ · ক্যাপস্টোন, পর্ব ৬৭; পুরো কোর্সের মানচিত্র: কোর্স হোম
আচরণগত প্রশ্নে STAR: Situation, Task, Action, Result, শেষে একটি শিক্ষা, দুই মিনিটে। ML-এর গল্পে খোঁজা হয়, খারাপ সংখ্যা লুকাননি তো?
সততার নিয়ম: নিচের উত্তরগুলো এই কোর্সের ক্যাপস্টোনে (পর্ব ৭২) সত্যিই যা এসেছে, সেই সংখ্যায় লেখা, শুধু কাঠামো দেখাতে। নিজে চালালে নিজের সংখ্যা বলুন; যা করেননি, তা নয়। কাল্পনিক ডেটায় কোনো ব্যবসায়িক ফল দাবি করা যায় না; প্রথম বাক্যেই বলুন ডেটা simulation.
প্র ২৩“আপনার প্রকল্পটি তিন মিনিটে বলুন।” (সহজ)
দুর্বল উত্তর: “Churn model বানিয়েছি, XGBoost, SHAP, Streamlit, Docker সব ব্যবহার করেছি।” কেন দুর্বল: টুলের তালিকা, সিদ্ধান্ত বা প্রমাণ নেই।
শক্ত উত্তর: “সিদ্ধান্ত: একটি কাল্পনিক অনলাইন দোকান কাকে ৳১০০-এর কুপন দেবে, simulation-এর ডেটায়। Unit মাসের ১ তারিখে সক্রিয় ক্রেতা, label পরের ৯০ দিনে অর্ডার নেই। Feature শুধু cutoff-এর আগের তথ্য থেকে, আর তা একটি test প্রমাণ করে: পরের অর্ডার মুছলেও feature হুবহু এক। সময়-ক্রমের fold-এ logistic আর boosting প্রায় সমান, তাই logistic; একবারের test-এ AUC ০.৭৭৫ [০.৭৫৬, ০.৭৯৩], ECE ০.০২৯. শেষ সিদ্ধান্ত টাকায়: পুরোনো এলোমেলো পরীক্ষার uplift আর CLV মিলিয়ে ২,৭০০ জনের ১,১৯৯ জন, প্রত্যাশিত লাভ ৳৪৮.৬ হাজার, যা যাচাইয়ের জন্য প্রতি দলে ৪৭২ জনের A/B পরিকল্পনা।” শেষে একটি সীমা বলুন। রিভিশন: পর্ব ৭২.
প্র ২৪“আপনার কাজে এমন একটি ঝুঁকি পেয়েছেন, যা অন্যরা দেখেননি?” (মাঝারি)
দুর্বল উত্তর: “Model-এ কোনো bias ছিল না, কারণ জেলা কলাম দিইনি।”
শক্ত উত্তর: S: “কুপনের নিয়ম চূড়ান্ত হওয়ার পর দলভিত্তিক হিসাব করছিলাম।” T: “জেলা feature-এ ছিল না, কিন্তু ফল দুই দলে কেমন, তা দেখা আমার দায়িত্ব ছিল।” A: “ঝুঁকির তালিকায় metro-র বাইরের churner বেশি এসেছিলেন (recall-এর ফাঁক ০.০৯৪, CI [০.০৩৯, ০.১৪৩]). অথচ টাকার নিয়মে metro সামান্য বেশি কুপন পায়, ৪৫.৮% বনাম ৪২.১%, কারণ দেরির ডেলিভারি বাইরের ক্রেতার অনুমিত CLV কমিয়েছে (৳৩৪৮ বনাম ৳৪৪৬)।” R: “Memo-তে ঝুঁকি হিসেবে লিখলাম: খারাপ সেবা পাওয়া দলকে কম মূল্যবান দেখানো একটি চক্র; A/B-তে জেলাভেদে কুপনের হার guardrail.” শিক্ষা: “সংবেদনশীল কলাম বাদ দেওয়া ন্যায্যতার প্রমাণ নয়; ফল দলভেদে মাপতে হয়।” রিভিশন: পর্ব ৭২, পর্ব ৬০.
প্র ২৫“আপনার ৳৪৮.৬ হাজারের সংখ্যাটি কতটা বিশ্বাস করব?” (কঠিন)
দুর্বল উত্তর: “পুরোপুরি, কোড দিয়ে হিসাব করা।” কেন দুর্বল: কোডের নির্ভুলতা আর অনুমানের নির্ভুলতা এক নয়।
শক্ত উত্তর: “এটি একটি অনুমান, তিনটি শর্তে দাঁড়িয়ে। এক, কুপনে ফেরা ক্রেতা একজন সাধারণ থাকা-ক্রেতার মতো কিনবেন, যা যাচাই হয়নি। দুই, uplift-এর প্রতিটি মান প্রায় ৫৯৪ জনের পরীক্ষা থেকে, ± ০.০৩–০.০৪; শুধু ধনাত্মক অনুমান বেছে যোগ করলে যোগফল আশাবাদী, অর্থাৎ winner's curse. তিন, পরীক্ষাটি পুরোনো, আজকের ক্রেতা আলাদা হতে পারেন। তাই পূর্ণ চালুর আগে প্রতি দলে ৪৭২ জনের A/B, ১৮০ দিনের net margin মূল মাপ, মাঝপথে থামানো নয়।” রিভিশন: পর্ব ৭২, পর্ব ৬২.
আপনি মেশিন লার্নিং কোর্সের ৭৭টি পর্ব পেরিয়ে এসেছেন: শেখার তত্ত্ব, linear algebra আর optimization, সম্ভাবনার model, SVM আর kernel, tree আর boosting, unsupervised আর Bayesian ML, forecasting আর recommender, ব্যাখ্যা আর ন্যায্যতা, data science-এর কাজের ধারা, production আর একটি পূর্ণ প্রকল্প। সবচেয়ে বড় অর্জন কোনো algorithm-এর নাম নয়, একটি অভ্যাস: যেকোনো ভালো সংখ্যা দেখে জিজ্ঞেস করা, “কোন ভাগে মাপা, কার তুলনায়, কোন দলে খারাপ, আর এটি কি সম্পর্ক না কারণ?”
এরপর কী করবেন
- আবার ঝালিয়ে নিন: যে প্রশ্নে আটকেছেন, কোর্স হোম থেকে সেই মডিউলে ফিরে যান; পাশাপাশি পর্ব ৭৩–৭৬.
- নিজের একটি প্রকল্প, ক্যাপস্টোনের শৃঙ্খলায়: আগে লেখা মানদণ্ড, সময় ধরে ভাগ, একবারের test, model card আর memo.
- পরের AI কোর্স (প্রস্তুত হচ্ছে): deep learning, NLP, generative AI, MLOps আর AI ethics. পাশের সম্পূর্ণ কোর্স: System Design, Cloud আর DevOps, DBMS আর SQL.
এই পাতা কোনো চাকরির নিশ্চয়তা দেয় না; আপনার হাতে আছে যাচাই করা যায় এমন কাজ, আর তা সীমাসহ সৎভাবে বলতে পারা।
AI-এর যুগে ML ইন্টারভিউর প্রস্তুতি
AI assistant একজন ধৈর্যশীল নকল ইন্টারভিউয়ার হতে পারে, কিন্তু ML-এ তার ভুলগুলো পরিচিত। সে প্রায়ই পুরোনো API দেয় (scikit-learn-এর সরানো parameter, XGBoost বা LightGBM-এর পুরোনো argument, pandas-এর append), না-থাকা function বা hyperparameter বানায়, test set-এ tuning করে বা target-এর তথ্য ফাঁস করে, training বা একটি ভাগের metric চূড়ান্ত বলে, imbalance আর calibration উপেক্ষা করে, SHAP-কে কারণ হিসেবে পড়ে, আর বিশ্বাসযোগ্য কিন্তু ভুল derivation লেখে। System design-এ সরঞ্জামের তালিকা দেয়, label আর feedback loop বাদ দেয়। তাই তাকে উত্তর লিখতে না বলে, আপনাকে চেপে ধরতে বলুন।
কোনো আসল প্রতিষ্ঠানের ডেটা, কোড বা মানুষের তথ্য কখনো দেবেন না।
আরও গভীরে: D. Sculley ও সহকর্মীদের “Hidden Technical Debt in Machine Learning Systems” (NeurIPS ২০১৫) দেখায়, বাস্তব ML ব্যবস্থায় model-এর কোড ছোট অংশ; ঋণ জমে ডেটা, configuration আর নজরদারিতে, যা system design আলাপের মূল বিষয়। Lakkaraju ও সহকর্মীরা (KDD ২০১৭) selective labels সমস্যা বিশ্লেষণ করেছেন, যা mock ১-এর holdout-এর যুক্তি। Ron Kohavi, Diane Tang ও Ya Xu-র বই Trustworthy Online Controlled Experiments (২০২০) SRM আর peeking-এর মতো ফাঁদের ব্যবহারিক তালিকা দেয়।
নিজেকে যাচাই করুন
ভুল হলে কারণসহ ব্যাখ্যা পাবেন, আবার চেষ্টাও করতে পারবেন।
ক্রমএকটি ML system design ইন্টারভিউতে আলাপের ধাপগুলো সঠিক ক্রমে সাজান (▲▼ চেপে সরান)
- সিদ্ধান্ত, ভুলের দাম আর পরিধি জিজ্ঞেস করে ঠিক করা
- Unit, অনুমানের মুহূর্ত আর label কখন জানা যায়, তা লেখা
- Offline metric, online metric আর guardrail আগে থেকে ঠিক করা
- অনুমানের মুহূর্তে পাওয়া যায় এমন feature, baseline আর প্রথম model
- Serving, fallback, shadow-canary-A/B আর চার স্তরের নজরদারি
(মাঝারি) একটি model-এর learning curve-এ ২০০ থেকে ১,৬০০ সারি পর্যন্ত training accuracy ০.৮২ থেকে ০.৮১৫, validation ০.৭৭ থেকে ০.৮০. সবচেয়ে কাজের পরের পদক্ষেপ কোনটি?
- আরও অনেক সারি জোগাড় করা
- Regularization আরও কড়া করা
- আরও নমনীয় model বা নতুন feature চেষ্টা করা
- তালাবন্ধ test খুলে দেখা model কেমন
(মাঝারি) ৩% positive-এর ডেটায় class_weight="balanced" দিয়ে logistic regression শেখানো হলো। আগের তুলনায় সাধারণত কী ঘটে?
- AUC অনেক বেড়ে যায়
- গড় অনুমিত সম্ভাবনা base rate-এর অনেক ওপরে ওঠে, AUC প্রায় একই থাকে
- সম্ভাবনা আরও ভালো calibrated হয়
- কোনো পরিবর্তন হয় না, কারণ ডেটা একই
(মাঝারি) একটি A/B test ১৪ দিনের জন্য পরিকল্পিত। দুই দলের আসল হার সমান হলেও কেউ রোজ দেখে প্রথম p < ০.০৫-এ থামান। ভুয়া জয়ের সম্ভাবনা মোটামুটি কেমন?
- ৫%-এর অনেক বেশি, প্রায় ২০% বা তারও ওপরে
- ঠিক ৫%
- ৫%-এর কম, কারণ বেশি তথ্য দেখা হয়েছে
- প্রায় ১০০%
(কঠিন) একটি জালিয়াতি-model যে অর্ডার সন্দেহ করে, তা বাতিল হয়, তাই সেগুলোর আসল ফল জানা যায় না। পরের model কীভাবে শেখানো ও মাপা উচিত?
- শুধু অনুমোদিত অর্ডারের label দিয়ে
- একটি ছোট এলোমেলো holdout রেখে, যেখানে কাউকে আটকানো হয় না, সেখানকার label দিয়ে
- বাতিল সব অর্ডারকে প্রতারণা ধরে নিয়ে
- Threshold কমিয়ে আরও বেশি অর্ডার বাতিল করে
(মাঝারি) একটি পণ্যে একটি বিক্রি হারানোর দাম ৳১২০, একটি একক বেশি রাখার দাম ৳৪০. পরের সপ্তাহের চাহিদার কোন quantile পর্যন্ত মজুদ রাখা উচিত?
- ৫০% (median)
- ২৫%
- ৩০০%-এর মতো কিছু, অর্থাৎ গড়ের তিন গুণ
- ৭৫%
(কঠিন) ঐতিহাসিক ডেটায় কুপন-পাওয়া ক্রেতাদের churn বেশি, কিন্তু কুপন মূলত ঝুঁকিপূর্ণ ক্রেতাদের দেওয়া হয়েছিল। ঝুঁকির দল ধরে ভাগ করলে প্রতিটি দলে কুপন-পাওয়াদের churn কম। কোন সিদ্ধান্ত সবচেয়ে যুক্তিসংগত?
- কুপন সম্ভবত উপকারী; অমাপা কারণ থাকতে পারে বলে এলোমেলো পরীক্ষায় নিশ্চিত হওয়া
- মোট ছবিই সঠিক: কুপন ক্ষতিকর
- দুটি ছবি বিপরীত, তাই ডেটা অর্থহীন
- একটি churn model-এ কুপন feature-এর SHAP মান দেখে সিদ্ধান্ত নেওয়া
শব্দকোষ
লেখার মধ্যে ডটেড দাগ দেওয়া শব্দে মাউস রাখুন বা চাপুন — অর্থ দেখাবে। এই পর্বের সব শব্দ এখানে একসাথে:
মনে রাখুন
- প্রতিটি দাবির পাশে baseline, ভাগের নাম আর অনিশ্চয়তা; পার্থক্য noise-এর ভেতরে হলে সরলটি।
- Learning curve-এর আকার বলে আরও ডেটা না অন্য model.
- Class weight ক্রম রাখে, সম্ভাবনা বিকৃত করে; threshold আসে ভুলের দাম থেকে।
- Importance আর SHAP model-এর ভর দেখায়, জগতের কারণ নয়; causal প্রশ্নে পরীক্ষা বা লেখা অনুমান।
- Model-এর সিদ্ধান্ত পরের label বদলায়: এলোমেলো holdout রাখুন।
- System design-এ model-এর আগে সিদ্ধান্ত, label আর metric; শেষে fallback আর নজরদারি।
আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ
- মেশিন লার্নিং · কোর্স হোম৭৭টি পর্বপুরো রোডম্যাপ। যে মডিউলে দুর্বল মনে হলো, সেখানে ফিরে যান।
- পর্ব ৭১ · ML system designনকশাদশ ধাপের কাঠামো, offline বনাম online, fallback আর feedback loop; অংশ ৭–৯-এর ভিত্তি।
- পর্ব ৭২ · ক্যাপস্টোনআবার করুনঅংশ ১০-এর STAR গল্পের উৎস; নিজে চালিয়ে নিজের সংখ্যা বানান।
- AI-এর ভিত্তি · ইন্টারভিউমৌলিকBase rate, leakage, nested CV আর আধুনিক AI-এর প্রাথমিক প্রশ্ন।
- System Design · Mock ইন্টারভিউপাশের ট্র্যাকবড় distributed ব্যবস্থার নকশার আলাপে হাত ঝালাই।
- Cloud আর DevOps · DevOps ইন্টারভিউপাশের ট্র্যাকDeploy, canary, নজরদারি আর incident-এর প্রশ্ন।