অধ্যায় 4 · পরিসংখ্যান: সৎভাবে ডেটা পড়া
ডেটা বর্ণনা: গড়, মধ্যমা, বিস্তার ও পার্সেন্টাইল
- পৃষ্ঠা 9 / 17
- 3 মিনিট পড়া
কিছু ট্রেন করার আগে ডেটাটা দেখতে হয়। বর্ণনামূলক পরিসংখ্যান হাজার হাজার সংখ্যাকে কয়েকটায় গুছিয়ে বলে: মাঝখানটা কোথায়, আর সেগুলো কতটা ছড়ানো। প্রোডাকশনে একটা AI সিস্টেম নজরে রাখার সময়ও এই সংখ্যাগুলোই রিপোর্ট করবেন।
মাঝখান: গড় নাকি মধ্যমা?
গড় হলো যোগফল ভাগ সংখ্যা। মধ্যমা হলো ডেটা সাজানোর পর মাঝের মান। ডেটায় আউটলায়ার থাকলে এরা আলাদা কথা বলে:
import numpy as np
# একটা API-র উত্তরের সময়, মিলিসেকেন্ডে — একটা কল খুব ধীর
latency = np.array([210, 190, 230, 205, 220, 198, 215, 2400, 207, 212])
print("mean: ", latency.mean())
print("median:", np.median(latency))
print("std: ", latency.std().round(1))
print("without the slow call: mean", np.delete(latency, 7).mean().round(1),
" std", np.delete(latency, 7).std().round(1))mean: 428.7
median: 211.0
std: 657.2
without the slow call: mean 209.7 std 11.1দশটার মধ্যে একটা ধীর কল গড়কে দ্বিগুণেরও বেশি করে দেয় (৪২৮.৭ ms), অথচ মধ্যমা (২১১ ms) তবু একটা সাধারণ কলের বর্ণনা দেয়। কয়েকটা চরম মান যখন বিভ্রান্ত করতে পারে — আয়, বাড়ির দাম, উত্তরের সময় — তখন মধ্যমা ব্যবহার করুন। মোড হলো সবচেয়ে বেশিবার আসা মান; এটা মূলত শ্রেণির জন্য ব্যবহৃত হয় ("ব্যবহারকারীরা কোন উত্তর সবচেয়ে বেশি বেছেছে?")।
বিস্তার: ভ্যারিয়েন্স আর স্ট্যান্ডার্ড ডেভিয়েশন
দুটো ক্লাসের গড় একই হয়েও তারা পুরো আলাদা হতে পারে:
import numpy as np
a = np.array([48, 50, 50, 52]) # একই গড় নম্বরের দুটো ক্লাস
b = np.array([20, 40, 60, 80])
for name, marks in [("class A", a), ("class B", b)]:
deviations = marks - marks.mean()
variance = np.mean(deviations ** 2)
print(f"{name}: mean {marks.mean():.0f}, variance {variance:.0f}, std {np.sqrt(variance):.1f}")class A: mean 50, variance 2, std 1.4
class B: mean 50, variance 500, std 22.4- প্রতিটা মান থেকে গড় বিয়োগ করুন (বিচ্যুতি)।
- সেগুলোর বর্গ করুন, যাতে ঋণাত্মক আর ধনাত্মক কাটাকাটি না হয়।
- বর্গগুলোর গড় নিন: এটাই ভ্যারিয়েন্স।
- মূল এককে ফিরতে বর্গমূল নিন: স্ট্যান্ডার্ড ডেভিয়েশন (std, σ)।
ক্লাস A-এর নম্বর সবই ৫০-এর দুয়েক নম্বরের মধ্যে; ক্লাস B-এর নম্বর ৬০ নম্বর জুড়ে ছড়ানো। গড় একই, গল্প সম্পূর্ণ আলাদা। গড়ের পাশে সবসময় বিস্তারও জানান।
NumPy-র
std()n দিয়ে ভাগ করে। pandas-এর.std()ভাগ করে n − 1 দিয়ে ("স্যাম্পল" স্ট্যান্ডার্ড ডেভিয়েশন), তাই ছোট ডেটায় দুটো একটু আলাদা উত্তর দেয়। দুটোই সঠিক; একটু আলাদা প্রশ্নের উত্তর দেয়।
পার্সেন্টাইল: p50, p95, p99
p95 (৯৫তম পার্সেন্টাইল) হলো সেই মান, যার নিচে ৯৫% ডেটা। একটা AI সার্ভিসের জন্য এর মানে "১০০ জনের মধ্যে ৯৫ জন এর চেয়ে কম অপেক্ষা করেছে"। টিমগুলো গড়ের বদলে p95 আর p99-এ লক্ষ্য ঠিক করে, কারণ সবচেয়ে ধীর অভিজ্ঞতার ব্যবহারকারীরাই অভিযোগ করেন:
import numpy as np
rng = np.random.default_rng(7)
latency = rng.lognormal(mean=5.3, sigma=0.4, size=10_000) # ১০,০০০টা সিমুলেট করা API কল
for p in [50, 95, 99]:
print(f"p{p}: {np.percentile(latency, p):6.0f} ms")
print(f"mean: {latency.mean():5.0f} ms")p50: 199 ms
p95: 384 ms
p99: 501 ms
mean: 216 msমধ্যমা (p50) ১৯৯ ms, কিন্তু ১০০ জনে ১ জন আধা সেকেন্ডের বেশি অপেক্ষা করেন। গড় (২১৬ ms) এটা পুরোপুরি লুকিয়ে রাখে।
নিজে চেষ্টা করুন
- ২,৪০০ ms-এর কলটা বদলে ২৪০ ms করুন। গড় আর মধ্যমা কতটা বদলায়?
[2, 4, 4, 4, 5, 5, 7, 9]-এর ভ্যারিয়েন্স হাতে হিসাব করুন, তারপর NumPy দিয়ে মিলিয়ে নিন (উত্তর ৪)।- pandas দিয়ে নিজের একটা CSV লোড করে
df.describe()চালান। এই পাতার কোন সংখ্যাগুলো এটা দেখায়?