সরাসরি পর্বে যান
পর্ব ৭১ · ৭৭-এর মধ্যে · মডিউল ১৩

ML system design — একটি পুরো নকশা, শুরু থেকে নজরদারি পর্যন্ত

Machine Learning System Design — Requirements, Framing, Metrics, Feature Store, Serving with Fallbacks, A/B Evaluation, Feedback Loops and Monitoring

Taught in Bangla, this lesson designs a delivery-time promise system for a fictional shop in ten steps: requirements, quantile framing, capacity and latency estimates, point-in-time features and feature stores, offline versus online metrics, timeouts with fallbacks, a feedback-loop simulation with a blind holdout, and monitoring, with in-browser Python simulations and an interview checklist.

এই পর্বে যা শিখবেন

  • একটি ML system নকশার দশটি ধাপ, আর শুরুতে কোন প্রশ্নগুলো জিজ্ঞাসা করবেন
  • অনুরোধের হার, peak, latency budget আর storage-এর খামের পেছনের হিসাব নিজে করা
  • Label job, point-in-time feature, feature store আর training-serving skew-এর সম্পর্ক বোঝা
  • Offline metric, online metric আর guardrail বাছা, আর দুইয়ের অমিল simulation-এ দেখা
  • Fallback, feedback loop, cold start আর মানুষের হস্তক্ষেপসহ নকশা লেখা, আর ইন্টারভিউর জন্য একটি চেকলিস্ট পাওয়া

এই কোর্সে এতদিন প্রায় প্রতিটি পর্ব একটি অংশ গভীরে দেখেছে: framing (পর্ব ০২), label-এর মান (পর্ব ০৫), model বাছাই (পর্ব ৩৮), A/B test (পর্ব ৬২), distribution shift (পর্ব ৫৯)। AI-এর ভিত্তি কোর্সের পর্ব ৭৪-এ একটি AI প্রকল্পের জীবনচক্রও দেখেছেন। এই পর্ব সব টুকরো জোড়া লাগায়: একটি বাস্তবধর্মী সমস্যা নিয়ে শুরু থেকে নজরদারি পর্যন্ত একটি পুরো নকশা, যেভাবে কাজে বা ইন্টারভিউতে লিখতে হয়। চারটি চালানো যায় এমন ব্লক পাতাতেই চলে (ব্রাউজারের Python, NumPy, pandas, scikit-learn আর matplotlib); প্রথমবার scikit-learn নামতে প্রায় দশ সেকেন্ড লাগে।

১ · ML system design কী — দশ ধাপের একটি মানচিত্র

একজন স্থপতি বাড়ির নকশা শুরু করেন ইট দিয়ে নয়, প্রশ্ন দিয়ে: কতজন থাকবেন, বাজেট কত, জমি কেমন, বন্যার পানি কতদূর ওঠে। তারপর মোটা দাগের হিসাব: কয়টি ঘর, কত বর্গফুট। এরপর ভিত, দেয়াল, বিদ্যুৎ আর পানির লাইন। আর বাড়ি তৈরির পরও কাজ শেষ নয়: ফাটল দেখা, মেরামত, নতুন তলা। Model হলো বাড়ির একটি সুন্দর ঘর মাত্র; ভিত, লাইন আর রক্ষণাবেক্ষণ ছাড়া সেই ঘরে কেউ থাকতে পারে না।

ML system design মানে এমন একটি পুরো ব্যবস্থার নকশা, যা ডেটা থেকে শেখে, আসল ব্যবহারকারীর অনুরোধে সময়মতো উত্তর দেয়, ব্যর্থ হলে নিরাপদে নামে, আর সময়ের সঙ্গে নিজের মান মাপে ও ঠিক রাখে। সাধারণ system design (System Design কোর্সের পর্ব ০৬) থেকে তিনটি পার্থক্য: আচরণ কোডে লেখা নয়, ডেটা থেকে শেখা; সঠিকতা পরীক্ষায় হ্যাঁ বা না নয়, একটি পরিসংখ্যান; আর পৃথিবী বদলালে কোড একই থাকলেও system খারাপ হয়। এই পর্বে দশটি ধাপ ব্যবহার করব:

  1. প্রশ্ন আর পরিধি: কোন সিদ্ধান্ত, কার জন্য, কী সীমার মধ্যে।
  2. Framing: ML task, target, loss (পর্ব ০২-এর সাত আংটার শিকল)।
  3. Metric: offline, online আর guardrail, আগে থেকে লিখে রাখা।
  4. ডেটা আর label: কোথা থেকে, কখন জানা যায়, কতটা বিশ্বাসযোগ্য।
  5. Feature: অনুমানের মুহূর্তে কী জানা যায়, আর training-এও ঠিক সেটিই।
  6. Baseline আর model: সবচেয়ে সরল উত্তর আগে, তারপর তাকে হারানো।
  7. Training pipeline: পুনরুৎপাদনযোগ্য, যাচাইসহ, version-সহ।
  8. Serving: batch না online, latency, fallback.
  9. মূল্যায়ন: shadow, canary আর A/B test.
  10. নজরদারি আর পুনরাবৃত্তি: drift, দেরিতে আসা label, retrain, পরের সংস্করণ।

ধাপগুলো সরলরেখায় চলে না। Metric বাছতে গিয়ে প্রায়ই দেখা যায় label নেই; latency budget দেখে model বদলাতে হয়। তবু ক্রমটি একটি ভালো চেকলিস্ট। আমাদের সমস্যা: কাল্পনিক অনলাইন দোকান বাজারঘর checkout পাতায় ক্রেতাকে দেখাতে চায়, “এই অর্ডার এত ঘণ্টার মধ্যে পৌঁছাবে”। প্রথম ধাপ প্রশ্ন জিজ্ঞাসা, যা নিচের stepper-এ।

বাজারঘর · checkout-এ ডেলিভারির সময়ের প্রতিশ্রুতি · উত্তরগুলো ধরে নেওয়া
প্রশ্ন
ধরে নেওয়া উত্তর
নকশায় প্রভাব
  1. সিদ্ধান্ত। সংখ্যাটি একটি প্রতিশ্রুতি। খুব ছোট বললে দেরি হয়, ক্রেতা বাতিল করেন বা অভিযোগ করেন; খুব বড় বললে ক্রেতা কেনাই ছেড়ে দেন। তাই সফলতা মাপতে হবে বিক্রি আর কথা রাখা দুই দিক থেকে।
  2. আউটপুট। “গড়ে ২৬ ঘণ্টা” বললে প্রায় অর্ধেক অর্ডার দেরিতে পৌঁছায়। প্রতিশ্রুতির জন্য দরকার একটি উঁচু quantile: “৮০% অর্ডার এর মধ্যে”। পর্ব ০২-এ দেখেছেন, quantile শেখায় pinball loss.
  3. মাত্রা। সংখ্যা ছাড়া নকশা অনুমাননির্ভর। এখানে অনুরোধ কম, কিন্তু checkout পাতার পুরো latency লক্ষ্যের মধ্যে ETA-কে নিজের ভাগ মানতে হবে।
  4. ডেটা। ডেলিভারির আসল সময় জানা যায় পৌঁছানোর পর, অর্থাৎ অনুমানের এক থেকে পাঁচ দিন পরে (label delay). তাই নজরদারি আর retrain-এর হিসাবে এই দেরি ধরতে হবে।
  5. ব্যর্থতা। ETA একটি সহায়ক তথ্য, অর্থ লেনদেনের অংশ নয়। Model ধীর বা বন্ধ হলেও checkout চলবে, একটি সরল নিয়মের উত্তর দিয়ে।
  6. পরিধি। রুট বাছাই বা চার্জ নির্ধারণ আলাদা সমস্যা। ইন্টারভিউতে এগুলো মুখে বলে বাদ দেওয়া সময় বাঁচায় আর দেখায় যে আপনি সীমা টানতে জানেন।

২ · Requirement আর framing — checkout-এ ডেলিভারির প্রতিশ্রুতি

Functional requirement: checkout পাতায় ঠিকানা আর ঝুড়ি দেখে একটি সংখ্যা, “N ঘণ্টার মধ্যে পৌঁছাবে”; ঠিকানা বদলালে সংখ্যাও বদলাবে; প্রতিটি অনুমান তার model-এর version-সহ লগ হবে। Non-functional requirement: ETA অংশের p99 latency ৬০ ms-এর নিচে; বড় sale-এর ভিড়েও চলবে; model বন্ধ থাকলেও checkout চলবে; প্রতিশ্রুতি অন্তত ৮০% অর্ডারে রক্ষা হবে, আর প্রতিটি অঞ্চলে (zone) আলাদাভাবেও।

Framing. Unit একটি অর্ডার; অনুমানের মুহূর্ত checkout পাতা খোলা; target “অর্ডার নিশ্চিত থেকে ক্রেতার হাতে পৌঁছানো, ঘণ্টায়”; বাতিল অর্ডারের target নেই। প্রতিশ্রুতির জন্য আমরা শর্তসাপেক্ষ ৮০%-quantile অনুমান করি, অর্থাৎ quantile regression, যার loss τ = ০.৮-এর pinball (পর্ব ২৪)। কেন ০.৮? এটি এখনো একটি অনুমান; অংশ ৬-এর simulation আর পরে A/B test এটি যাচাই করবে। আরেকটি বিকল্প ছিল পরিসর দেখানো (“২০ থেকে ৩২ ঘণ্টা”), যার জন্য পর্ব ৫৮-এর conformal পদ্ধতি কাজে লাগে; কিন্তু ছোট পর্দায় একটি সংখ্যা বেশি পরিষ্কার, তাই প্রথম সংস্করণে একটি সংখ্যা।

মূল ধারণা

Framing-এর প্রতিটি পছন্দ পরের সব ধাপে ছড়ায়। “গড় সময়” বললে loss squared, metric RMSE, আর প্রায় অর্ধেক প্রতিশ্রুতি ভাঙে। “৮০%-quantile” বললে loss pinball, metric coverage আর pinball, আর প্রতিশ্রুতি একটু লম্বা হয়। কোনটি ঠিক, তা গণিত বলে না, ব্যবসার দাম বলে।

কখন ML নয়? শুরুর সংস্করণ হতে পারে একটি টেবিল: প্রতিটি zone-এর গত মাসের ৮০% quantile. পর্ব ০২-এর নিয়মে এটিই baseline, আর অংশ ৭-এ এটিই fallback হবে। ML তখনই যোগ করবেন, যখন এই টেবিলকে মাপা যায় এমন পার্থক্যে হারানো যায়, আর সেই পার্থক্য রক্ষণাবেক্ষণের খরচের চেয়ে বেশি।

৩ · খামের পেছনের হিসাব — অনুরোধ, latency আর storage

System Design কোর্সের পর্ব ০৩-এর back-of-the-envelope নিয়মে, প্রতিটি অনুমান আলাদা করে লিখে। সংখ্যাগুলো বাজারঘরের জন্য ধরে নেওয়া, কোনো আসল দোকানের পরিসংখ্যান নয়: দিনে ৫০,০০০ অর্ডার; একটি অর্ডারের আগে গড়ে চারবার checkout পাতা খোলা হয় (অনেকে না কিনে ফেরেন); প্রতিবার দুটি অনুমান (সাধারণ আর পরের দিনের ডেলিভারি); সন্ধ্যার ভিড় গড়ের তিন গুণ (peak factor), আর বড় sale-এর দিন তার আরও পাঁচ গুণ।

দিনে ৫০,০০০ অর্ডার · ৪টি checkout view/অর্ডার · peak ×৩ · sale ×৫ · ২টি অনুমান/view
ধাপ
হিসাব
ফল
  1. দিনের অনুরোধ। প্রতিটি অর্ডারের আগে চারবার checkout পাতা খোলা হয় ধরে দিনে ২,০০,০০০ view. অনুমান view-প্রতি, অর্ডার-প্রতি নয়: যিনি কেনেননি, তিনিও সংখ্যাটি দেখেছেন।
  2. গড় হার। একদিনে ৮৬,৪০০ সেকেন্ড, তাই গড়ে সেকেন্ডে ২.৩টি অনুরোধ। ছোট সংখ্যা, কিন্তু গড় দিয়ে নকশা হয় না।
  3. ভিড়। সন্ধ্যায় তিন গুণ, sale-এর দিনে আরও পাঁচ গুণ: সেকেন্ডে ৩৪.৭টি অনুরোধ, দুটি অনুমান করে ৬৯.৪টি অনুমান। নকশা হয় এই সংখ্যার জন্য।
  4. Latency budget. Checkout API-র পুরো p99 লক্ষ্য ৩০০ ms; তার ২০%, অর্থাৎ ৬০ ms, ETA-র ভাগ। সেই ৬০ ms আবার ভাগ: network ৯, feature পড়া ২১, model ২১, আর অপ্রত্যাশিতের জন্য ৯ ms.
  5. Storage. প্রতিটি অনুমানের লগ (feature, অনুমান, version, সময়) প্রায় ১ KB ধরে বছরে ৭৩ GB. Label-সহ training সারি বছরে ১ কোটি ৮২ লাখ ৫০ হাজার, ২০০ byte করে প্রায় ৩.৬৫ GB: একটি ল্যাপটপের memory-তেই ধরে।
  6. যন্ত্র। একটি অনুমানে ২১ ms লাগলে একটি core সেকেন্ডে প্রায় ৪৭টি করে। ৬৯.৪-এর জন্য দেড়টি core; দ্বিগুণ জায়গা রেখে চারটি core, আর একটি বিকল হলেও চলার জন্য অন্তত দুটি copy. সংখ্যার দিক থেকে এটি ছোট system; কঠিন অংশ latency-র লেজ, সঠিক feature আর ব্যর্থতার পথ।

একই হিসাব একটি ছোট function-এ, যাতে অনুমান বদলে সঙ্গে সঙ্গে ফল দেখা যায়। শেষ লাইনে অর্ডার দশ গুণ করে দেখা হয়েছে।

# বাজারঘরের checkout-এ ডেলিভারির সময়: খামের পেছনের হিসাব (সব সংখ্যা ধরে নেওয়া)
def capacity(orders_day=50_000, views_per_order=4, preds_per_view=2,
             peak=3, sale_day=5, budget_ms=300, eta_share=0.2,
             log_bytes=1_000, row_bytes=200, years=1):
    views = orders_day * views_per_order          # checkout পাতা খোলা, দিনে
    avg_rps = views / 86_400
    peak_rps = avg_rps * peak                     # সন্ধ্যার ভিড়
    sale_rps = peak_rps * sale_day                # বড় sale-এর দিনের ভিড়
    eta_ms = budget_ms * eta_share                # পুরো checkout API-র ভাগ
    split = {"network": 0.15, "features": 0.35, "model": 0.35, "spare": 0.15}
    logs_gb = views * log_bytes * 365 * years / 1e9      # প্রতিটি অনুমানের লগ
    train_gb = orders_day * row_bytes * 365 * years / 1e9  # label-সহ training সারি
    return {"checkout views/day": views,
            "avg req/s": round(avg_rps, 1), "peak req/s": round(peak_rps, 1),
            "sale-day req/s": round(sale_rps, 1),
            "predictions/s at sale peak": round(sale_rps * preds_per_view, 1),
            "ETA budget ms": eta_ms,
            "budget split ms": {k: round(v * eta_ms, 1) for k, v in split.items()},
            "prediction logs GB/year": round(logs_gb, 1),
            "training rows/year": orders_day * 365,
            "training data GB/year": round(train_gb, 2)}

for k, v in capacity().items():
    print(f"{k:28s} {v}")
print("10x orders, sale-day req/s:", capacity(orders_day=500_000)["sale-day req/s"])

আসল আউটপুট (ব্রাউজারের Python):

checkout views/day           200000
avg req/s                    2.3
peak req/s                   6.9
sale-day req/s               34.7
predictions/s at sale peak   69.4
ETA budget ms                60.0
budget split ms              {'network': 9.0, 'features': 21.0, 'model': 21.0, 'spare': 9.0}
prediction logs GB/year      73.0
training rows/year           18250000
training data GB/year        3.65
10x orders, sale-day req/s: 347.2

দশ গুণ অর্ডারেও sale-এর ভিড়ে সেকেন্ডে ৩৪৭টি অনুরোধ, যা কয়েকটি সাধারণ server-এর কাজ। শিক্ষা দুটি। প্রথম, অনেক ML system-এর throughput সাধারণ web সেবার তুলনায় ছোট; ভারী অংশ প্রায়ই training আর লগ, অনুমান নয়। দ্বিতীয়, latency budget-ই model বাছাইয়ের সীমা: ২১ ms-এ একটি ছোট gradient boosting সহজে চলে, কিন্তু শত শত tree-র বিশাল ensemble বা প্রতিটি অনুরোধে database-এ দশটি query চলবে না। Latency budget আর p99-এর তত্ত্ব System Design কোর্সের পর্ব ০৪-এ।

৪ · ডেটা, label আর feature — feature store-এর ধারণা

Label job. প্রতিদিন একটি job অর্ডারের ঘটনা থেকে label বানায়: “নিশ্চিত” থেকে “হাতে পৌঁছানো” পর্যন্ত ঘণ্টা। প্রশ্নগুলো ছোট নয়: ক্রেতা বাড়িতে না থাকলে দ্বিতীয় চেষ্টার সময় কি গোনা হবে? ফেরত অর্ডারের label কী? পর্ব ০৫-এর মতো, এই নিয়মগুলো লিখে রাখতে হয় আর label-এর একটি এলোমেলো নমুনা হাতে মিলিয়ে দেখতে হয়, কারণ courier-এর app-এ “পৌঁছেছে” চাপার সময় আর আসল পৌঁছানোর সময় সবসময় এক নয়।

Feature. চারটি দল: অর্ডার (zone, hub থেকে দূরত্ব, পণ্যের সংখ্যা), hub-এর বর্তমান চাপ (গত এক ঘণ্টার অর্ডার ÷ courier-সংখ্যা), আবহাওয়া (বৃষ্টি), আর সময় (ঘণ্টা, সপ্তাহের দিন, ঈদের আগের সপ্তাহ কি না)। নিয়ম পর্ব ০২-এর: শুধু point-in-time feature, অর্থাৎ checkout-এর মুহূর্তে যা জানা যায়। “ওই দিনের মোট অর্ডার” training-এ সহজে পাওয়া যায়, কিন্তু checkout-এর সময় দিন শেষ হয়নি: এটি ভবিষ্যতের তথ্য, আর একে ব্যবহার করলে offline ফল মিথ্যা ভালো দেখায় (AI-এর ভিত্তি কোর্সের পর্ব ৫৬)।

Training-serving skew. সবচেয়ে নীরব ভুল: training-এ hub-এর চাপ হিসাব হয়েছে data warehouse-এর SQL-এ (পর্ব ৬১), আর online-এ app-এর কোডে, একটু আলাদা সংজ্ঞায় (ধরুন একটিতে বাতিল অর্ডার গোনা হয়, অন্যটিতে হয় না)। Model একটি সংখ্যা শিখেছে, পায় আরেকটি। এর নাম training-serving skew. প্রতিকার: একটি সংজ্ঞা, দুই জায়গায় একই কোড, আর online-এ লগ করা feature-এর সঙ্গে offline-এ আবার হিসাব করা feature-এর নিয়মিত তুলনা। একই preprocessing-কে model-এর সঙ্গে একটি pipeline-এ বাঁধা (AI-এর ভিত্তি কোর্সের পর্ব ৬৪) এর একটি অংশ সমাধান করে; packaging-এর বিস্তার পর্ব ৬৮ (Model serving — FastAPI, batch scoring আর ONNX)-এ।

Feature store-এর ধারণা. যখন অনেক model একই feature ব্যবহার করে, প্রতিষ্ঠানগুলো প্রায়ই একটি feature store বানায়: feature-এর সংজ্ঞা এক জায়গায়, আর দুটি ভান্ডার। Offline ভান্ডার প্রতিটি মানের পুরো ইতিহাস সময়সহ রাখে, যাতে training-এর প্রতিটি সারির জন্য “তখন যা জানা ছিল” তা জোড়া যায় (point-in-time join). Online ভান্ডার শুধু সর্বশেষ মান রাখে, key দিয়ে কয়েক ms-এ পড়া যায় (যেমন hub_id → load). বাজারঘরের প্রথম সংস্করণে আলাদা টুল লাগবে না: একটি টেবিল আর একটি cache-ই যথেষ্ট (System Design কোর্সের পর্ব ২৮)। তবে ধারণাটি, অর্থাৎ এক সংজ্ঞা আর সময়সহ ইতিহাস, প্রথম দিন থেকেই মানা ভালো।

Cold start. বাজারঘর একটি নতুন জেলায় hub খুলল; সেখানে কোনো ডেলিভারির ইতিহাস নেই। Cold start-এর সাধারণ পথ: কাছের অনুরূপ zone-এর rule আর দূরত্বের feature দিয়ে শুরু, প্রথম কয়েক সপ্তাহ বাড়তি buffer (যেমন ০.৯-quantile), আর নতুন zone-এর coverage আলাদা করে প্রতিদিন দেখা। যথেষ্ট label জমলে সেই zone model-এ সাধারণ zone হয়ে যায়।

৫ · Baseline, model আর training pipeline — পুরো নকশার ছবি

Baseline: zone-এর ৮০% quantile. প্রথম model: tabular ডেটা, কয়েক হাজার থেকে কয়েক কোটি সারি, ২১ ms-এর budget, তাই quantile loss-সহ একটি ছোট histogram gradient boosting (পর্ব ৩৮, পর্ব ৩৬)। Deep learning-এর কোনো বিশেষ কারণ এখানে নেই। একাধিক quantile একসঙ্গে লাগলে সেগুলো যেন একে অপরকে না কাটে, তা দেখতে হবে (quantile crossing).

Training pipeline প্রতি সপ্তাহে একবার: (১) গত ছয় মাসের label-সহ অর্ডার, শেষ সাত দিন বাদ (তাদের label এখনো অসম্পূর্ণ); (২) point-in-time join; (৩) ডেটার মৌলিক যাচাই (সারির সংখ্যা, missing, অসম্ভব মান); (৪) সময় ধরে ভাগ: পুরোনো অংশে শেখা, সর্বশেষ দুই সপ্তাহে মূল্যায়ন (পর্ব ৫২-এর backtest-এর মতো); (৫) baseline আর চালু model-এর পাশে pinball, coverage আর zone-ভিত্তিক coverage; (৬) সীমা পার হলে model registry-তে version, metric, ডেটার সময়কাল আর কোডের commit-সহ জমা। পর্ব ০৪-এর seed আর config-এর নিয়ম এখানে বাধ্যতামূলক, কারণ ছয় মাস পরে “এই model কোন ডেটায় শেখা?” প্রশ্নের উত্তর লাগবেই। এসব test-এর বিস্তার পর্ব ৬৯ (ML system-এর test আর নজরদারি — data test, model test আর drift)-এ।

বাজারঘরের ETA system: অনলাইন পথ আর অফলাইন পথ

উপরে প্রতিটি checkout-এর অনুরোধ; নিচে নিয়মিত চলা job. ভাঙা দাগ = একই feature-এর সংজ্ঞা দুই জায়গায়

Architecture of the delivery-time estimate system: online path and offline path অনলাইন পথ · প্রতিটি checkout (p99 ≤ ৬০ ms) অফলাইন পথ · নিয়মিত job ক্রেতার checkoutঠিকানা, ঝুড়ি Checkout APIপুরো p99 ৩০০ ms ETA servicemodel: q = 0.8 অনুমানtimeout হলে zone-এর rule Online feature storehub-এর চাপ, বৃষ্টি Prediction logfeature, অনুমান, version Offline feature storeসময়সহ পুরো ইতিহাস Order DB + scanঅর্ডার, courier-এর ঘটনা Label jobনিশ্চিত → হাতে, ঘণ্টা Training setpoint-in-time join Train + offline evalbaseline-এর পাশে Model registryversion, metric, ডেটা→ shadow, canary নজরদারিলগ + দেরির label: coverage, drift, p99, fallback একই সংজ্ঞা retrain-এর সংকেত
ছবি ৫.১ — অনলাইন পথে প্রতিটি অনুরোধ ETA service-এ আসে, যা online feature store থেকে সর্বশেষ মান পড়ে, অনুমান দেয় (বা timeout হলে rule), আর লগ লেখে। অফলাইন পথে label job আর offline feature store-এর ইতিহাস মিলে training set; শেখা model registry-তে জমা হয়ে shadow আর canary হয়ে চালু হয়। নজরদারি লগ আর দেরিতে আসা label মিলিয়ে retrain-এর সংকেত দেয়।

Batch না online? সব ঠিকানা আর ঝুড়ির জন্য আগে থেকে ETA হিসাব করে রাখা (batch) সম্ভব নয়, কারণ hub-এর চাপ আর বৃষ্টি প্রতি মুহূর্তে বদলায়, আর ঠিকানা-ঝুড়ির জোড়া অসংখ্য। তাই অনুমান online. তবে একটি মাঝামাঝি পথ আছে: zone-এর rule-এর টেবিল রাতে batch-এ হিসাব হয়, আর সেটিই fallback. Serving-এর ধরনগুলোর বিস্তার পর্ব ৬৮-এ, আর অনেক বড় ডেটায় training পর্ব ৭০ (বড় ডেটায় ML — out-of-core, incremental learning আর Polars/DuckDB)-এ।

৬ · Offline বনাম online — সেরা MAE কেন সেরা ব্যবসা নয়

একটি offline metric পুরোনো ডেটায় model-এর মান মাপে; একটি online metric চালু অবস্থায় ব্যবসার ফল মাপে। দুটি এক দিকে চলবে, এমন কোনো নিশ্চয়তা নেই। নিচের module কাল্পনিক বাজারঘরের অর্ডার বানায়: zone (০ ঢাকা, ১ কাছের জেলা, ২ দূরের জেলা), দূরত্ব, বৃষ্টি, hub-এর চাপ আর পণ্যের সংখ্যা; ডেলিভারির ঘণ্টা ডানে-হেলানো, দূরের zone-এ অনিশ্চয়তা বেশি। online_value একটি simulated ব্যবসার নিয়ম: প্রতিশ্রুতি zone-এর স্বাভাবিক সময়ের (৮, ২৪, ৪৮ ঘণ্টা) চেয়ে যত লম্বা, ক্রেতার কেনার সম্ভাবনা তত কমে; আর আসল সময় প্রতিশ্রুতি ছাড়ালে ৩৫% অর্ডার বাতিল বা ফেরত হয়। এই সংখ্যাগুলো উদাহরণের জন্য বানানো, কোনো গবেষণার ফল নয়।

# বাজারঘর (কাল্পনিক দোকান): checkout-এ দেখানো ডেলিভারির সময়, seeded ডেটা
import numpy as np
import pandas as pd

FEATS = ["zone", "dist", "rain", "load", "n_items"]

def base_hours(df):                              # আসল (অজানা) গড় প্রক্রিয়া, ঘণ্টায়
    return ((5 + 0.06 * df.dist + np.array([0, 14, 30])[df.zone])
            * (1 + 0.3 * df.rain) * df.load * (1 + 0.03 * df.n_items))

def orders(n, seed=71):
    rng = np.random.default_rng(seed)
    zone = rng.choice(3, n, p=[0.5, 0.3, 0.2])   # 0 ঢাকা, 1 কাছের জেলা, 2 দূরের জেলা
    dist = rng.gamma(2 + 2 * zone, np.array([3, 10, 30])[zone])
    df = pd.DataFrame({"zone": zone, "dist": dist.round(1),
                       "rain": rng.binomial(1, 0.2, n),
                       "load": rng.normal(1, 0.15, n).clip(0.6, 1.6).round(2),
                       "n_items": rng.integers(1, 6, n)})
    noise = rng.lognormal(0, 0.25 + 0.1 * df.zone, n)   # দূরে অনিশ্চয়তা বেশি
    df["hours"] = (base_hours(df) * noise).round(1)
    return df

def online_value(promise, actual, zone):         # simulated ব্যবসার ফল, ১,০০০ checkout-এ
    buy = 0.92 * np.exp(-0.012 * (promise - np.array([8, 24, 48])[zone]).clip(0))
    late = actual > promise
    done = buy * (1 - 0.35 * late)              # দেরি হলে ৩৫% বাতিল বা ফেরত
    return 1000 * done.mean(), 100 * late.mean()

ছয়টি প্রার্থী: zone-এর median (rule), squared loss-এর linear regression, আর চারটি histogram gradient boosting: squared loss, absolute loss (median), quantile ০.৮ আর quantile ০.৯৫. সবার অনুমান পূর্ণ ঘণ্টায় ওপরে গোল করে প্রতিশ্রুতি বানানো হয়েছে, আর ৩,০০০টি নতুন অর্ডারে offline MAE আর simulated online ফল পাশাপাশি।

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.ensemble import HistGradientBoostingRegressor as HGB
from sklearn.linear_model import LinearRegression
from bazar_eta import orders, online_value, FEATS

tr, te = orders(3000, seed=71), orders(3000, seed=710)
X, y = tr[FEATS], tr.hours
rule = tr.groupby("zone").hours.median()          # baseline: zone-এর median
cands = {"rule: zone median": rule[te.zone].to_numpy(),
         "linear (squared)": LinearRegression().fit(X, y).predict(te[FEATS])}
for name, kw in [("HGB squared", {}), ("HGB median", {"loss": "absolute_error"}),
                 ("HGB q=0.8", {"loss": "quantile", "quantile": 0.8}),
                 ("HGB q=0.95", {"loss": "quantile", "quantile": 0.95})]:
    m = HGB(max_iter=150, learning_rate=0.1, random_state=0, **kw).fit(X, y)
    cands[name] = m.predict(te[FEATS])
rows = []
for name, p in cands.items():
    p = np.ceil(p)                                 # ক্রেতাকে পূর্ণ ঘণ্টায় প্রতিশ্রুতি
    value, late = online_value(p, te.hours.to_numpy(), te.zone.to_numpy())
    rows.append({"model": name, "MAE_h": np.abs(p - te.hours).mean(),
                 "late_%": late, "done_per_1000": value})
t = pd.DataFrame(rows).set_index("model").round(2)
print(t)
print("best offline:", t.MAE_h.idxmin(), "| best online:", t.done_per_1000.idxmax())
fig, ax = plt.subplots(figsize=(6, 4))
ax.scatter(t.MAE_h, t.done_per_1000)
for name, r in t.iterrows():
    ax.annotate(name, (r.MAE_h, r.done_per_1000), fontsize=8)
ax.set_xlabel("offline MAE (hours, lower is better)")
ax.set_ylabel("simulated completed orders per 1000")
ax.set_title("Best offline model is not best online")

আসল আউটপুট (ব্রাউজারের Python):

                   MAE_h  late_%  done_per_1000
model
rule: zone median   7.51   40.17         781.08
linear (squared)    7.80   44.00         741.67
HGB squared         7.48   36.63         767.56
HGB median          6.95   42.40         762.44
HGB q=0.8           9.44   19.17         785.71
HGB q=0.95         14.70    8.00         765.91
best offline: HGB median | best online: HGB q=0.8

Offline-এ সেরা median model (MAE ৬.৯৫ ঘণ্টা), কারণ MAE-র সেরা উত্তর median. কিন্তু তার প্রতিশ্রুতি ৪২.৪% অর্ডারে ভাঙে, আর online ফল ৭৬২.৪৪. Online-এ সেরা ০.৮-quantile model: MAE সবচেয়ে খারাপদের একটি (৯.৪৪), কিন্তু দেরি মাত্র ১৯.১৭%, আর ফল ৭৮৫.৭১. ০.৯৫ বেশি সাবধানী: দেরি ৮%, কিন্তু লম্বা প্রতিশ্রুতিতে ক্রেতা কেনা ছাড়েন, ফল ৭৬৫.৯১. একটি অবাক করা দিক: সরল zone-median rule (৭৮১) সব squared আর median model-কে online-এ হারায়, কারণ তার ছোট প্রতিশ্রুতি বেশি ক্রেতা ধরে রাখে। ছবিতে বিন্দুগুলো একটি সরলরেখায় নেই; MAE কমা মানে ব্যবসা বাড়া নয়। সতর্কতা: এই ফল সম্পূর্ণ নির্ভর করে online_value-এর বানানো নিয়মের ওপর। আসল জগতে সেই নিয়ম অজানা, তাই শেষ বিচার A/B test.

তাহলে offline-এ কী মাপবেন? যে metric ব্যবসার ফলের সঙ্গে একই দিকে চলে বলে যুক্তি আর অতীতের পরীক্ষা দেখায়। নিচের stepper metric বাছাইয়ের ধাপগুলো সাজায়।

লক্ষ্য: প্রতিশ্রুতি রাখা আর বিক্রি না হারানো · সব সীমা লঞ্চের আগে লিখে রাখা
স্তর
মাপ
কেন বা সীমা
  1. লক্ষ্য। একটি north star: প্রতি ১,০০০ checkout-এ সম্পন্ন অর্ডার। এটি বিক্রি (লম্বা প্রতিশ্রুতিতে কমে) আর কথা রাখা (দেরিতে বাতিল) দুটিই ধরে।
  2. Offline প্রধান। Model যা অনুমান করে (৮০% quantile), তার সঠিক মাপ pinball loss আর coverage: কত ভাগ অর্ডার প্রতিশ্রুতির মধ্যে পৌঁছাল। Coverage ৭৮–৮২%-এর বাইরে গেলে model ভুল quantile শিখছে।
  3. Offline সহায়ক। MAE দেখানো যায়, কিন্তু সিদ্ধান্ত নয়। জরুরি হলো slice: সব মিলিয়ে ৮০% হলেও দূরের zone-এ ৬০% হলে সেই এলাকার ক্রেতারা প্রতারিত বোধ করবেন।
  4. Online প্রধান। পর্ব ৬২-এর মতো A/B test, randomisation-এর একক ক্রেতা (একজন ক্রেতা বারবার আলাদা সংখ্যা দেখলে বিভ্রান্ত হবেন)। Sample size আর সময় আগে থেকে হিসাব।
  5. Guardrail. উন্নত হওয়ার দরকার নেই, কিন্তু খারাপ হওয়া চলবে না: দেরির হার, বাতিল, “আমার অর্ডার কোথায়” কল, p99 latency, fallback-এর হার।
  6. নিয়ম। লঞ্চের নিয়ম পরীক্ষার আগে লেখা: primary-তে উন্নতি আর কোনো guardrail সীমা পেরোয়নি। ফল দেখার পর নিয়ম বদলালে পর্ব ৬৩-এর ভুল ব্যাখ্যার ফাঁদে পড়বেন।

A/B test-এর আগে দুটি নিরাপদ ধাপ। Shadow deployment: নতুন model আসল অনুরোধে পাশাপাশি চলে, অনুমান লগ হয়, কিন্তু ক্রেতা দেখেন পুরোনোটি; এতে latency, ত্রুটি আর feature-এর অমিল ধরা পড়ে, কোনো ঝুঁকি ছাড়া। তারপর canary: ১–৫% ক্রেতার কাছে চালু, guardrail দেখে ধাপে ধাপে বাড়ানো (Cloud & DevOps কোর্সের পর্ব ৫৯)। মনে রাখুন, shadow-তে latency আর সঠিক feature যাচাই হয়, কিন্তু ক্রেতার আচরণ নয়: প্রতিশ্রুতি না দেখালে তার প্রভাব মাপা যায় না।

৭ · Serving আর fallback — model না পারলে কী

ETA service প্রতিটি অনুরোধে দুটি কাজ করে: online feature store থেকে hub-এর চাপ আর বৃষ্টি পড়া, তারপর model চালানো। দুটিরই লেজ আছে: বেশিরভাগ অনুরোধ দ্রুত, কিন্তু কিছু অনেক ধীর, আর কখনো model আটকে যায় (memory-র চাপ, নতুন version লোড হওয়া)। সমাধান System Design কোর্সের পর্ব ৪৮-এর: একটি timeout, আর সময় পেরোলে একটি fallback, এখানে zone-এর ৮০% quantile টেবিল, যা memory-তে থাকে আর প্রায় ১ ms নেয়। নিচের ব্লক simulated latency (feature-এর জন্য median ৮ ms, model-এর জন্য ১৫ ms, ২% অনুরোধে ২ সেকেন্ড আটকে থাকা) দিয়ে পাঁচটি timeout তুলনা করে।

import numpy as np
import pandas as pd
from sklearn.ensemble import HistGradientBoostingRegressor as HGB
from bazar_eta import orders, online_value, FEATS

tr, te = orders(3000, seed=71), orders(5000, seed=711)
q80 = HGB(loss="quantile", quantile=0.8, max_iter=150, random_state=0)
model_p = np.ceil(q80.fit(tr[FEATS], tr.hours).predict(te[FEATS]))
rule_p = np.ceil(tr.groupby("zone").hours.quantile(0.8)[te.zone].to_numpy())
y, z = te.hours.to_numpy(), te.zone.to_numpy()

rng = np.random.default_rng(42)                  # প্রতিটি অনুরোধের latency (ms), simulated
feat_ms = rng.lognormal(np.log(8), 0.5, len(te))            # feature store থেকে পড়া
model_ms = rng.lognormal(np.log(15), 0.6, len(te))          # model চালানো
model_ms[rng.random(len(te)) < 0.02] = 2000                 # ২% অনুরোধে model আটকে যায়
need = feat_ms + model_ms
rows = []
for timeout in [25, 40, 60, 100, np.inf]:
    fb = need > timeout                          # সময় পেরোলে rule-এর উত্তর
    p = np.where(fb, rule_p, model_p)
    ms = np.where(fb, timeout + 1, need)         # rule প্রায় ১ ms নেয়
    done, late = online_value(p, y, z)
    rows.append({"timeout_ms": timeout, "fallback_%": 100 * fb.mean(),
                 "p50_ms": np.percentile(ms, 50), "p99_ms": np.percentile(ms, 99),
                 "MAE_h": np.abs(p - y).mean(), "late_%": late, "done_per_1000": done})
print(pd.DataFrame(rows).round(1).to_string(index=False))
for name, p in [("model only", model_p), ("rule only", rule_p)]:
    done, late = online_value(p, y, z)
    print(f"{name:10s} MAE {np.abs(p - y).mean():.1f}  late {late:.1f}%  done {done:.1f}")

আসল আউটপুট (ব্রাউজারের Python):

 timeout_ms  fallback_%  p50_ms  p99_ms  MAE_h  late_%  done_per_1000
       25.0        48.0    24.4    26.0   10.2    19.5          780.1
       40.0        14.5    24.4    41.0    9.9    19.1          783.7
       60.0         4.1    24.4    61.0    9.9    19.2          783.6
      100.0         2.0    24.4   101.0    9.8    19.2          783.8
        inf         0.0    24.4  2007.7    9.8    19.1          784.3
model only MAE 9.8  late 19.1%  done 784.3
rule only  MAE 10.9  late 19.1%  done 776.0

Timeout ছাড়া p99 প্রায় ২,০০৮ ms: আটকে থাকা ২% অনুরোধ পুরো checkout-কে দুই সেকেন্ড ধরে রাখে। ৬০ ms timeout-এ ৪.১% অনুরোধ rule-এর উত্তর পায়, p99 নামে ৬১ ms-এ, আর ব্যবসার ফল ৭৮৪.৩ থেকে মাত্র ৭৮৩.৬. খুব কড়া timeout (২৫ ms) অর্ধেক অনুরোধকে rule-এ পাঠায়; ফল ৭৮০.১, rule-এর একার ৭৭৬-এর দিকে। Fallback ভালো কাজ করছে কারণ rule-টিও একই ৮০% quantile লক্ষ্য করে: দেরির হার একই (দুটিতেই ১৯.১%), শুধু প্রতিশ্রুতি একটু কম ধারালো। শিক্ষা: fallback যেন একই প্রশ্নের একটি সরল উত্তর হয়, শুধু একটি ফাঁকা জায়গা নয়। আর fallback-এর হার নিজেই একটি নজরদারির সংকেত: হঠাৎ বাড়লে model বা feature store-এ গোলমাল।

মানুষের হাত. কিছু ঘটনা কোনো model আগে দেখেনি: বন্যায় একটি জেলার রাস্তা বন্ধ, হরতাল, বড় সড়কে দুর্ঘটনা। তখন operations দলের হাতে একটি সুইচ থাকা উচিত: একটি zone-এ নির্দিষ্ট ঘণ্টা যোগ করা, বা সেই zone-এ ETA দেখানো বন্ধ রাখা। এটি human-in-the-loop-এর সরল রূপ; প্রতারণা ধরার model-এ এর রূপ হলো সন্দেহজনক অর্ডারের একটি সারি, যা একজন মানুষ যাচাই করেন। প্রতিটি হস্তক্ষেপ লগ হবে, যাতে পরে সেই সময়ের label training থেকে আলাদা রাখা যায়।

৮ · Feedback loop, নজরদারি আর পুনরাবৃত্তি

চালু model নিজের ভবিষ্যৎ training ডেটা বদলাতে পারে (feedback loop). পর্ব ৫৩-এ দেখেছেন, যা সুপারিশ হয় তা-ই বেশি বিক্রি হয়; পর্ব ৬০-এ, যাঁরা বাকি পান না তাঁদের label কখনো আসে না (selective labels). ETA-র ক্ষেত্রে একটি সূক্ষ্ম রূপ: hub-এর কর্মীরা checkout-এর প্রতিশ্রুতি দেখেন। প্রতিশ্রুতিতে হাতে সময় থাকলে তাঁরা অন্য জরুরি অর্ডার আগে পাঠান, তাই অর্ডারটি একটু দেরিতে পৌঁছায়। পরের সপ্তাহের label-এ সেই দেরি ঢোকে, model আরও লম্বা প্রতিশ্রুতি শেখে, আর চক্র চলে। নিচের simulation-এ hub বাড়তি সময়ের ৬০% খরচ করে ফেলে, আর প্রতিশ্রুতি হলো model-এর অনুমানের ১.২ গুণ। তুলনার কৌশল: এলোমেলো ১০% অর্ডারে hub প্রতিশ্রুতি দেখে না (holdout), আর model শেখে শুধু সেই অংশে।

import numpy as np
import pandas as pd
from sklearn.linear_model import LinearRegression
from bazar_eta import orders

def design(df):                                  # সরল feature: zone one-hot আর দূরত্ব
    return np.c_[df.zone == 1, df.zone == 2, df.dist, df.rain, df.load]

def run(strategy, rounds=6, slack=0.6, buffer=1.2):
    hist = orders(4000, seed=7100)               # শুরুর ডেটা: প্রতিশ্রুতি দেখানোর আগের যুগ
    model = LinearRegression().fit(design(hist), hist.hours)
    out = []
    for r in range(rounds):
        week = orders(4000, seed=7101 + r)
        t0 = week.hours.to_numpy()               # প্রতিশ্রুতি না থাকলে যা লাগত
        promise = buffer * model.predict(design(week))
        blind = np.random.default_rng(r).random(len(week)) < 0.10   # ১০% hub প্রতিশ্রুতি দেখে না
        seen = (strategy == "no holdout") | ~blind
        # hub প্রতিশ্রুতি দেখলে হাতে সময় থাকলে ঢিলে দেয়: বাড়তি সময়ের ৬০% খরচ হয়
        actual = t0 + seen * slack * np.clip(promise - t0, 0, None)
        out.append({"round": r, "promise_h": promise.mean(), "actual_h": actual.mean(),
                    "on_time_%": 100 * (actual <= promise).mean()})
        train = blind if strategy == "train on blind 10%" else np.ones(len(week), bool)
        model = LinearRegression().fit(design(week)[train], actual[train])
    return pd.DataFrame(out).set_index("round").round(1)

for s in ["no holdout", "train on blind 10%"]:
    print(s); print(run(s))

আসল আউটপুট (ব্রাউজারের Python):

no holdout
       promise_h  actual_h  on_time_%
round
0           27.8      27.5       67.9
1           33.0      29.9       79.1
2           35.5      31.2       82.2
3           37.0      31.7       85.3
4           37.8      32.2       87.3
5           39.7      33.5       87.2
train on blind 10%
       promise_h  actual_h  on_time_%
round
0           27.8      27.0       67.9
1           28.7      27.2       71.1
2           26.8      26.6       66.1
3           25.7      25.7       66.6
4           27.1      26.2       69.4
5           27.8      27.0       66.6

Holdout ছাড়া ছয় দফায় গড় প্রতিশ্রুতি ২৭.৮ থেকে ৩৯.৭ ঘণ্টা, আর আসল গড় ডেলিভারি ২৭.৫ থেকে ৩৩.৫: ক্রেতারা প্রায় ছয় ঘণ্টা বেশি অপেক্ষা করছেন। অথচ dashboard-এ সবচেয়ে চোখে পড়া সংখ্যা “সময়মতো”-র হার ৬৭.৯% থেকে ৮৭%-এ উঠেছে, যেন model আরও ভালো হচ্ছে! প্রতিটি সপ্তাহে model নিজের লগ করা ডেটায় ভালোই fit করে; সমস্যা হলো ডেটাটি নিজেই model-এর তৈরি। অন্ধ ১০%-এ শেখালে প্রতিশ্রুতি ২৬–২৯ ঘণ্টায় স্থির থাকে। দাম দুটি: মাত্র ৪০০ সারিতে শেখা, তাই দফা থেকে দফায় ওঠানামা; আর ১০% অর্ডারে hub-এর কাছে প্রতিশ্রুতির তথ্য থাকে না। (প্রতিশ্রুতি না থাকলে এই ডেটায় গড় ডেলিভারি প্রায় ২৩ ঘণ্টা; দুই কৌশলেই ৯০% অর্ডারে ১.২ গুণ buffer-এর কারণে কিছু ঢিলেমি থেকে যায়।)

এই simulation-এর বানানো নিয়ম (৬০% ঢিলেমি) বাস্তবে কতটা সত্য, তা জানা নেই; প্রশ্নটি হলো আপনার system-এ এমন একটি পথ আছে কি না। একই নকশা বহু জায়গায় খাটে: প্রতারণার model যে অর্ডার আটকায়, তার label আসে না, তাই একটি ছোট এলোমেলো অংশ নিয়ম ছাড়াই যাচাই হয়; সুপারিশে কিছু অংশে নতুন পণ্য দেখানো হয় (exploration). প্রতিটি সিদ্ধান্তের সম্ভাবনা লগ করলে পরে inverse probability weighting দিয়ে সংশোধনও সম্ভব (পর্ব ৬৪)।

নজরদারি চার স্তরে: (১) service: অনুরোধের হার, p99, ত্রুটি, fallback-এর হার; (২) ডেটা: feature-এর missing আর বণ্টন (PSI-এর হিসাব পর্ব ৫৯-এ, আবার শেখানোর দরকার নেই); (৩) অনুমান: গড় প্রতিশ্রুতি zone-ভেদে, যা label আসার আগেই পাওয়া যায় (prediction drift); (৪) মান: label আসার পর zone-ভিত্তিক coverage আর pinball, holdout অংশে আলাদা করে। ঋতুর জন্য আলাদা reference: ঈদের সপ্তাহকে সাধারণ সপ্তাহের সঙ্গে তুলনা করলে প্রতিবছর ভুয়া সতর্কতা। Alert, dashboard আর rollback-এর বিস্তার পর্ব ৬৯-এ; incident-এর সময় কাজের ধারা Cloud & DevOps কোর্সের পর্ব ৬৭-এ, আর dashboard বানানো পর্ব ৬৬-এ।

পুনরাবৃত্তি আর খরচ. প্রথম সংস্করণ চালুর পর পরের ধাপ বাছতে হয় দাম দেখে: নতুন feature (courier-এর অবস্থান) কি latency আর রক্ষণাবেক্ষণের দাম মেটাবে? প্রতি সপ্তাহের retrain-এর বদলে মাসে একবার যথেষ্ট কি না, তা অতীতের ডেটায় backtest করে দেখা যায়। প্রতিটি নতুন অংশ (feature store, স্বয়ংক্রিয় retrain, আলাদা model প্রতি zone) একটি স্থায়ী দায়িত্ব যোগ করে। D. Sculley ও সহকর্মীরা ২০১৫ সালে NeurIPS-এ “Hidden Technical Debt in Machine Learning Systems” প্রবন্ধে যুক্তি দেন, বাস্তব ML system-এ model-এর কোড একটি ছোট অংশ, আর আশপাশের ডেটা, configuration আর নজরদারির কোডেই বেশিরভাগ ঋণ জমে।

৯ · দ্বিতীয় নকশা: পণ্যের সুপারিশ, আর ইন্টারভিউর চেকলিস্ট

একই দশ ধাপ একটি ভিন্ন সমস্যায়: বাজারঘরের home পাতায় “আপনার জন্য” ২০টি পণ্য। তুলনা করলে বোঝা যায়, কোন সিদ্ধান্ত সমস্যা থেকে আসে আর কোনটি পদ্ধতি থেকে।

ধাপডেলিভারির সময়পণ্যের সুপারিশ
সিদ্ধান্তএকটি প্রতিশ্রুতি দেখানোলাখো পণ্য থেকে ২০টি বাছা আর সাজানো
Framingquantile regressionদুই ধাপ: candidate generation (কয়েকশো প্রার্থী), তারপর ranking (কেনার সম্ভাবনা)
Labelআসল ঘণ্টা, ১–৫ দিন পরেclick আর কেনা (implicit feedback); না-দেখানো পণ্যের label নেই, ওপরের ঘরে click বেশি
Offline metricpinball, coverageসময় মেনে recall@k, NDCG (পর্ব ৫৩)
Online metricসম্পন্ন অর্ডার / checkoutsession-প্রতি কেনা বা আয়; guardrail: বৈচিত্র্য, নতুন বিক্রেতার দেখা পাওয়া, latency
Servingপ্রতিটি অনুরোধে onlineপ্রার্থী রাতে batch-এ বা embedding দিয়ে, ranking online; জনপ্রিয় তালিকা cache-এ
Cold startনতুন zone: কাছের ruleনতুন ক্রেতা: জনপ্রিয় আর জেলাভিত্তিক; নতুন পণ্য: বিবরণ আর বিভাগের feature
Feedback loopপ্রতিশ্রুতি hub-এর গতি বদলায়যা দেখানো হয় তা-ই বিক্রি হয়; জনপ্রিয় আরও জনপ্রিয়
Fallbackzone-এর quantile টেবিলজেলার জনপ্রিয় তালিকা

সবচেয়ে বড় পার্থক্য label-এ। ETA-র label প্রায় নিরপেক্ষ (যদি feedback loop সামলানো হয়); সুপারিশের label পুরোপুরি model-এর আগের সিদ্ধান্তে বাঁধা, কারণ ক্রেতা শুধু দেখানো পণ্যেই click করতে পারেন। তাই সুপারিশে offline মূল্যায়ন আরও দুর্বল, আর online test বেশি জরুরি। পর্ব ৫৩-এর matrix factorization আর two-tower ধারণা candidate generation-এ, আর পর্ব ৩৬-এর boosting ranking-এ বসে।

ইন্টারভিউর ধরন

ML system design ইন্টারভিউ সাধারণত ৪৫ থেকে ৬০ মিনিটের একটি খোলা আলোচনা: “একটি ডেলিভারির সময়ের অনুমান নকশা করুন”। একটি কাজের সময়-ভাগ: প্রশ্ন আর পরিধি ৫–৮ মিনিট; framing আর metric ৮–১০; ডেটা, label আর feature ১০; model আর training ৮; serving, fallback আর হিসাব ৮; মূল্যায়ন, নজরদারি আর feedback loop ৮; শেষে ঝুঁকি আর পরের ধাপ। পরীক্ষক সাধারণত দেখেন আপনি প্রশ্ন জিজ্ঞাসা করেন কি না, সংখ্যা দিয়ে যুক্তি দেন কি না, আর trade-off নিজে থেকে বলেন কি না। পূর্ণ walkthrough-সহ অনুশীলন পর্ব ৭৭ (ML ধারণা আর system design ইন্টারভিউ — গভীর প্রশ্ন আর আলোচনা)-এ।

পুনরায় ব্যবহারযোগ্য চেকলিস্ট

আরও গভীরে: Martin Zinkevich-এর “Rules of Machine Learning” (Google-এর প্রকাশিত নির্দেশিকা) প্রথম নিয়মেই বলে, ML ছাড়া পণ্য চালু করতে ভয় পাবেন না; প্রথম model সরল রাখুন আর pipeline ঠিক করুন। Juan Perdomo ও সহকর্মীরা ২০২০ সালে ICML-এ “performative prediction” নামে সেই অবস্থা বিশ্লেষণ করেন, যেখানে অনুমান নিজের লক্ষ্য-বণ্টন বদলায়, অংশ ৮-এর চক্রের মতো। Chip Huyen-এর বই Designing Machine Learning Systems (O'Reilly, ২০২২) এই পর্বের ধাপগুলোর একটি বিস্তারিত ব্যবহারিক রূপ দেয়।

পরীক্ষা ও ইন্টারভিউতে: (১) দিনে ১,২০,০০০ অর্ডার, অর্ডারপ্রতি ৩টি view, peak ×৪ হলে peak req/s? ৩,৬০,০০০ ÷ ৮৬,৪০০ = ৪.১৭; × ৪ = প্রায় ১৬.৭. (২) প্রতিশ্রুতির জন্য কোন loss? উঁচু quantile-এর pinball loss, কারণ গড় বা median প্রায় অর্ধেক প্রতিশ্রুতি ভাঙে। (৩) Training-serving skew কী, প্রতিকার? training আর online-এ feature-এর হিসাব আলাদা; এক সংজ্ঞা, একই কোড, লগ করা feature-এর সঙ্গে তুলনা। (৪) Offline MAE কমেছে, online বিক্রি কমেছে: কারণ? metric ভুল পরিসংখ্যান মাপছে (median বনাম quantile), বা feedback loop, বা offline ডেটা আর চালু অবস্থার পার্থক্য। (৫) Model আটকে গেলে? timeout, তারপর একই প্রশ্নের সরল rule, আর fallback-এর হার নজরে।

১০ · AI-এর যুগে — AI-এর বানানো ML নকশা যাচাই

“একটি ETA prediction system নকশা করো” বললে AI assistant প্রায়ই সুন্দর দেখতে একটি তালিকা দেয়: Kafka, feature store, deep learning model, Kubernetes, real-time retraining. তাতে প্রায়ই অনুপস্থিত থাকে প্রশ্ন, সংখ্যা, fallback আর feedback loop; আর অনেক সময় চোখে পড়ে এমন বড় সরঞ্জাম, যা দিনে ৫০,০০০ অর্ডারের দোকানের দরকার নেই। নিচের ভুলগুলো প্রায়ই দেখা যায়।

AI প্রায়ই যা করেকেন সমস্যাকীভাবে ধরবেন
প্রশ্ন ছাড়াই সরঞ্জামের তালিকাসিদ্ধান্ত আর সীমা না জেনে নকশাপ্রথমে সিদ্ধান্ত, metric আর সংখ্যা চান
RMSE বা MAE-কে একমাত্র metricপ্রতিশ্রুতির জন্য ভুল পরিসংখ্যানব্যবসার ক্ষতির আকার থেকে loss বাছুন; offline-online মিল যাচাই
“দিনের মোট অর্ডার” বা পরের তথ্য feature-এleakage; offline ফল মিথ্যা ভালোপ্রতিটি feature-এর “কখন জানা যায়” কলাম
Fallback আর timeout-এর কথা নেইmodel আটকালে checkout আটকায়p99 আর ব্যর্থতার পথ লিখতে বলুন
“প্রতিদিন স্বয়ংক্রিয় retrain” যাচাই ছাড়াঅসম্পূর্ণ label আর feedback loop-এ ভুল শেখাlabel delay, holdout, retrain-এর পরে যাচাই আর rollback
পুরোনো বা বানানো library APIচলে না বা ভুল চলেনিজের version-এর docs; ছোট ডেটায় চালিয়ে দেখা
বড় সংখ্যা বা “৯৯.৯% নির্ভুল” দাবিউৎসহীন সংখ্যাপ্রতিটি সংখ্যার উৎস বা হিসাব চান

AI-কে নকশার সঙ্গে সংখ্যা, অনুমান আর ঝুঁকিও চাইতে বলুন:

একটি কাল্পনিক অনলাইন দোকানের checkout পাতায় “এত ঘণ্টার মধ্যে পৌঁছাবে” দেখানোর ML system নকশা করো। দিনে ৫০,০০০ অর্ডার, অর্ডারপ্রতি ৪বার checkout পাতা খোলা হয়, checkout API-র p99 লক্ষ্য ৩০০ ms, label ১–৫ দিন পরে আসে। ১. প্রথমে ৬টি প্রশ্ন লেখো, যা নকশার আগে জিজ্ঞাসা করা উচিত, আর প্রতিটির উত্তর নকশায় কী বদলায়। ২. Target, loss আর কেন সেই loss, লেখো; গড় না quantile, তা যুক্তি দিয়ে বলো। ৩. গড় আর peak req/s, latency budget-এর ভাগ আর বছরে লগের storage হিসাব করো, প্রতিটি ধাপ দেখিয়ে। ৪. প্রতিটি feature-এর জন্য “checkout-এর মুহূর্তে জানা যায় কি না” লেখো। ৫. Offline metric, online metric, guardrail আর লঞ্চের নিয়ম দাও। ৬. Timeout, fallback, cold start আর feedback loop-এর ঝুঁকি আর প্রতিকার লেখো। কোনো সংখ্যা বানিয়ে আসল পরিসংখ্যান বলে দেখাবে না; যা ধরে নিয়েছ, তা “ধরে নেওয়া” লিখবে। যে tool বা library-র নাম দেবে, তার কোন version ধরে লিখছ, তা বলো।

AI-এর দেওয়া ML নকশা হাতে পেলে — যাচাইয়ের চেকলিস্ট

ভাবনার প্রশ্ন

প্রতিটি প্রশ্ন নিয়ে নিজে কিছুক্ষণ ভাবুন — তারপর “→ উত্তর” চাপুন।

প্র ০১“Model হলো system-এর ছোট একটি অংশ”: Hidden Technical Debt প্রবন্ধ আর Rules of ML কী বলেছিল, আর কেন তা আজও প্রাসঙ্গিক?

২০১৫ সালে NeurIPS-এ D. Sculley, Gary Holt, Daniel Golovin ও সহকর্মীরা “Hidden Technical Debt in Machine Learning Systems” প্রবন্ধে একটি ছবি দেখান, যা পরে বহুবার উদ্ধৃত হয়েছে: মাঝখানে ছোট একটি বাক্স “ML code”, আর চারপাশে অনেক বড় বাক্স: ডেটা সংগ্রহ, যাচাই, feature বের করা, configuration, serving-এর অবকাঠামো, নজরদারি। তাঁদের যুক্তি, ML দ্রুত কিছু বানাতে দেয়, কিন্তু সেই দ্রুততার দাম পরে দিতে হয়। তাঁরা কয়েকটি ঋণের নাম দেন: entanglement (একটি feature বদলালে সবকিছু বদলায়, তাঁদের ভাষায় “changing anything changes everything”), undeclared consumers (কোনো model-এর অনুমান কে কে ব্যবহার করছে জানা নেই, তাই বদলালে অজানা ক্ষতি), glue code আর pipeline jungle, আর hidden feedback loop.

প্রায় একই সময়ে Martin Zinkevich Google-এর অভিজ্ঞতা থেকে “Rules of Machine Learning” নামে একটি নির্দেশিকা প্রকাশ করেন। এর শুরুর নিয়মগুলো এই পর্বের সঙ্গে মেলে: ML ছাড়া চালু করতে ভয় পাবেন না; আগে metric নকশা আর বাস্তবায়ন করুন; প্রথম model সরল রাখুন আর অবকাঠামো ঠিক করুন; চালু model-এর feature লগ করুন যাতে training-এ একই মান ব্যবহার হয়। শেষেরটি আসলে training-serving skew-এর প্রতিকার।

আজ সরঞ্জাম অনেক বদলেছে: feature store, model registry, pipeline-এর কাঠামো এখন খোলা উৎসের আর বাণিজ্যিক দুই রূপেই পাওয়া যায়। কিন্তু ঋণের মূল কারণ সরঞ্জাম নয়, সিদ্ধান্ত: কোন feature-এর মালিক কে, কোন metric দিয়ে বিচার হবে, model ব্যর্থ হলে কী হবে। এগুলো নকশার প্রশ্ন, আর এই পর্বের দশ ধাপ মূলত সেই প্রশ্নগুলো আগে জিজ্ঞাসা করার একটি অভ্যাস। তবে মনে রাখবেন, প্রবন্ধটি একটি অবস্থানপত্র, পরিমাপের গবেষণা নয়; “৯০% কোড ML নয়” ধরনের সংখ্যা ছবি থেকে পড়া অনুমান মাত্র।

মূল উপলব্ধি: ML system-এর ঋণ জমে model-এর চারপাশে, ডেটা, configuration, নজরদারি আর অদৃশ্য নির্ভরতায়; সরল model আর পরিষ্কার pipeline দিয়ে শুরু করা সেই ঋণ কমানোর সবচেয়ে সস্তা উপায়।

প্র ০২Offline-এ ভালো model online-এ কেন হতাশ করে? বাস্তবের প্রকাশিত অভিজ্ঞতা কী বলে?

Lucas Bernardi, Themistoklis Mavridis আর Pablo Estevez ২০১৯ সালে KDD-তে একটি বড় ভ্রমণ-বুকিং প্ল্যাটফর্মে প্রায় ১৫০টি সফল ML প্রয়োগের অভিজ্ঞতা লেখেন। তাঁদের একটি পর্যবেক্ষণ বহু আলোচিত: offline metric-এ model-এর উন্নতি প্রায়ই ব্যবসার metric-এর উন্নতিতে রূপ নেয়নি, আর দুইয়ের মধ্যে তাঁরা স্পষ্ট সম্পর্ক পাননি। তাঁরা কয়েকটি সম্ভাব্য কারণ বলেন: মূল্য একসময় পরিপূর্ণ হয়ে যায় (আরও নির্ভুলতায় ক্রেতার আর কিছু আসে-যায় না), offline metric একটি প্রতিনিধি মাপ যা আসল লক্ষ্য থেকে সরে যায়, আর কখনো অনুমান “খুব ভালো” হলে ক্রেতার কাছে অস্বস্তিকর লাগে। এটি একটি প্রতিষ্ঠানের অভিজ্ঞতা, সাধারণ সূত্র নয়, কিন্তু অনেক দল একই কথা বলে।

আরেকটি বহু উদ্ধৃত উদাহরণ Netflix Prize (২০০৬–২০০৯)। RMSE-তে ১০% উন্নতির জন্য পুরস্কার জেতা দলের বিশাল ensemble পুরোপুরি চালু করা হয়নি; Netflix-এর প্রকৌশল ব্লগ ২০১২ সালে জানায়, অতিরিক্ত নির্ভুলতা সেই প্রকৌশল খরচের যোগ্য মনে হয়নি, আর ততদিনে ব্যবসাও DVD থেকে streaming-এ সরেছিল, যেখানে কী মাপতে হবে সেটিই বদলে গিয়েছিল। অর্থাৎ offline metric একটি সময়ের প্রশ্নের উত্তর দিয়েছিল, যা পরে আর মূল প্রশ্ন ছিল না।

এই পর্বের simulation তৃতীয় একটি কারণ দেখায়: metric ভুল পরিসংখ্যান মাপছে। MAE median চায়, ব্যবসা চায় একটি উঁচু quantile. আরও কারণ: offline ডেটা পুরোনো নীতির ফল (feedback loop), offline-এ ব্যবহার করা feature online-এ দেরিতে বা ভিন্নভাবে আসে (skew), আর offline মূল্যায়ন সব ক্রেতাকে সমান ধরে, অথচ ব্যবসার মূল্য কিছু দলে কেন্দ্রীভূত। প্রতিকার: offline metric-কে ব্যবসার ক্ষতির আকার থেকে বাছা, অতীতের A/B test-এর ফলের সঙ্গে offline metric-এর মিল নিয়মিত যাচাই করা, আর লঞ্চের সিদ্ধান্ত online test-এ রাখা।

মূল উপলব্ধি: Offline metric একটি প্রতিনিধি মাপ; তার সঙ্গে ব্যবসার ফলের সম্পর্ক ধরে নেওয়া যায় না, মাপতে হয়, আর শেষ সিদ্ধান্ত online পরীক্ষায়।

প্র ০৩অনুমান যখন ভবিষ্যৎ ডেটা বদলায়: predictive policing থেকে performative prediction পর্যন্ত feedback loop-এর গবেষণা কী শিখিয়েছে?

Feedback loop-এর সবচেয়ে আলোচিত উদাহরণগুলোর একটি predictive policing. Danielle Ensign, Sorelle Friedler, Scott Neville, Carlos Scheidegger আর Suresh Venkatasubramanian ২০১৮ সালে FAT* সম্মেলনে (“Runaway Feedback Loops in Predictive Policing”) একটি সরল গাণিতিক model দিয়ে দেখান: যেখানে পুলিশ বেশি পাঠানো হয়, সেখানে বেশি অপরাধ নথিভুক্ত হয়, আর সেই নথি পরের দিন আবার সেখানেই পুলিশ পাঠায়। দুটি এলাকার আসল অপরাধের হার কাছাকাছি হলেও ব্যবস্থাটি একটি এলাকায় আটকে যেতে পারে। তাঁরা দেখান, নথির ওজন সংশোধন করলে, অর্থাৎ কোথায় কতটা দেখা হয়েছিল তা হিসাবে আনলে, এই পলায়ন কমে। এটি একটি model-ভিত্তিক বিশ্লেষণ, নির্দিষ্ট কোনো শহরের মাপ নয়।

Juan Perdomo, Tijana Zrnic, Celestine Mendler-Dünner আর Moritz Hardt ২০২০ সালে ICML-এ বিষয়টি সাধারণ কাঠামোয় আনেন: “performative prediction”, যেখানে model-এর বণ্টন-বদল নিজেই শেখার অংশ। তাঁরা দেখান, বারবার নতুন ডেটায় retrain করলে কিছু শর্তে system একটি স্থির অবস্থায় পৌঁছায় (performatively stable), কিন্তু সেই অবস্থা সবচেয়ে ভালো অবস্থা নাও হতে পারে। এই পর্বের ETA simulation ঠিক এর একটি ছোট রূপ: retrain-এর পর প্রতিশ্রুতি বাড়ছিল আর ধীরে থামার দিকে যাচ্ছিল, কিন্তু ক্রেতার জন্য খারাপ জায়গায়।

ব্যবহারিক প্রতিকার তিনটি। প্রথম, একটি ছোট এলোমেলো অংশ যেখানে model-এর সিদ্ধান্ত প্রয়োগ হয় না বা প্রভাব ফেলে না; এর খরচ আছে (কিছু ক্রেতা কম ভালো সেবা পান), তাই অংশটি ছোট আর সময়ে সীমিত রাখা হয়। দ্বিতীয়, প্রতিটি সিদ্ধান্তের সম্ভাবনা লগ করা, যাতে পরে ওজন দিয়ে সংশোধন করা যায়। তৃতীয়, শুধু model-এর নিজের মাপ (on-time%) নয়, বাইরের একটি মাপও (আসল গড় ডেলিভারির সময়) নজরে রাখা, যা চক্রের ফলে খারাপ হলে ধরা পড়ে।

মূল উপলব্ধি: যে system নিজের label তৈরিতে ভূমিকা রাখে, তার ডেটা আর নিরপেক্ষ সাক্ষী নয়; এলোমেলো holdout, সম্ভাবনার লগ আর বাইরের মাপ ছাড়া চক্রটি দেখাই যায় না।

প্র ০৪Feature store কেন জন্মাল, আর কোন দলের তা দরকার নেই?

২০১৭ সালে Uber-এর প্রকৌশল ব্লগে Michelangelo নামের অভ্যন্তরীণ ML প্ল্যাটফর্মের বর্ণনা বেরোয়। সেখানে একটি অংশ ছিল ভাগ করা feature-এর ভান্ডার, যাতে এক দলের বানানো feature অন্য দল ব্যবহার করতে পারে, আর training আর serving-এ একই মান পায়। এরপর ধারণাটি ছড়ায়: ২০১৯ সালের দিকে Gojek আর Google Cloud মিলে Feast নামে একটি খোলা উৎসের feature store শুরু করে, আর পরে বেশ কয়েকটি বাণিজ্যিক পণ্য আসে। বিস্তারিত সংস্করণভেদে বদলেছে, তাই নির্দিষ্ট সরঞ্জামের কথা নিজের version-এর docs দেখে যাচাই করবেন।

সমস্যাটি তিনটি। প্রথম, training-serving skew: একই feature দুটি দল দুই ভাষায় লেখে, আর ছোট পার্থক্য নীরবে model-এর মান কমায়। দ্বিতীয়, point-in-time correctness: training-এর প্রতিটি সারিতে “তখন যা জানা ছিল” জোড়া কঠিন, বিশেষত যখন feature-এর মান বারবার বদলায়; ভুল join-এ ভবিষ্যৎ ঢুকে পড়ে। তৃতীয়, পুনর্ব্যবহার আর মালিকানা: একশোটি model-এ “গত ৩০ দিনের কেনা” একশোভাবে হিসাব হলে কোনটি ঠিক, কেউ জানে না।

কিন্তু প্রতিটি দলের এই সমস্যা সমান বড় নয়। বাজারঘরের প্রথম ETA model-এ চারটি feature: zone আর দূরত্ব অর্ডার থেকে আসে, বৃষ্টি একটি ছোট টেবিল থেকে, hub-এর চাপ একটি cache থেকে। একটি পুরো feature store চালানো এখানে বাড়তি অবকাঠামো, বাড়তি শেখা আর বাড়তি ব্যর্থতার জায়গা। ধারণাগুলো, অর্থাৎ এক সংজ্ঞা, সময়সহ ইতিহাস, আর online-এ লগ করা feature, একটি সাধারণ database আর ভালো কোড-শৃঙ্খলা দিয়েই মানা যায়। যখন model আর দলের সংখ্যা বাড়ে, আর একই feature বহু জায়গায় লাগে, তখন সরঞ্জামের দাম মেটে।

মূল উপলব্ধি: Feature store একটি সরঞ্জাম, মূল কথা তিনটি নিয়ম: এক সংজ্ঞা, point-in-time ইতিহাস আর online মানের লগ; ছোট দল নিয়মগুলো মেনে সরঞ্জাম পরে আনতে পারে।

প্র ০৫ক্রেতাকে কোন সংখ্যা দেখাবেন: গড়, একটি quantile, না একটি পরিসর? প্রতিশ্রুতির সততা আর ব্যবসার লাভ কি একই দিকে চলে?

অংশ ৬-এর simulation-এ ০.৮-quantile সবচেয়ে বেশি সম্পন্ন অর্ডার দিয়েছে, কিন্তু সেটি একটি বানানো নিয়মের ফল। আসল প্রশ্নটি নৈতিক আর ব্যবসায়িক দুটিই: ক্রেতাকে যে সংখ্যা দেখানো হচ্ছে, তা কী অর্থ বহন করে, আর ক্রেতা তা কীভাবে বোঝেন? “৩০ ঘণ্টার মধ্যে” বললে বেশিরভাগ ক্রেতা ধরে নেন প্রায় নিশ্চিত; অথচ ০.৮-quantile মানে প্রতি পাঁচটির একটিতে দেরি। প্রতিশ্রুতি খুব কম বলে বিক্রি বাড়ানো একটি প্রলোভন, যা স্বল্পমেয়াদে metric বাড়ায় আর দীর্ঘমেয়াদে আস্থা কমায়; ছোট A/B test সাধারণত সেই দীর্ঘ প্রভাব ধরতে পারে না (পর্ব ৬২-এর novelty আর সময়ের আলোচনা)।

বিকল্পগুলো তুলনা করা যায়। পরিসর (“২০–৩২ ঘণ্টা”) অনিশ্চয়তা সৎভাবে দেখায়; পর্ব ৫৮-এর conformalized quantile regression একটি coverage-এর নিশ্চয়তাসহ পরিসর দেয়, তবে সেই নিশ্চয়তা গড় অর্থে, প্রতিটি zone-এ আলাদাভাবে নয়, যদি না দলভিত্তিক পদ্ধতি ব্যবহার করেন। একটি দিন (“বৃহস্পতিবারের মধ্যে”) ক্রেতার কাছে সবচেয়ে বোধগম্য, কিন্তু রাত ১১টায় অর্ডার করলে দিনের সীমা অন্যরকম আচরণ করে। আর কিছু দোকান প্রতিশ্রুতি ভাঙলে ক্ষতিপূরণ দেয়; তখন quantile বাছা আসলে একটি খরচের হিসাব হয়ে যায়।

এখানে ন্যায্যতার প্রশ্নও আছে। গড়ে ৮০% coverage মানে হতে পারে ঢাকায় ৯০% আর দূরের জেলায় ৬০%. দূরের ক্রেতারা তখন বারবার ভাঙা প্রতিশ্রুতি পান, অথচ গড় সংখ্যা সুন্দর দেখায়। তাই zone-ভিত্তিক coverage-কে guardrail রাখা দরকার, যা পর্ব ৬০-এর quality-of-service ক্ষতির ভাবনার সঙ্গে মেলে।

মূল উপলব্ধি: দেখানো সংখ্যাটি একটি প্রতিশ্রুতি; তার পরিসংখ্যানগত অর্থ, প্রতিটি দলে coverage আর দীর্ঘমেয়াদি আস্থা নকশার অংশ, শুধু একটি স্বল্পমেয়াদি metric বাড়ানোর প্রশ্ন নয়।

অনুশীলন

হিসাবগুলো খাতায় করুন, তারপর উত্তর মেলান। চাইলে পাতার ব্লকগুলোতে সংখ্যা বদলে যাচাই করুন।

  1. পূর্ণ numerical: একটি দোকানে দিনে ১,২০,০০০ অর্ডার, অর্ডারপ্রতি ৩বার checkout পাতা খোলা, প্রতিবার ২টি অনুমান। সন্ধ্যার ভিড় গড়ের ৪ গুণ, sale-এর দিন তার আরও ৩ গুণ। প্রতিটি অনুমানের লগ ১.৫ KB. Checkout API-র p99 লক্ষ্য ২৫০ ms, তার ২৪% ETA-র। একটি অনুমানে model ২০ ms নেয়। (ক) গড়, peak আর sale-এর req/s আর sale-এর অনুমান/s; (খ) ETA-র budget; (গ) বছরে লগের GB; (ঘ) দ্বিগুণ জায়গা রেখে কয়টি core?

    (ক) view: ১,২০,০০০ × ৩ = ৩,৬০,০০০/দিন; গড় ৩,৬০,০০০ ÷ ৮৬,৪০০ = ৪.১৭ req/s; peak × ৪ = ১৬.৬৭; sale × ৩ = ৫০ req/s; অনুমান × ২ = ১০০/s. (খ) ২৫০ × ০.২৪ = ৬০ ms. (গ) ৩,৬০,০০০ × ১.৫ KB × ৩৬৫ = ১৯,৭১,০০,০০০ KB ≈ ১৯৭.১ GB. (ঘ) একটি core: ১,০০০ ÷ ২০ = ৫০ অনুমান/s; ১০০-র জন্য ২টি core, দ্বিগুণ জায়গা রেখে ৪টি core, অন্তত দুটি আলাদা copy-তে ভাগ করে, যাতে একটি বিকল হলেও চলে। সংখ্যাগুলো ছোট, তাই নকশার মনোযোগ latency-র লেজ আর fallback-এ।

  2. সমালোচনা ও নকশা: একটি দল বাজারঘরের জন্য প্রতারণা-ধরার নকশা লিখেছে: “প্রতিটি অর্ডারে একটি deep learning model, offline AUC ০.৯৭. স্কোর ০.৫-এর বেশি হলে অর্ডার বাতিল। প্রতি রাতে আগের দিনের সব অর্ডারে retrain, label হলো ‘ফেরত বা টাকা না দেওয়া’। Feature-এ আছে ক্রেতার ‘মোট ফেরত, আজ পর্যন্ত’। Model ব্যর্থ হলে অর্ডার আটকে থাকবে, যতক্ষণ না model ফেরে। সফলতার মাপ AUC.” কী কী সমস্যা, আর আপনার নকশা কী?

    সমস্যা: (১) Selective labels আর feedback loop: বাতিল অর্ডারের ফল কখনো জানা যায় না, তাই প্রতি রাতের retrain শুধু অনুমোদিত অর্ডারে শেখে; ধীরে ধীরে model এমন জগৎ শেখে যেখানে ঝুঁকিপূর্ণ অর্ডার প্রায় নেই। (২) Label delay: ফেরত বা টাকা না দেওয়া জানতে দিন-সপ্তাহ লাগে; আগের দিনের অর্ডারের label অসম্পূর্ণ। (৩) Leakage আর skew: “মোট ফেরত, আজ পর্যন্ত” training-এ সম্ভবত পরের ফেরতও গোনে; point-in-time হিসাব দরকার। (৪) Threshold ০.৫: ভুল বাতিল (ভালো ক্রেতা হারানো) আর ভুল অনুমোদনের দাম আলাদা; খরচ থেকে সীমা (পর্ব ৫০, পর্ব ২৬)। (৫) Fallback নেই: model বন্ধ হলে পুরো বিক্রি বন্ধ; একটি সরল নিয়ম লাগে। (৬) Metric: AUC ব্যবসার ক্ষতি মাপে না; টাকায় ক্ষতি, ভুল বাতিলের হার আর অভিযোগ guardrail. (৭) সরাসরি বাতিল কঠোর; মাঝের স্তরে মানুষের যাচাই বা অগ্রিম টাকা চাওয়া যায়। নকশা: point-in-time feature; খরচভিত্তিক তিন স্তরের সিদ্ধান্ত (অনুমোদন, অগ্রিম টাকা চাওয়া বা মানুষের যাচাই, বাতিল); ১–২% এলোমেলো অংশে নিয়ম ছাড়া অনুমোদন আর সম্ভাবনার লগ; label চূড়ান্ত হওয়া অর্ডারে সাপ্তাহিক retrain, সময় ধরে মূল্যায়ন, shadow আর canary; timeout হলে সরল নিয়ম; দলভেদে ভুল বাতিলের হার নজরে।

  3. আউটপুট অনুমান করুন: চালানোর আগে দুটি লাইন লিখুন। কোন প্রতিশ্রুতি MAE-তে ভালো, আর কোনটি প্রতিশ্রুতি রক্ষায়?
    import numpy as np
    actual = np.array([5, 8, 30, 50])
    pred_a = np.array([6, 7, 26, 45])
    pred_b = np.array([7, 10, 34, 60])
    for p in (pred_a, pred_b):
        print(np.abs(p - actual).mean(), (actual > p).mean())

    ডেস্কটপে সত্যিকারের run (Python 3.14.4, NumPy 2.5.4):

    2.75 0.75
    4.5 0.0

    A-র ভুল ১, ১, ৪, ৫; গড় ১১/৪ = ২.৭৫. কিন্তু ৮ > ৭, ৩০ > ২৬, ৫০ > ৪৫: চারটির তিনটিতে প্রতিশ্রুতি ভাঙে, তাই ০.৭৫. B-র ভুল ২, ২, ৪, ১০; গড় ১৮/৪ = ৪.৫, কিন্তু একটিও দেরি নেই, তাই ০.০. MAE-তে A ভালো, প্রতিশ্রুতিতে B: অংশ ৬-এর শিক্ষার ছোট রূপ। (actual > p) একটি bool array, আর তার .mean() True-এর ভাগ দেয়।

  4. কোডিং: পাতার bazar_eta module ব্যবহার করে একটি function লিখুন rule_promise(train, new, tau), যা zone-এর τ-quantile পূর্ণ ঘণ্টায় ওপরে গোল করে প্রতিশ্রুতি দেয়। τ = ০.৫০, ০.৫৫, …, ০.৯৫-এর মধ্যে validation অর্ডারে (seed=72) online_value সবচেয়ে বেশি এমন τ বাছুন, তারপর আলাদা test অর্ডারে (seed=73) ফল ছাপান। Training অর্ডার orders(3000, seed=71).
    import numpy as np
    from bazar_eta import orders, online_value
    
    tr, va, te = orders(3000, seed=71), orders(3000, seed=72), orders(3000, seed=73)
    
    def rule_promise(train, new, tau):               # zone-এর tau-quantile, পূর্ণ ঘণ্টায়
        q = train.groupby("zone").hours.quantile(tau)
        return np.ceil(q[new.zone].to_numpy())
    
    taus = np.round(np.arange(0.5, 0.96, 0.05), 2)
    val = [online_value(rule_promise(tr, va, t), va.hours.to_numpy(), va.zone.to_numpy())[0]
           for t in taus]
    best = taus[int(np.argmax(val))]
    print("validation:", dict(zip(taus.tolist(), np.round(val, 1).tolist())))
    done, late = online_value(rule_promise(tr, te, best), te.hours.to_numpy(), te.zone.to_numpy())
    print(f"best tau {best}  test done/1000 {done:.1f}  late {late:.1f}%")

    ডেস্কটপে সত্যিকারের run (Python 3.14.4, NumPy 2.5.4, pandas 3.1.1) ছাপে:

    validation: {0.5: 781.5, 0.55: 777.5, 0.6: 776.0, 0.65: 772.6, 0.7: 790.6, 0.75: 783.2, 0.8: 777.0, 0.85: 772.0, 0.9: 752.1, 0.95: 720.2}
    best tau 0.7  test done/1000 791.2  late 24.0%

    পড়া: validation-এর বক্ররেখা মসৃণ নয়: ০.৫-এ ৭৮১.৫, ০.৬৫-এ ৭৭২.৬, আবার ০.৭-এ ৭৯০.৬. পূর্ণ ঘণ্টায় গোল করা আর ৩,০০০টি অর্ডারের এলোমেলোতা মিলে এই ওঠানামা। তাই একটি validation set-এ “সেরা” τ বাছা ঝুঁকিপূর্ণ; কয়েকটি seed বা সময়ের ভাগে গড় নিয়ে, আর ০.৯৫-এর মতো স্পষ্ট খারাপ অঞ্চল বাদ দিয়ে, একটি পরিসর (০.৭–০.৮) বাছাই বেশি নিরাপদ। মনে রাখুন, online_value নিজেই বানানো; আসল সিদ্ধান্ত A/B test-এ।

নিজেকে যাচাই করুন

ভুল হলে কারণসহ ব্যাখ্যা পাবেন, আবার চেষ্টাও করতে পারবেন।

ক্রমএকটি ML system নকশার ধাপগুলো সঠিক ক্রমে সাজান (▲▼ চেপে সরান)

  1. সিদ্ধান্ত, ব্যবহারকারী আর সীমা নিয়ে প্রশ্ন জিজ্ঞাসা করা
  2. Target, loss, offline ও online metric আর guardrail ঠিক করা
  3. Label কখন জানা যায় আর point-in-time feature ঠিক করা
  4. Baseline বানিয়ে তারপর model আর training pipeline
  5. Timeout আর fallback-সহ serving, তারপর shadow, canary আর A/B test
  6. নজরদারি, feedback loop-এর holdout আর পরের সংস্করণ

একটি দোকানে দিনে ৯০,০০০ অর্ডার, অর্ডারপ্রতি ২বার checkout পাতা খোলা হয়, আর ভিড়ের সময় চাপ গড়ের ৪ গুণ। ভিড়ের সময় সেকেন্ডে প্রায় কতটি অনুরোধ?

  • প্রায় ২.১
  • প্রায় ৮.৩
  • প্রায় ৪.২
  • প্রায় ৫০০

ক্রেতাকে “এত ঘণ্টার মধ্যে পৌঁছাবে” দেখানো হবে, আর লক্ষ্য প্রায় ৮০% অর্ডারে কথা রাখা। Model কোন loss দিয়ে শেখানো সবচেয়ে মানানসই?

  • Squared loss
  • Absolute loss
  • τ = ০.৮-এর pinball (quantile) loss
  • Log loss

Training-এ “hub-এর চাপ” feature হিসাব হয়েছে দিনের শেষে মোট অর্ডার দিয়ে, কিন্তু চালু system-এ হিসাব হয় গত এক ঘণ্টার অর্ডার দিয়ে। এই সমস্যার নাম কী?

  • Training-serving skew (আর সঙ্গে leakage)
  • Label shift
  • Cold start
  • Overfitting

ডেলিভারির প্রতিশ্রুতি দেখে hub-এর কর্মীরা হাতে সময় থাকা অর্ডার পিছিয়ে দেন, আর প্রতি সপ্তাহে সেই ডেটায় model retrain হয়। প্রতিশ্রুতি ধীরে ধীরে বাড়ছে। কোন প্রতিকার মূল কারণে আঘাত করে?

  • আরও বেশি সপ্তাহের ডেটায় retrain
  • আরও জটিল model
  • Retrain চিরতরে বন্ধ
  • এলোমেলো একটি ছোট অংশে hub প্রতিশ্রুতি দেখবে না, আর model সেই অংশে শিখবে

একটি online ETA service-এর model কখনো কখনো দুই সেকেন্ড আটকে থাকে। Checkout পাতার জন্য সবচেয়ে ভালো নকশা কোনটি?

  • Model উত্তর না দেওয়া পর্যন্ত অপেক্ষা
  • একটি timeout, তারপর zone-এর quantile টেবিল থেকে উত্তর, আর fallback-এর হার লগ
  • উত্তর না পাওয়া পর্যন্ত বারবার retry
  • ত্রুটি দেখিয়ে checkout বন্ধ রাখা

ETA model-এর A/B test-এ primary metric “১,০০০ checkout-এ সম্পন্ন অর্ডার”। নিচের কোনটি guardrail হিসেবে সবচেয়ে মানানসই?

  • Offline MAE
  • Model training-এ কত মিনিট লাগে
  • দেরির হার আর ETA-র p99 latency
  • মোট অর্ডারের সংখ্যা

শব্দকোষ

লেখার মধ্যে ডটেড দাগ দেওয়া শব্দে মাউস রাখুন বা চাপুন — অর্থ দেখাবে। এই পর্বের সব নতুন শব্দ এখানে একসাথে:

মনে রাখুন

  1. দশ ধাপ: প্রশ্ন, framing, metric, ডেটা ও label, feature, baseline ও model, pipeline, serving, মূল্যায়ন, নজরদারি। প্রশ্ন আর সংখ্যা ছাড়া সরঞ্জামের তালিকা নকশা নয়।
  2. হিসাব: view/দিন ÷ ৮৬,৪০০ × peak; latency budget ভাগ করে প্রতিটি অংশের সীমা; লগ আর training-এর storage. অনেক ML system-এ অনুরোধ কম, কঠিন অংশ লেজ আর সঠিকতা।
  3. Feature: শুধু অনুমানের মুহূর্তে জানা তথ্য; training আর serving-এ এক সংজ্ঞা; feature store এই নিয়মের সরঞ্জাম।
  4. Metric: offline metric ব্যবসার সিদ্ধান্তের পরিসংখ্যান মাপুক (প্রতিশ্রুতির জন্য quantile); online primary, guardrail আর লঞ্চের নিয়ম আগে লেখা; শেষ বিচার A/B test.
  5. ঝুঁকি: timeout আর একই প্রশ্নের সরল fallback; feedback loop-এর জন্য এলোমেলো holdout; cold start-এ বাড়তি buffer; মানুষের সুইচ।

পরের পর্বে: পর্ব ৭২ (ক্যাপস্টোন — বাজারঘরের churn আর lifetime value প্রকল্প)। এই কোর্সের প্রায় সব হাতিয়ার একসঙ্গে: churn আর CLV অনুমান, কাকে retention offer দেবেন তার টাকায় হিসাব, আর চালু করার পরিকল্পনা।

আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ

এই পর্বটি শেয়ার করুন:
এই পর্বে ভুল পেয়েছেন? জানান