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

ডেটার পরিসংখ্যান — mean, variance, correlation আর CLT

Statistics for Data — Centre, Spread, Correlation, the Central Limit Theorem, Confidence Intervals and p-values

Taught in Bangla, this lesson covers centre and spread, why sample variance divides by n − 1, outlier rules, Pearson versus Spearman correlation and why correlation is not causation. In-page runs show the Central Limit Theorem, interval coverage, a Welch t-test against a permutation test and effect size, with ASA guidance on reading p-values.

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

  • কেন্দ্রের মাপ (mean, median, mode, trimmed mean) আর কোনটি কোন প্রশ্নের উত্তর
  • ছড়ানোর মাপ: range, variance, SD, n − 1-এর কারণ, MAD, coefficient of variation, আর z-score দিয়ে outlier খোঁজার সীমা
  • Covariance আর Pearson correlation হাতে হিসাব, Spearman কখন ভালো, আর correlation থেকে কারণ কেন টানা যায় না
  • Sampling distribution, standard error আর Central Limit Theorem, simulation দিয়ে; কোথায় CLT খাটে না
  • t-interval, “৯৫%”-এর সঠিক অর্থ, p-value, Welch t-test, permutation test, effect size, multiple comparisons আর A/B test

বাজারঘরের বিশ্লেষককে প্রতিদিন কয়েকটি প্রশ্নের উত্তর দিতে হয়: একটি সাধারণ অর্ডার কত টাকার? ডেলিভারি কত দিনে হয়, আর তা কতটা অনিশ্চিত? বড় অর্ডারে কি দেরি বেশি? নতুন কুরিয়ার কি সত্যিই ধীর, নাকি এ মাসে কাকতালে এমন দেখাচ্ছে? প্রথম দুটি বর্ণনার প্রশ্ন (descriptive statistics), তৃতীয়টি সম্পর্কের, শেষটি অনুমানের (inference): নমুনা থেকে বড় জগৎ সম্পর্কে কিছু বলা। পর্ব ১৬-এ mean, std আর percentile হিসাবের যন্ত্র, পর্ব ২৯-এ box plot আর IQR, আর পর্ব ৩০-এ bootstrap CI-এর error bar দেখেছেন। এখানে সেই সংখ্যাগুলোর পেছনের যুক্তি: কেন এই সূত্র, কখন সেটি ঠকায়, আর ফলটি কী বলে, কী বলে না।

এই পাতার চালানো যায় এমন কোড চলে আপনার ব্রাউজারে (Pyodide: NumPy 2.4.6, SciPy 1.18.0, pandas 3.0.2, matplotlib 3.10.8). SciPy প্রথমবার লোড হতে কয়েক সেকেন্ড লাগতে পারে, পরের run দ্রুত। লেখকের ল্যাপটপের run-গুলো (Python 3.14.4, একই NumPy আর SciPy) আলাদা করে “সত্যিকারের run” বলে চিহ্নিত।

১ · কেন্দ্র — mean, median, mode আর trimmed mean

“একটি সাধারণ অর্ডার কত টাকার?” প্রশ্নের উত্তর একটি সংখ্যা, যাকে বলে কেন্দ্রের মাপ। চারটি প্রচলিত মাপ আছে, আর প্রতিটি একটু আলাদা প্রশ্নের উত্তর দেয়।

  • Mean (গড়): সব মান যোগ করে সংখ্যা দিয়ে ভাগ। প্রতীকে নমুনার গড় x̄ = (x1 + x2 + … + xn) / n, যেখানে n হলো মানের সংখ্যা। জনসংখ্যার (সব সম্ভাব্য অর্ডারের) আসল গড়কে লেখা হয় গ্রিক অক্ষর μ (মিউ) দিয়ে। গড়ের একটি সুন্দর গুণ: মোট = গড় × n. তাই মাসের মোট আয় অনুমান করতে গড়ই লাগে।
  • Median: মানগুলো ছোট থেকে বড় সাজালে ঠিক মাঝেরটি; জোড় সংখ্যক হলে মাঝের দুটির গড়। “অর্ধেক অর্ডার এর কম, অর্ধেক বেশি”.
  • Mode: সবচেয়ে বেশিবার আসা মান। ১ থেকে ৫ তারার রেটিং, পেমেন্ট পদ্ধতি বা জুতার মাপে এটিই সবচেয়ে অর্থপূর্ণ; ৪৯৩.৭ টাকার মতো ধারাবাহিক মানে প্রায় অর্থহীন, কারণ প্রতিটি মান একবারই আসে।
  • Trimmed mean: সাজানো মানের দুই প্রান্ত থেকে নির্দিষ্ট ভাগ বাদ দিয়ে বাকিগুলোর গড়। ক্রিকেটের কিছু রেটিং বা বিচারকদের নম্বরে সবচেয়ে বেশি আর সবচেয়ে কম নম্বর বাদ দেওয়ার যে রীতি, এটি তা-ই।

পার্থক্যটি সবচেয়ে ভালো বোঝা যায় একটি অস্বাভাবিক মান যোগ করলে। ধরুন দশটি সাধারণ অর্ডার: ৩৮০ থেকে ৬১০ টাকা, মোট ৪৯৮০ টাকা, তাই গড় ৪৯৮. সাজালে মাঝের দুটি ৪৯০ আর ৫০০, median ৪৯৫. এখন একটি অফিস একবারে ২৫,০০০ টাকার অর্ডার দিল। নতুন গড় = (৪৯৮০ + ২৫০০০) / ১১ = ২৯৯৮০ / ১১ ≈ ২৭২৫.৫ টাকা: এগারোটির দশটি অর্ডারই এর পাঁচ ভাগের এক ভাগের কম, তবু “সাধারণ অর্ডার” ২৭২৫ টাকা! median এখন এগারোটির মাঝের, মানে ষষ্ঠটি: ৫০০ টাকা, মাত্র ৫ টাকা নড়েছে। যে মাপ কয়েকটি চরম মানে প্রায় নড়ে না, তাকে বলে robust. median-এর “ভেঙে পড়ার বিন্দু” (breakdown point) ৫০%: অর্ধেকের কম মান যত খারাপই হোক, median অসীমে যায় না; গড়ের জন্য একটি মানই যথেষ্ট।

তাহলে কি সবসময় median? না, প্রশ্নটি দেখুন। “মাসে মোট কত টাকার পণ্য পৌঁছাতে হবে” প্রশ্নে ২৫,০০০ টাকার অর্ডারটিও সত্যিকারের, আর মোটের হিসাবে গড়ই ঠিক। “একজন সাধারণ ক্রেতা কত খরচ করেন” প্রশ্নে median. দাম বা ডেলিভারি-সময়ের মতো ডান দিকে লম্বা লেজের ডেটায় (ধনাত্মক skewness) দুটিই রিপোর্ট করুন: গড় median-এর চেয়ে অনেক বড় হলে সেটিই একটি তথ্য। ১০% trimmed mean দুইয়ের মাঝামাঝি: এগারোটি মানের প্রতিটি প্রান্ত থেকে একটি বাদ, তাই ২৫,০০০ বাদ পড়ে, ফল ৫১১.১ টাকা।

২ · ছড়ানো — range, variance, SD আর n − 1 কেন

দুটি কুরিয়ারের গড় ডেলিভারি-সময় সমান ৩ দিন হতে পারে, অথচ একটি সবসময় ২ থেকে ৪ দিনে দেয় আর অন্যটি কখনো ১ দিনে, কখনো ৯ দিনে। ক্রেতার কাছে দ্বিতীয়টি অনেক খারাপ। তাই কেন্দ্রের সঙ্গে লাগে ছড়ানোর মাপ।

Range সবচেয়ে সহজ: সবচেয়ে বড় − সবচেয়ে ছোট। দশটি অর্ডারে ৬১০ − ৩৮০ = ২৩০ টাকা। কিন্তু এটি মাত্র দুটি মান দেখে, তাই একটি outlier-এই নষ্ট হয়, আর নমুনা বড় হলে প্রায় সবসময় বাড়ে। IQR (মাঝের ৫০%-এর চওড়া) পর্ব ২৯-এর box plot-এ দেখেছেন; সেটি robust.

Variance সব মান ব্যবহার করে: প্রতিটি মান গড় থেকে কত দূরে (বিচ্যুতি, deviation), সেই দূরত্বের বর্গ, আর বর্গগুলোর গড়। বর্গ কেন? কারণ বিচ্যুতিগুলোর সাধারণ যোগফল সবসময় শূন্য (গড়ের সংজ্ঞাই তা), তাই সরাসরি গড় নিলে কিছুই পাওয়া যায় না। বর্গ চিহ্ন সরিয়ে দেয়। কিন্তু বর্গের একক “দিন²”, যা অর্থহীন; তাই তার বর্গমূল নিই, যার নাম standard deviation (SD), আবার “দিন” এককে। নমুনার জন্য সূত্র:

s2 = ∑(xi − x̄)2 / (n − 1),   s = √s2

এখানে s2 নমুনার variance, s নমুনার SD, আর জনসংখ্যার আসল মানকে লেখা হয় σ2 আর σ (সিগমা)। পাঁচটি অর্ডারের ডেলিভারি-দিন ২, ৪, ৪, ৫, ১০ দিয়ে ধাপে ধাপে দেখুন।

ডেলিভারি-দিন: 2, 4, 4, 5, 10লাল = এই ধাপের হিসাব

            
হিসাব
গড়
বর্গের যোগফল
variance
SD
  1. গড়। পাঁচটি মানের যোগফল ২৫, তাই গড় ৫ দিন। সব বিচ্যুতি মাপা হবে এই বিন্দু থেকে।
  2. বিচ্যুতি। প্রতিটি মান থেকে ৫ বিয়োগ: −৩, −১, −১, ০, +৫. যোগফল ঠিক ০, তাই শুধু যোগ করে ছড়ানো মাপা যায় না।
  3. বর্গ। ৯, ১, ১, ০, ২৫. ঋণাত্মক চিহ্ন চলে গেল, আর ৫ দিনের দূরত্ব ১ দিনের দূরত্বের ২৫ গুণ ওজন পেল।
  4. যোগফল। ∑ = ৩৬. এর ২৫ এসেছে একা ১০ দিনের অর্ডারটি থেকে: variance-ও গড়ের মতো outlier-এ খুব স্পর্শকাতর।
  5. ভাগ। পাঁচটিই যদি পুরো জগৎ হয়, ৫ দিয়ে ভাগ: ৭.২ (NumPy-র default). এরা যদি সব অর্ডারের একটি নমুনা হয়, ৪ দিয়ে ভাগ: ৯.০ (pandas-এর default).
  6. বর্গমূল। SD ২.৬৮৩ বা ৩.০ দিন। “একটি অর্ডার সাধারণত গড় থেকে প্রায় ৩ দিন দূরে”, মোটা দাগে।

n − 1 কেন — সহজ ভাষায়

বিচ্যুতি মাপা হয়েছে নমুনার গড় x̄ থেকে, আসল গড় μ থেকে নয় (μ অজানা)। আর x̄ হলো সেই বিন্দু, যেখান থেকে এই নমুনার বর্গের যোগফল সবচেয়ে কম; তাই μ থেকে মাপলে যা হতো, x̄ থেকে মাপলে যোগফল প্রায় সবসময় তার চেয়ে কম, আর n দিয়ে ভাগ করা variance গড়ে আসল σ2-এর চেয়ে ছোট আসে। n − 1 দিয়ে ভাগ করলে ঘাটতি ঠিক পূরণ হয়; এর নাম Bessel's correction. আরেকভাবে: বিচ্যুতির যোগফল শূন্য হতেই হবে, তাই প্রথম চারটি জানলে পঞ্চমটি আর স্বাধীন নয়; স্বাধীন টুকরো n − 1 টি, যার নাম degrees of freedom (df). নিচের কোডে এটি সত্যিই মাপা হয়েছে: ১,০০,০০০টি পাঁচ-মানের নমুনা, আসল variance ৪.

import numpy as np
import pandas as pd
from scipy import stats

# 10 ordinary orders, money kept in integer paisa
paisa = np.array([45_000, 52_000, 38_000, 61_000, 47_000,
                  55_000, 49_000, 43_000, 58_000, 50_000], dtype=np.int64)
taka = paisa / 100
big = np.append(taka, 25_000.0)          # one office order of 25,000 taka
for name, x in [("10 orders", taka), ("+ 1 big", big)]:
    print(f"{name:9} mean {x.mean():7.1f}  median {np.median(x):5.1f}"
          f"  trim10% {stats.trim_mean(x, 0.1):5.1f}")

ratings = np.array([5, 4, 5, 3, 5, 4, 1, 5, 4, 5])
m = stats.mode(ratings)
print("rating mode:", m.mode, "seen", m.count, "times")

days = np.array([2, 4, 4, 5, 10])        # delivery days, 5 orders
s = pd.Series(days)
print("numpy  var:", np.var(days), "| ddof=1:", np.var(days, ddof=1))
print("pandas var:", s.var(), "| ddof=0:", s.var(ddof=0))
print("numpy  std:", round(np.std(days), 3), "| pandas std:", s.std())

# why n-1: 100,000 samples of 5 from a population with variance 4
rng = np.random.default_rng(42)
smp = rng.normal(0, 2, size=(100_000, 5))
print("avg var ddof=0:", round(smp.var(axis=1).mean(), 3),
      "| ddof=1:", round(smp.var(axis=1, ddof=1).mean(), 3))

print("SD with big order:", round(np.std(big, ddof=1), 1),
      "| MAD:", stats.median_abs_deviation(big))
print("CV of 10 orders:", round(np.std(taka, ddof=1) / taka.mean(), 3))

ব্রাউজারে (Pyodide) একটি run-এর আসল আউটপুট:

10 orders mean   498.0  median 495.0  trim10% 498.8
+ 1 big   mean  2725.5  median 500.0  trim10% 511.1
rating mode: 5 seen 5 times
numpy  var: 7.2 | ddof=1: 9.0
pandas var: 9.0 | ddof=0: 7.2
numpy  std: 2.683 | pandas std: 3.0
avg var ddof=0: 3.203 | ddof=1: 4.004
SD with big order: 7387.9 | MAD: 50.0
CV of 10 orders: 0.141

প্রথম দুই লাইন হাতের হিসাবই: গড় ৪৯৮ থেকে ২৭২৫.৫, median ৪৯৫ থেকে ৫০০, trimmed mean ৪৯৮.৮ থেকে ৫১১.১. রেটিং-এর mode ৫, দশটির পাঁচটিই ৫ তারা। তারপর একই পাঁচটি ডেলিভারি-দিনে NumPy দিল ৭.২, pandas ৯.০, ঠিক stepper-এর দুটি ভাগ; কেউ ভুল নয়, শুধু default আলাদা (পর্ব ১৬). পরের লাইনটি n − 1-এর প্রমাণ: আসল variance ৪, অথচ n দিয়ে ভাগ করা অনুমানের গড় ৩.২, প্রায় ঠিক (n − 1)/n × ৪ = ০.৮ × ৪; n − 1 দিয়ে ভাগ করলে ৪.০০. শেষ দুই লাইন পরের অনুচ্ছেদের বিষয়।

MAD (median absolute deviation) হলো SD-র robust ভাই: প্রতিটি মান median থেকে কত দূরে, সেই দূরত্বগুলোর median. এগারোটি অর্ডারে (২৫,০০০ সহ) SD ৭৩৮৭.৯ টাকা, যা প্রায় পুরোটাই একটি অর্ডারের কারণে; MAD মাত্র ৫০ টাকা, বাকি দশটির আসল ছড়ানোর কাছাকাছি। Normal ডেটায় SD-র সঙ্গে তুলনা করতে MAD-কে প্রায় ১.৪৮২৬ দিয়ে গুণ করা হয় (SciPy-তে scale="normal").

Coefficient of variation (CV) = SD ÷ গড়, এককহীন: দশটি অর্ডারে ৭০.০ ÷ ৪৯৮ ≈ ০.১৪১, মানে ছড়ানো গড়ের প্রায় ১৪%. এটি দিয়ে ভিন্ন এককের জিনিসের ছড়ানো তুলনা করা যায়, তবে শুধু সবসময়-ধনাত্মক মানে; তাপমাত্রার মতো মানে CV অর্থহীন।

৩ · z-score আর outlier ধরার নিয়ম — z > 3 বনাম IQR-এর বেড়া

পরীক্ষায় অঙ্কে ৭০ আর বাংলায় ৭০ পেলেন; কোনটি ভালো? যদি অঙ্কে ক্লাসের গড় ৫০ আর SD ১০, বাংলায় গড় ৬৫ আর SD ৫, তাহলে অঙ্কের ৭০ গড়ের ২ SD ওপরে, বাংলার ৭০ মাত্র ১ SD ওপরে। এই “গড় থেকে কতটি SD দূরে” সংখ্যাটির নাম z-score:

z = (x − x̄) / s

পুরো কলামকে z-score-এ বদলানো (standardisation) দিলে গড় ০, SD ১; ভিন্ন এককের feature এক মাপে আনতে machine learning-এ এটি প্রচলিত (পর্ব ৬৩). এটি আকৃতি বদলায় না: বাঁকা ডেটা বাঁকাই থাকে।

Outlier খুঁজতে প্রচলিত নিয়ম “|z| > ৩ হলে outlier”, কারণ normal ডেটায় ৩ SD-র বাইরে প্রায় ০.৩% মান পড়ে। কিন্তু এতে একটি ফাঁদ আছে (masking): outlier নিজেই SD ফুলিয়ে দেয়, তাই নিজের z ছোট দেখায়। ছোট নমুনায় এটি গাণিতিকভাবে বাঁধা: n টি মানে কোনো |z| কখনো (n − 1)/√n-এর বেশি হতে পারে না। n = ১০-এ সেই সীমা ২.৮৪৬, মানে দশটি মানে z > ৩ কখনোই কিছু ধরবে না। n = ১১-এ সীমা ৩.০১৫, আর ২৫,০০০ টাকার অর্ডারের z আসে ৩.০১ (লেখকের যন্ত্রে মাপা): কোনোমতে সীমা পার, অথচ অর্ডারটি বাকিগুলোর পঞ্চাশ গুণ!

IQR-এর বেড়া (Tukey-র নিয়ম, পর্ব ২৯-এর box plot-এর whisker) median আর quartile দিয়ে তৈরি, তাই outlier নিজে বেড়া সরাতে পারে না। এগারোটি অর্ডারে Q1 = ৪৬০, Q3 = ৫৬৫, IQR = ১০৫; ওপরের বেড়া ৫৬৫ + ১.৫ × ১০৫ = ৭২২.৫ টাকা। ২৫,০০০ বহু দূরে বাইরে, স্পষ্টভাবে ধরা পড়ে।

নিয়মকীসের ওপর দাঁড়িয়েসুবিধাসাবধান
|z| > ৩গড় আর SDnormal-এর মতো বড় ডেটায় সহজ ব্যাখ্যাoutlier নিজেই SD ফোলায়; ছোট n-এ কিছুই ধরে না; বাঁকা ডেটায় অনেক সাধারণ মানকে ধরে
Q1 − ১.৫ IQR, Q3 + ১.৫ IQRquartilerobust, আকৃতি ধরে নেয় নালম্বা লেজের ডেটায় (দাম, সময়) বহু বৈধ মানকেও বাইরে দেখায়
median ± ৩ × MAD (স্কেল করা)median আর MADrobust z-score-এর মতোঅর্ধেকের বেশি মান একই হলে MAD শূন্য হয়ে যায়

কোনো নিয়ম “এটি ভুল ডেটা” বলে না। এগুলো শুধু বলে কোন মান একবার চোখে দেখা দরকার। ২৫,০০০ টাকার অর্ডার টাইপের ভুল হতে পারে, আবার সত্যিকারের অফিস অর্ডারও হতে পারে। কারণ না জেনে মুছবেন না; কী বাদ দিলেন আর কেন, লিখে রাখুন (পর্ব ২৩)।

৪ · Covariance আর Pearson correlation — হাতে ৫টি বিন্দু, তারপর Spearman

“বড় অর্ডারে কি প্যাক করতে বেশি সময় লাগে?” দুটি সংখ্যা একসঙ্গে বাড়ে কি না, তার প্রথম মাপ covariance. ধারণাটি: প্রতিটি অর্ডারে x (পণ্যের সংখ্যা) গড়ের ওপরে না নিচে, আর y (প্যাকিং-মিনিট) গড়ের ওপরে না নিচে। দুটিই ওপরে বা দুটিই নিচে হলে বিচ্যুতির গুণফল ধনাত্মক, একটি ওপরে একটি নিচে হলে ঋণাত্মক। গুণফলগুলোর গড়ই covariance:

cov(x, y) = ∑(xi − x̄)(yi − ȳ) / (n − 1)

সমস্যা হলো covariance-এর মান এককের ওপর নির্ভর করে: মিনিটের বদলে সেকেন্ডে মাপলে ৬০ গুণ হয়ে যায়, অথচ সম্পর্ক একই। তাই দুই SD দিয়ে ভাগ করে এককহীন করা হয়; ফল Pearson correlation r, যা সবসময় −১ থেকে +১-এর মধ্যে:

r = ∑(xi − x̄)(yi − ȳ) / √[ ∑(xi − x̄)2 · ∑(yi − ȳ)2 ]

(n − 1) ওপরে-নিচে কেটে যায়, তাই r-এ ddof নিয়ে ভাবতে হয় না। পাঁচটি অর্ডার দিয়ে হাতে হিসাব করুন:

অর্ডারx (পণ্য)y (মিনিট)x − x̄y − ȳগুণফল(x − x̄)2(y − ȳ)2
১12−2−2444
২24−10010
৩3501001
৪4410010
৫5521241
যোগফল (x̄ = 3, ȳ = 4)006106

covariance = ৬ / ৪ = ১.৫; r = ৬ / √(১০ × ৬) = ৬ / √৬০ ≈ ৬ / ৭.৭৪৬ ≈ ০.৭৭৫. একটি বেশ শক্ত ধনাত্মক সম্পর্ক, তবে নিখুঁত নয় (চতুর্থ অর্ডারে পণ্য বেশি, সময় কম)। r-এর অর্থ মনে রাখার একটি উপায়: r2 ≈ ০.৬, মোটা দাগে y-এর ছড়ানোর প্রায় ৬০% একটি সরলরেখা দিয়ে x থেকে “ব্যাখ্যা” করা যায় (পর্ব ৫৮-এ linear regression-এ এর পূর্ণ অর্থ)।

Pearson কী ধরে না — বাঁকা সম্পর্ক আর outlier

Pearson r মাপে শুধু সরলরৈখিক সম্পর্ক। দুটি সাধারণ বিপদ আছে। প্রথমত, সম্পর্ক একমুখী (monotone, x বাড়লে y সবসময় বাড়ে) কিন্তু বাঁকা হলে r ১-এর কম আসে, যদিও সম্পর্কটি নিখুঁত। দ্বিতীয়ত, একটি চরম বিন্দু একাই r-কে বানিয়ে দিতে বা নষ্ট করতে পারে। দুটির ওষুধ Spearman rank correlation (ρ, রো): প্রতিটি মানকে তার ক্রম (rank: সবচেয়ে ছোট ১, তারপর ২ …) দিয়ে বদলে তারপর Pearson. ক্রমে বাঁক আর দূরত্ব হারিয়ে যায়, থাকে শুধু “কে কার চেয়ে বড়”. পরিসংখ্যানবিদ ও মনোবিজ্ঞানী Charles Spearman ১৯০৪ সালে এটি প্রকাশ করেন; Pearson-এর সূত্র দাঁড়িয়ে আছে Francis Galton-এর ১৮৮০-এর দশকের কাজ আর Karl Pearson-এর ১৮৯০-এর দশকের প্রবন্ধের ওপর।

import numpy as np
from scipy import stats

# hand example: items in an order vs packing minutes
x = np.array([1, 2, 3, 4, 5])
y = np.array([2, 4, 5, 4, 5])
print("cov matrix (ddof=1):\n", np.cov(x, y))
print("r by hand 6/sqrt(60) =", round(6 / np.sqrt(60), 4),
      "| np.corrcoef:", round(np.corrcoef(x, y)[0, 1], 4))

rng = np.random.default_rng(42)
# 1) monotone but curved: discount % vs orders (grows fast)
disc = np.arange(1, 21)
orders = np.round(30 * 1.25 ** disc)
p, s = stats.pearsonr(disc, orders), stats.spearmanr(disc, orders)
print(f"curve:   pearson {p.statistic:.3f}  spearman {s.statistic:.3f}")

# 2) no real link, then one extreme order added
qty = rng.integers(1, 6, 20)
days = rng.integers(1, 6, 20)
for label, a, b in [("no link", qty, days),
                    ("+outlier", np.append(qty, 60), np.append(days, 30))]:
    p, s = stats.pearsonr(a, b), stats.spearmanr(a, b)
    print(f"{label:8} pearson {p.statistic:.3f} (p={p.pvalue:.3f})"
          f"  spearman {s.statistic:.3f} (p={s.pvalue:.3f})")

ব্রাউজারে একটি run-এর আসল আউটপুট:

cov matrix (ddof=1):
 [[2.5 1.5]
 [1.5 1.5]]
r by hand 6/sqrt(60) = 0.7746 | np.corrcoef: 0.7746
curve:   pearson 0.881  spearman 1.000
no link  pearson -0.271 (p=0.248)  spearman -0.330 (p=0.156)
+outlier pearson 0.962 (p=0.000)  spearman -0.139 (p=0.549)

np.cov-এর কর্ণে x আর y-এর variance (২.৫, ১.৫), কোণে covariance ১.৫, আর np.corrcoef-এর ০.৭৭৪৬ হাতের ৬/√৬০-এর সঙ্গে মেলে। লক্ষ করুন, np.cov-এর default ddof=1, np.var-এর উল্টো।

বাঁকা কিন্তু নিখুঁত একমুখী সম্পর্কে Spearman ঠিক ১.০০০, Pearson ০.৮৮১. তৃতীয় লাইনের দুটি কলামে কোনো সম্পর্ক বানানো হয়নি, তবু ২০টি বিন্দুতে কাকতালে r = −০.২৭, আর p = ০.২৪৮ বলছে এমন মান কাকতালে সহজেই আসে। শেষ লাইনটি বিপদ: একটি মাত্র অর্ডার (৬০টি পণ্য, ৩০ দিন) যোগ করায় Pearson ০.৯৬২ আর p ছাপা হয়েছে ০.০০০, অথচ Spearman প্রায় নড়েনি (−০.১৩৯), কারণ ক্রমে ওই বিন্দুটি শুধু “সবচেয়ে বড়”. শিক্ষা: r দেখার আগে scatter দেখুন (পর্ব ২৯), আর দুটি correlation অনেক আলাদা হলে কারণ খুঁজুন।

আরেকটি সীমা: r = ০ মানে শুধু “সরলরৈখিক সম্পর্ক নেই”, সম্পর্ক নেই নয়; U-আকারের সম্পর্কে r ০ হতে পারে (অনুশীলন ২).

৫ · Correlation মানে কারণ নয় — confounder আর Simpson

গ্রীষ্মে আইসক্রিমের বিক্রি বাড়ে, পানিতে ডোবার ঘটনাও বাড়ে; দুটির correlation ধনাত্মক। কিন্তু আইসক্রিম কাউকে ডোবায় না: গরম দুটিকেই বাড়ায়। এমন তৃতীয় চলককে বলে confounder, আর তার কারণে তৈরি ভুয়া সম্পর্ককে spurious correlation. বাজারঘরে একই গল্প: ঈদের সপ্তাহে অর্ডারের আকারও বাড়ে, ডেলিভারির দেরিও বাড়ে (কুরিয়ারের ভিড়)। সব সপ্তাহ মিলিয়ে “বড় অর্ডারে দেরি বেশি” দেখা যাবে, অথচ ঈদ আর সাধারণ সপ্তাহ আলাদা করলে সম্পর্ক প্রায় শূন্য হতে পারে। পর্ব ২৪-এ Simpson's paradox-এ এর চরম রূপ দেখেছেন: দলে দলে যে প্রবণতা, সব মেলালে তার উল্টো।

Correlation থেকে কারণ বলার আগে প্রশ্ন করুন: তৃতীয় কিছু (ঈদ, জেলা, ক্রেতার ধরন) দুটিকেই প্রভাবিত করছে কি? কারণ কি উল্টো দিকে (বেশি কেনেন বলেই কুপন পান)? শুধু একটি বাছাই করা দল দেখছি কি? নাকি অনেক জোড়ার মধ্যে একটি কাকতালে বড় এসেছে (অংশ ৯)?

কারণ জানার সবচেয়ে নির্ভরযোগ্য পথ এলোমেলো ভাগ করা পরীক্ষা (randomised experiment): লটারি করে ক্রেতাদের দুই দলে ভাগ করে একটিকে নতুন ব্যবস্থা দেওয়া। লটারি গড়ে confounder-গুলো দুই দলে সমান ভাগ করে। ধারণাটি ১৯২০-৩০-এর দশকে কৃষি গবেষণায় Ronald Fisher জনপ্রিয় করেন; আজকের A/B test (অংশ ৯) এরই উত্তরসূরি।

৬ · নমুনার গড়ও নড়ে — sampling distribution, standard error আর CLT

এ মাসের ৩০টি ডেলিভারির গড় ২.৩ দিন; পরের মাসের ৩০টির গড় প্রায় নিশ্চিতভাবে আলাদা হবে। একই আকারের অনেক নমুনা নিলে নমুনার গড়গুলো যেভাবে ছড়ায়, তাকে বলে sampling distribution. চায়ের দোকানে একটি কাপ খুব মিষ্টি হতে পারে, কিন্তু দশ কাপের গড় মিষ্টতা দিনে দিনে অনেক কম নড়ে। এই “গড় কম নড়ে”-র মাপ standard error (SE):

SE(x̄) = σ / √n,   বাস্তবে অনুমান: s / √n

√n-এর দিকে খেয়াল করুন: নমুনা চার গুণ করলে SE অর্ধেক, একশো গুণ করলে দশ ভাগের এক ভাগ। আর SD বলে একটি অর্ডার কত ছড়ায় (নমুনা বাড়লেও প্রায় একই থাকে), SE বলে গড় কত নড়ে (নমুনা বাড়লে কমে); পর্ব ৩০-এর error bar-এ এই দুটি দাগই দেখেছেন।

এখন সবচেয়ে চমকপ্রদ কথাটি। বাজারঘরের ডেলিভারি-সময় ধরুন exponential distribution মানে (গড় μ = ২ দিন, SD σ = ২ দিন; distribution-গুলো পর্ব ৩৬-এ)। এটি খুব বাঁকা: বেশিরভাগ অর্ডার তাড়াতাড়ি, কয়েকটি অনেক দেরিতে। তবু ৩০টি করে অর্ডারের গড় নিলে, সেই গড়গুলোর histogram প্রায় একটি ঘণ্টা। এটিই Central Limit Theorem (CLT): স্বাধীন, একই distribution-এর, সসীম variance-এর মান থেকে নেওয়া নমুনার গড় n বড় হলে প্রায় normal, গড় μ আর SD σ/√n, মূল ডেটার আকৃতি যা-ই হোক।

বাঁকা জনসংখ্যা থেকে প্রায় ঘণ্টা-আকারের গড়

ওপরে সব ডেলিভারির distribution, মাঝে তিনটি আসল নমুনা, নিচে ১০,০০০টি নমুনার গড়ের histogram (seed 42)

Central Limit Theorem: সব অর্ডার, নমুনা আর নমুনার গড় জনসংখ্যা: সব ডেলিভারি (μ = 2, σ = 2) μ = 2 লম্বা ডান লেজ 0246810 দিন নমুনা ১, n = 30গড় 1.87 নমুনা ২, n = 30গড় 1.43 নমুনা ৩, n = 30গড় 2.20 … ১০,০০০ বার: গড়গুলোর histogram 123 দিন লাল রেখা: normal, গড় 2, SD = 2/√30 ≈ 0.365 ডানে সামান্য লেজ এখনো আছে (skew ≈ 0.37)

মাঝের তিনটি নমুনা লক্ষ করুন: একই জনসংখ্যা, একই n, অথচ গড় ১.৮৭, ১.৪৩ আর ২.২০. দ্বিতীয়টি পেলে কেউ হয়তো বলতেন “আমাদের ডেলিভারি দেড় দিনে”! নিচের histogram বলে এমন নমুনা অস্বাভাবিক নয়: গড়গুলোর SD ০.৩৬৫, আর ১.৪৩ মাত্র প্রায় ১.৬ SE নিচে।

Abraham de Moivre ১৭৩৩ সালে মুদ্রা ছোড়ার গণনায় এর প্রথম রূপ পান, Laplace পরে তা বড় করেন, আর নামটি George Pólya-র ১৯২০ সালের প্রবন্ধ থেকে। Machine learning-এ এটি সর্বত্র: test set-এর accuracy অনেকগুলো ০/১-এর গড়, তাই তার অনিশ্চয়তা SE দিয়ে মাপা যায় (পর্ব ৬০)।

যেখানে CLT খাটে না — ভারী লেজ

CLT-এর শর্ত “সসীম variance” শুধু কাগুজে নয়। কিছু distribution-এ চরম মান এত ঘন ঘন আসে যে variance, এমনকি গড়ও, সংজ্ঞায়িত নয়; এদের বলে heavy-tailed. সবচেয়ে পরিচিত উদাহরণ Cauchy distribution. লেখকের ল্যাপটপে সত্যিকারের run (Python 3.14.4, NumPy 2.4.6): দশ লাখ মান পর্যন্ত চলমান গড়, exponential আর Cauchy পাশাপাশি।

~/bazarghar-ai$ python cauchy.py
n=       10  exponential  2.921  cauchy   1.329
n=      100  exponential  1.798  cauchy   4.448
n=    1,000  exponential  2.029  cauchy   0.424
n=   10,000  exponential  1.977  cauchy  -0.396
n=  100,000  exponential  2.007  cauchy   1.686
n=1,000,000  exponential  2.000  cauchy  10.830
largest |cauchy| value: 8,308,267
cauchy median: -0.0007

Exponential-এর চলমান গড় ধীরে ধীরে ২-এর কাছে থিতু হয়, যা law of large numbers. Cauchy-র গড় কোথাও থামে না: ১০০-এ ৪.৪৫, দশ হাজারে −০.৪০, আর দশ লাখে হঠাৎ ১০.৮৩, কারণ একটি মান এসেছে প্রায় ৮৩ লাখ। Cauchy-র যত মানেরই গড় নিন, তা একটি মানের মতোই অনিশ্চিত থাকে; অথচ median ০-এর খুব কাছে। আর্থিক বাজারের রিটার্ন বা ভাইরাল পোস্টের share সংখ্যায় ভারী লেজ দেখা যায় বলে অনেক গবেষক মনে করেন; সেগুলো ঠিক কতটা ভারী, তা নিয়ে বিতর্ক আছে, কিন্তু সতর্কতা একই: “নমুনা বড়, তাই গড় নিশ্চিত” সব ডেটায় সত্য নয়।

৭ · Confidence interval — t-interval আর “৯৫%”-এর সঠিক অর্থ

CLT বলছে x̄ সাধারণত μ থেকে প্রায় ২ SE-এর মধ্যে থাকে; উল্টো করে পড়লে x̄ ± প্রায় ২ SE একটি পরিসর, যা সাধারণত μ-কে ঘিরে রাখে: confidence interval (CI). তবে SE-তে σ-এর বদলে s বসাই, আর ছোট নমুনায় s নিজেও নড়ে। William Sealy Gosset ১৯০৮ সালে “Student” ছদ্মনামে দেখান যে তখন অনিশ্চয়তা একটু মোটা লেজের t-distribution মানে, যার আকৃতি df = n − 1-এর ওপর নির্ভর করে আর df বাড়লে normal-এর কাছে যায় (গল্পটি ভাবনার প্রশ্ন ১-এ)।

CI = x̄ ± t০.৯৭৫, n−1 × s / √n

এখানে t০.৯৭৫, n−1 হলো t-distribution-এর সেই বিন্দু, যার নিচে ৯৭.৫% (তাই দুই পাশে ২.৫% করে বাদ, মাঝে ৯৫%). লেখকের SciPy-তে মাপা: df = ৪-এ ২.৭৭৬, ৭-এ ২.৩৬৫, ২৯-এ ২.০৪৫, ১০০০-এ ১.৯৬২, যা normal-এর ১.৯৬-এর প্রায় সমান। ছোট নমুনায় তাই interval চওড়া: অনিশ্চয়তার সৎ মূল্য। আটটি অর্ডার দিয়ে একটি interval ধাপে ধাপে বানান।

৮টি অর্ডারের ডেলিভারি-দিনলাল = এই ধাপের হিসাব

            
হিসাব
x̄
s
SE
interval
  1. নমুনা। আটটি অর্ডার, তাই df = ৭. ধরে নিচ্ছি অর্ডারগুলো একে অপরের থেকে স্বাধীন আর একই ধরনের।
  2. গড়। যোগফল ২০, গড় ২.৫ দিন। এটি আমাদের সেরা একক অনুমান (point estimate).
  3. SD. বিচ্যুতির বর্গের যোগফল ৭, n − 1 = ৭ দিয়ে ভাগ করে s2 = ১, s = ১ দিন।
  4. Standard error. ১ / √৮ ≈ ০.৩৫৪: আট অর্ডারের গড় সাধারণত এতটুকু নড়ে।
  5. t-এর মান। df = ৭-এ ৯৫%-এর জন্য ২.৩৬৫, normal-এর ১.৯৬-এর চেয়ে বড়, কারণ s-ও অনুমান।
  6. Interval. ২.৫ ± ০.৮৩৬ = ১.৬৬৪ থেকে ৩.৩৩৬ দিন; SciPy-র t.interval হুবহু একই। 1.96 নিলে পেতেন ১.৮০৭ থেকে ৩.১৯৩, যা ভুলভাবে সরু।

“৯৫%” মানে আসলে কী

সবচেয়ে প্রচলিত ভুল ব্যাখ্যা: “আসল গড় ৯৫% সম্ভাবনায় ১.৬৬৪ থেকে ৩.৩৩৬-এর মধ্যে।” প্রচলিত (frequentist) পরিসংখ্যানে μ একটি নির্দিষ্ট অজানা সংখ্যা; এই interval হয় তাকে ধরেছে, নয় ধরেনি। এলোমেলো হলো পদ্ধতিটি। সঠিক অর্থ: “এই পদ্ধতি বারবার নতুন নমুনায় প্রয়োগ করলে প্রায় ৯৫% interval আসল গড়কে ধরবে।” Jerzy Neyman ১৯৩৭ সালের প্রবন্ধে তত্ত্বটি এভাবেই দেন। simulation-এ আমরা μ জানি, তাই ১০০০টি interval বানিয়ে গুনে দেখা যায় কতগুলো μ ধরল; নিচের কোডে প্রথমে অংশ ৬-এর CLT histogram, তারপর এই গণনা। (Bayesian “credible interval”-এর অর্থ সত্যিই “μ এখানে থাকার সম্ভাবনা”, তবে তার জন্য prior লাগে; পর্ব ৫০.)

import numpy as np
import matplotlib.pyplot as plt
from scipy import stats

rng = np.random.default_rng(42)
mu = sigma = 2.0                  # exponential: mean 2 days, SD 2 days
fig, axs = plt.subplots(1, 3, figsize=(8, 2.8), dpi=100)
for ax, n in zip(axs, [1, 5, 30]):
    means = rng.exponential(mu, size=(10_000, n)).mean(axis=1)
    ax.hist(means, bins=40, color="#2563eb", alpha=0.8)
    ax.set(title=f"n = {n}", xlabel="Mean delivery days", yticks=[])
    print(f"n={n:2}  SD of means {means.std(ddof=1):.3f}  sigma/sqrt(n) "
          f"{sigma / np.sqrt(n):.3f}  skew {stats.skew(means):.2f}")
fig.suptitle("10,000 sample means from exponential delivery times")
fig.tight_layout(); plt.show()

# coverage: 1,000 samples, one 95% t-interval each
draw = {"normal": lambda k: rng.normal(mu, sigma, size=(1_000, k)),
        "expon": lambda k: rng.exponential(mu, size=(1_000, k))}
for kind, n in [("normal", 10), ("expon", 5), ("expon", 30)]:
    x = draw[kind](n)
    m, se = x.mean(axis=1), x.std(axis=1, ddof=1) / np.sqrt(n)
    t = stats.t.ppf(0.975, df=n - 1)
    hit = (m - t * se <= mu) & (mu <= m + t * se)
    print(f"{kind:6} n={n:2}  t={t:.3f}  caught mu=2: {hit.sum()} / 1000")

ব্রাউজারে একটি run-এর আসল আউটপুট (ছবিটি কোডের নিচে):

n= 1  SD of means 1.985  sigma/sqrt(n) 2.000  skew 1.99
n= 5  SD of means 0.898  sigma/sqrt(n) 0.894  skew 0.93
n=30  SD of means 0.367  sigma/sqrt(n) 0.365  skew 0.37
normal n=10  t=2.262  caught mu=2: 956 / 1000
expon  n= 5  t=2.776  caught mu=2: 886 / 1000
expon  n=30  t=2.045  caught mu=2: 924 / 1000

n = ১-এ histogram হুবহু exponential, n = ৫-এ লেজ ছোট, n = ৩০-এ প্রায় প্রতিসম ঘণ্টা। গড়গুলোর SD (১.৯৮৫, ০.৮৯৮, ০.৩৬৭) প্রায় σ/√n (২.০০০, ০.৮৯৪, ০.৩৬৫), আর skew ১.৯৯ থেকে ০.৩৭-এ নামে, তত্ত্বের ২/√n-এর মতো; তবে শূন্য হয় না: “৩০ হলেই normal” মোটা দাগের নিয়ম, আইন নয়।

Coverage: normal ডেটায় (n = ১০) ১০০০টির ৯৫৬টি interval μ = ২ ধরেছে, প্রতিশ্রুত প্রায় ৯৫% (১০০০টিতে ±১৪-এর মতো ওঠানামা স্বাভাবিক)। বাঁকা exponential ডেটায় n = ৫-এ মাত্র ৮৮৬, n = ৩০-এও ৯২৪: “৯৫%” interval আসলে প্রায় ৮৯% আর ৯২%, কারণ t-interval গড়কে normal ধরে। এমন ডেটায় নমুনা বড় করুন, log নিয়ে কাজ করুন বা bootstrap বিবেচনা করুন, আর নিজের ডেটার মতো simulation দিয়ে coverage যাচাই করুন। এটি একটি run-এর ফল; seed বদলালে সংখ্যা একটু বদলাবে।

৮ · Hypothesis test আর p-value — দুই কুরিয়ারের তুলনা

বাজারঘর দুটি কুরিয়ার ব্যবহার করে (দুটিই কাল্পনিক): “দ্রুতপথ” (কোডে Droot) আর “সবুজ” (Sobuj). এ মাসে দ্রুতপথের ৪০টি অর্ডারের গড় ২.১২ দিন, সবুজের ৩৫টির ২.৬২ দিন। পার্থক্য প্রায় আধা দিন। প্রশ্ন: সবুজ কি সত্যিই ধীর, নাকি এ মাসের অর্ডারগুলোয় কাকতালে এমন এসেছে? অংশ ৬ দেখিয়েছে, একই কুরিয়ারের দুই মাসের গড়ও আলাদা হয়।

Hypothesis test-এর যুক্তি আদালতের মতো। শুরুতে ধরে নেওয়া হয় “অভিযুক্ত নির্দোষ”: এখানে null hypothesis H0, “দুই কুরিয়ারের আসল গড় সমান; যা পার্থক্য দেখছি, তা শুধু নমুনার কাকতাল”. তারপর প্রশ্ন: H0 সত্য হলে এত বড় (বা আরও বড়) পার্থক্য কত ঘন ঘন দেখা যেত? সেই সম্ভাবনাই p-value. ছোট p মানে “H0 সত্য হলে এমন ডেটা বিরল”, তাই H0-এর বিরুদ্ধে প্রমাণ। কিন্তু আদালতে “প্রমাণের অভাবে খালাস” মানে “নির্দোষ প্রমাণিত” নয়; তেমনি বড় p মানে “পার্থক্য নেই প্রমাণিত” নয়, শুধু “এই ডেটায় যথেষ্ট প্রমাণ নেই”.

p-value কী নয় — ASA-র বিবৃতি

p-value-এর ভুল ব্যবহার এত ব্যাপক হয়ে উঠেছিল যে আমেরিকান স্ট্যাটিস্টিক্যাল অ্যাসোসিয়েশন (ASA) ২০১৬ সালে প্রথমবারের মতো একটি নির্দিষ্ট পরিসংখ্যানিক পদ্ধতি নিয়ে আনুষ্ঠানিক বিবৃতি দেয় (Ronald Wasserstein আর Nicole Lazar, The American Statistician). তার ছয়টি নীতি, সংক্ষেপে:

  1. p-value বলতে পারে ডেটা একটি নির্দিষ্ট পরিসংখ্যানিক মডেলের সঙ্গে কতটা বেমানান।
  2. p-value মাপে না যে hypothesis সত্য হওয়ার সম্ভাবনা কত, বা ডেটা শুধু কাকতালে তৈরি হওয়ার সম্ভাবনা কত।
  3. বৈজ্ঞানিক সিদ্ধান্ত, ব্যবসা বা নীতির সিদ্ধান্ত শুধু p একটি সীমা পার হলো কি না, তার ওপর দাঁড়ানো উচিত নয়।
  4. সঠিক সিদ্ধান্তের জন্য পূর্ণ রিপোর্ট আর স্বচ্ছতা লাগে।
  5. p-value বা “statistical significance” প্রভাবের আকার বা ফলের গুরুত্ব মাপে না।
  6. একা p-value কোনো মডেল বা hypothesis-এর পক্ষে-বিপক্ষে প্রমাণের ভালো মাপ নয়।

তাই “p = ০.০৩, মানে ৯৭% সম্ভাবনায় সবুজ ধীর” ভুল (নীতি ২); “p = ০.৪০, তাই দুটি সমান” ভুল; আর “p = ০.০০১, তাই পার্থক্য বিশাল” ভুল (নীতি ৫)। ০.০৫ সীমাটিও কোনো প্রাকৃতিক নিয়ম নয়; Ronald Fisher ১৯২০-এর দশকে একে একটি সুবিধাজনক মোটা দাগের সীমা হিসেবে প্রস্তাব করেছিলেন বলে সাধারণত বলা হয়, পরে তা প্রায় আইনের মতো ব্যবহৃত হয়।

Welch t-test আর permutation test

দুই দলের গড়ের তুলনার প্রচলিত পদ্ধতি t-test: পার্থক্যকে তার SE দিয়ে ভাগ করে t, তারপর t-distribution থেকে p. পুরোনো “Student” সংস্করণ দুই দলের variance সমান ধরে; Bernard Welch ১৯৪৭ সালে এমন সংস্করণ দেন, যা তা ধরে না: Welch t-test, SciPy-তে ttest_ind(..., equal_var=False). variance সমান হলেও এটি প্রায় একই ফল দেয়, তাই অনেক পরিসংখ্যানবিদ একেই default হিসেবে সুপারিশ করেন।

দ্বিতীয় পথ শুধু simulation: permutation test. H0 সত্য হলে, মানে কুরিয়ারের নামে কিছু যায় আসে না, তাহলে কোন অর্ডারে কোন লেবেল, তা এলোমেলো করলেও কিছু বদলানোর কথা নয়। তাই লেবেল হাজারবার এলোমেলো করে প্রতিবার গড়ের পার্থক্য লিখুন, আর দেখুন আসলটির মতো বড় পার্থক্য কত ভাগ ক্ষেত্রে আসে। ধারণাটি Fisher-এর ১৯৩৫ সালের বই The Design of Experiments-এ পাওয়া যায়। প্রথমে ছয়টি অর্ডারে হাতে দেখুন।

দ্রুতপথ: 2, 3, 4 দিন · সবুজ: 5, 6, 7 দিনলাল = এই ধাপ

            
হিসাব
আসল পার্থক্য
শেষ শাফলের পার্থক্য
p-value
  1. আসল পার্থক্য। সবুজের গড় দ্রুতপথের চেয়ে ৩ দিন বেশি। এটিই আমাদের test statistic.
  2. H0-এর জগৎ। কুরিয়ারে কিছু যায় আসে না ধরলে ছয়টি মান একটি ঝুড়ি; কোন তিনটি “দ্রুতপথ” পেল, তা শুধু ভাগ্য।
  3. প্রথম শাফল। A = [২, ৫, ৭], B = [৩, ৪, ৬]: পার্থক্য মাত্র −০.৩৩৩. এলোমেলো লেবেলে সাধারণত এমন ছোট পার্থক্যই আসে।
  4. দ্বিতীয় শাফল। A = [৩, ৬, ৭], B = [২, ৪, ৫]: পার্থক্য −১.৬৬৭, এবার উল্টো দিকে।
  5. সব সম্ভাব্য ভাগ। ছয়টি থেকে তিনটি বাছার উপায় ২০টি, তাই এখানে এলোমেলো না করে সবগুলোই গোনা যায়। পার্থক্যগুলো ০-এর চারপাশে প্রতিসম।
  6. p-value. ২০টির মাত্র ২টিতে পার্থক্য আসলটির মতো চরম (±৩), তাই p = ০.১০. Welch t-test একই ডেটায় ০.০২১ দেয়, কারণ সে normal ধরে নেয়; ছয়টি মানে সেই অনুমান যাচাই করা প্রায় অসম্ভব। permutation সৎভাবে বলছে: ছয়টি অর্ডারে এর চেয়ে বেশি নিশ্চিত হওয়া যায় না।

এবার আসল ৭৫টি অর্ডারে দুটি পদ্ধতি পাশাপাশি। ১০,০০০টি শাফল একসঙ্গে করা হয়েছে rng.permuted দিয়ে, প্রতিটি সারি একটি শাফল, যাতে লুপ ছাড়াই দ্রুত হয় (পর্ব ১৫)। p-এর সূত্রে লব আর হরে +১ একটি প্রচলিত সংশোধন: আসল লেবেলটিও একটি সম্ভাব্য শাফল, তাই p কখনো ঠিক ০ হয় না।

import numpy as np
from scipy import stats

rng = np.random.default_rng(42)
# delivery days for two fictional couriers (gamma: skewed, always > 0)
a = rng.gamma(shape=4, scale=0.55, size=40).round(1)     # "Droot"
b = rng.gamma(shape=4, scale=0.70, size=35).round(1)     # "Sobuj"
print(f"Droot n={a.size} mean {a.mean():.2f} sd {a.std(ddof=1):.2f}")
print(f"Sobuj n={b.size} mean {b.mean():.2f} sd {b.std(ddof=1):.2f}")
obs = b.mean() - a.mean()

w = stats.ttest_ind(b, a, equal_var=False)               # Welch
ci = w.confidence_interval(0.95)
print(f"Welch t={w.statistic:.3f} df={w.df:.1f} p={w.pvalue:.4f}")
print(f"95% CI of difference: {ci.low:.2f} to {ci.high:.2f} days")

# permutation test: shuffle the courier labels 10,000 times
pool = np.concatenate([a, b])
shuf = rng.permuted(np.tile(pool, (10_000, 1)), axis=1)
diffs = shuf[:, a.size:].mean(axis=1) - shuf[:, :a.size].mean(axis=1)
p_perm = (np.sum(np.abs(diffs) >= abs(obs)) + 1) / (diffs.size + 1)
print(f"observed diff {obs:.3f}  permutation p={p_perm:.4f}")

sp = np.sqrt(((a.size - 1) * a.var(ddof=1) + (b.size - 1) * b.var(ddof=1))
             / (a.size + b.size - 2))
print(f"Cohen's d = {obs / sp:.2f}")

ব্রাউজারে একটি run-এর আসল আউটপুট:

Droot n=40 mean 2.12 sd 0.73
Sobuj n=35 mean 2.62 sd 1.32
Welch t=1.970 df=51.7 p=0.0542
95% CI of difference: -0.01 to 1.00 days
observed diff 0.495  permutation p=0.0432
Cohen's d = 0.47

সবুজের গড় প্রায় আধা দিন বেশি (০.৪৯৫), আর SD প্রায় দ্বিগুণ (১.৩২ বনাম ০.৭৩), তাই Welch. df ৫১.৭ দশমিকসহ, কারণ variance আলাদা হলে df একটি সূত্রে (Welch–Satterthwaite) অনুমান করা হয়। Welch দিল p = ০.০৫৪২ আর পার্থক্যের ৯৫% CI −০.০১ থেকে ১.০০ দিন; permutation test দিল p = ০.০৪৩২.

একই ডেটা, দুটি যুক্তিসংগত পদ্ধতি, একটি “০.০৫-এর ওপরে”, অন্যটি “নিচে”: ASA-র তৃতীয় নীতির জীবন্ত উদাহরণ। ০.০৪৩ আর ০.০৫৪ প্রায় একই পরিমাণ প্রমাণ। দুটি ঠিক একই প্রশ্নও করে না: permutation-এর H0 “পুরো distribution একই”, Welch-এর শুধু “গড় সমান”; এখানে ছড়ানোও আলাদা, তাই permutation-এর ছোট p-এর একটি অংশ সেখান থেকেও আসতে পারে। সৎ রিপোর্ট: “সবুজ গড়ে প্রায় ০.৫ দিন ধীর (৯৫% CI প্রায় ০ থেকে ১ দিন), প্রমাণ মাঝারি; আরও এক মাসের ডেটা দেখা দরকার।”

৯ · উল্লেখযোগ্য মানেই জরুরি নয় — effect size, multiple comparisons আর A/B test

Effect size: নমুনা যথেষ্ট বড় হলে প্রায় যেকোনো ক্ষুদ্র পার্থক্যই “উল্লেখযোগ্য” হয়, তাই পার্থক্যটি কত বড়, তাও রিপোর্ট করুন: মূল এককে (“০.৫ দিন”) আর প্রয়োজনে এককহীন মাপে। প্রচলিত মাপ Cohen's d = গড়ের পার্থক্য ÷ মিলিত SD; কুরিয়ারে d = ০.৪৭, পার্থক্যটি একটি অর্ডারের সাধারণ ছড়ানোর প্রায় অর্ধেক। Jacob Cohen ০.২, ০.৫, ০.৮-কে “ছোট, মাঝারি, বড়” বলার মোটা দাগের প্রস্তাব দেন, নিজেই সতর্ক করে যে বিষয়ভেদে অর্থ বদলায়; ব্যবসায় আসল প্রশ্ন “০.৫ দিন ক্রেতার কাছে কতটা জরুরি?”

উল্টো দিকটি দেখুন। লেখকের ল্যাপটপে সত্যিকারের run (Python 3.14.4, SciPy 1.18.0): দুটি ডেলিভারি রুট, প্রতিটিতে এক লাখ অর্ডার, নতুন রুটে আসল পার্থক্য মাত্র ০.০৩ দিন (প্রায় ৪৩ মিনিট) ধরে বানানো ডেটা; আর একটি মাসে ২০টি আলাদা metric-এ test, যেখানে কোনোটিতেই আসল পার্থক্য নেই।

~/bazarghar-ai$ python pitfalls.py
diff 0.044 days  p = 9.9e-07  Cohen's d = 0.022
at least one p < 0.05 in 20 null tests: 0.62  (theory 1 - 0.95**20 = 0.64)
with Bonferroni 0.05/20 = 0.0025: 0.036

প্রথম লাইন: p ≈ ০.০০০০০১, অত্যন্ত “উল্লেখযোগ্য”, অথচ d = ০.০২২, পার্থক্য মাত্র এক ঘণ্টার মতো। পরিসংখ্যানিকভাবে নিশ্চিত, ব্যবহারিকভাবে প্রায় অর্থহীন (statistical বনাম practical significance). নমুনায় পার্থক্য ০.০৪৪ এসেছে, বানানো ০.০৩ নয়: এক লাখেও কাকতাল থাকে।

দ্বিতীয় লাইন multiple comparisons-এর সমস্যা: প্রতিটি test-এ কাকতালে p < ০.০৫-এর সম্ভাবনা ৫%, কিন্তু ২০টি স্বাধীন test-এ অন্তত একটিতে ১ − ০.৯৫২০ ≈ ০.৬৪; simulation-এ ৬২% মাসে অন্তত একটি মিথ্যা “আবিষ্কার”. সরল প্রতিকার Bonferroni: সীমাকে test-এর সংখ্যা দিয়ে ভাগ (০.০৫/২০ = ০.০০২৫), তাতে নেমেছে ৩.৬%-এ; দাম হলো আসল প্রভাব ধরার ক্ষমতাও কমে, তাই False Discovery Rate (Benjamini–Hochberg, ১৯৯৫)-এর মতো কম কঠোর পদ্ধতিও প্রচলিত।

এরই অসৎ রূপ p-hacking: p < ০.০৫ না আসা পর্যন্ত বিশ্লেষণ বদলানো: আরেকটি দল বাদ, আরেকটি metric, “আরও কয়েক দিন ডেটা নিই”. প্রতিটি সিদ্ধান্ত একা নির্দোষ মনে হয়, কিন্তু মিলে গোপনে অনেক test হয়। Joseph Simmons, Leif Nelson আর Uri Simonsohn ২০১১ সালে Psychological Science-এ দেখান, এমন কয়েকটি স্বাধীনতা মিলিয়ে মিথ্যা “উল্লেখযোগ্য” ফলের সম্ভাবনা ৫% থেকে অনেক গুণ বাড়ানো যায়। প্রতিকার: বিশ্লেষণের পরিকল্পনা ডেটা দেখার আগে লিখে রাখা।

A/B test — সব মিলিয়ে একটি প্রয়োগ

বাজারঘর নতুন checkout পাতা চালু করতে চায়। A/B test-এ ক্রেতাদের এলোমেলোভাবে দুই দলে ভাগ করা হয়: A পুরোনো পাতা, B নতুন; এলোমেলো ভাগ confounder-গুলো গড়ে সমান করে (অংশ ৫)। এই পর্বের সব ধারণা এখানে লাগে: আগে থেকে প্রধান metric আর নমুনার আকার ঠিক করা (SE আর √n থেকে); পার্থক্য আর তার CI রিপোর্ট; p-কে সংকেত হিসেবে দেখা, রায় হিসেবে নয়; প্রতিদিন উঁকি দিয়ে “উল্লেখযোগ্য হলেই থামা” এড়ানো; আর অনেক metric-এ সংশোধন। পরের machine learning কোর্সে মডেলের তুলনা আর online experiment আরও গভীরে আসবে।

আরও গভীরে: n − 1-এর তিন লাইনের প্রমাণ। ∑(xi − x̄)2 = ∑(xi − μ)2 − n(x̄ − μ)2 (বীজগণিত দিয়ে খোলা যায়)। প্রত্যাশিত মান নিলে প্রথম অংশ nσ2, আর দ্বিতীয় অংশ n × Var(x̄) = n × σ2/n = σ2. তাই প্রত্যাশিত যোগফল (n − 1)σ2, আর n − 1 দিয়ে ভাগ করলেই গড়ে σ2. লক্ষ করুন, এটি variance-কে পক্ষপাতহীন করে, SD-কে নয়: √ বক্র ফাংশন বলে s গড়ে σ-এর সামান্য কম থাকে। আরও পড়তে পারেন ASA-র ২০১৬ বিবৃতি আর ২০১৯ সালের The American Statistician-এর বিশেষ সংখ্যা “Statistical Inference in the 21st Century: A World Beyond p < 0.05”.

পরীক্ষা ও ইন্টারভিউতে প্রায়ই যা জিজ্ঞেস করা হয়:

  • Outlier থাকলে গড় না median? কেন্দ্রের “সাধারণ” মান চাইলে median (robust); মোট হিসাবে গড়, আর দুটিই রিপোর্ট করা ভালো।
  • নমুনার variance-এ n − 1 কেন? x̄ থেকে মাপা বিচ্যুতি গড়ে ছোট হয়; n − 1 দিয়ে ভাগ করলে অনুমান পক্ষপাতহীন হয় (Bessel's correction).
  • SD আর SE-র পার্থক্য? SD একটি পর্যবেক্ষণের ছড়ানো; SE = SD/√n গড়ের অনিশ্চয়তা, n বাড়লে কমে।
  • ৯৫% CI-এর সঠিক অর্থ? পদ্ধতিটি বারবার প্রয়োগ করলে প্রায় ৯৫% interval আসল মান ধরবে; একটি নির্দিষ্ট interval-এ μ থাকার সম্ভাবনা নয়।
  • p = ০.০৩ মানে কী? H0 আর মডেলের অনুমান সত্য হলে এমন বা আরও চরম ফল আসার সম্ভাবনা ৩%; H0 মিথ্যা হওয়ার সম্ভাবনা ৯৭% নয়।

১০ · AI-এর যুগে — AI সহকারীর পরিসংখ্যান যাচাই

“দুই কুরিয়ারের ডেটা তুলনা করে বলো কোনটি ভালো” লিখলে AI সহকারী কয়েক সেকেন্ডে কোড, p-value আর আত্মবিশ্বাসী উপসংহার দেবে। পরিসংখ্যানের ভুল error দেয় না; সংখ্যা নিখুঁত দেখায়, শুধু অর্থ ভুল। প্রায়ই যা দেখা যায়:

  • default-এর অমিল লুকায়: np.std (ddof=0) দিয়ে নমুনার SD, পাশে pandas-এর ddof=1; সংখ্যা মেলে না।
  • p-value ভুল পড়ে: “p = ০.০৪, তাই ৯৬% নিশ্চিত”, “p > ০.০৫, তাই পার্থক্য নেই”, effect size আর CI ছাড়া শুধু p.
  • অনুমান যাচাই করে না: variance আলাদা হলেও SciPy-র default equal_var=True, বা একই ক্রেতার অনেক অর্ডারকে স্বাধীন ধরা।
  • পুরোনো বা বানানো API: যেমন t.interval(alpha=...); এখন প্রথম parameter confidence.
  • অনেক test, বাছাই করা রিপোর্ট: বিশটি তুলনা করে শুধু “উল্লেখযোগ্য” দুটি দেখানো, correlation থেকে কারণ ঘোষণা, আর আসল ক্রেতার ডেটা চাওয়া।

প্রম্পটে প্রশ্ন, ডেটার গঠন, version আর রিপোর্টের শর্ত নিজেই দিন। আসল ক্রেতার ডেটা নয়, বানানো নমুনা দিন।

আমি Python 3.14, NumPy 2.4 আর SciPy 1.18 ব্যবহার করছি। দুটি কুরিয়ারের ডেলিভারি-দিনের দুটি array আছে (প্রতিটি মান একটি অর্ডার; একই ক্রেতার একাধিক অর্ডার থাকতে পারে)। কাজ: দুই কুরিয়ারের গড় ডেলিভারি-সময় তুলনা করো। শর্ত: ১. প্রতিটি দলের n, গড়, median আর SD (ddof=1) আলাদা করে print করো। ২. Welch t-test (equal_var=False) আর ১০,০০০ শাফলের permutation test দুটিই চালাও, seed দিয়ে। ৩. গড়ের পার্থক্য, তার ৯৫% CI আর Cohen's d রিপোর্ট করো; শুধু p দিয়ে সিদ্ধান্ত দেবে না। ৪. p-value-এর অর্থ এক বাক্যে লেখো, ASA ২০১৬-এর বিবৃতি মেনে। ৫. কোন অনুমান (স্বাধীনতা, ছড়ানো, বাঁক) ভাঙতে পারে, তা বলো; কোনো parameter নিয়ে নিশ্চিত না হলে বলো। ৬. কারণ-সম্পর্কের কোনো দাবি করবে না।

AI-এর পরিসংখ্যান হাতে পেলে — যাচাইয়ের চেকলিস্ট

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

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

প্র ০১একটি মদ কারখানা কেন পরিসংখ্যানের সবচেয়ে ব্যবহৃত একটি distribution-এর জন্মস্থান? ছোট নমুনার সমস্যাটা কী ছিল?

বিশ শতকের শুরুতে ডাবলিনের Guinness কারখানা বৈজ্ঞানিক পদ্ধতিতে বার্লি আর হপের মান উন্নত করতে চাইছিল, আর রসায়ন ও গণিত পড়া William Sealy Gosset সেখানে কাজ নেন। তাঁর সমস্যা ছিল বাস্তব: প্রতিটি পরীক্ষায় হাতে মাত্র কয়েকটি নমুনা, কারণ প্রতিটি নমুনা মানে এক ব্যাচ বা এক খণ্ড জমির ফসল। তখনকার পরিসংখ্যান, যা Karl Pearson-এর গবেষণাগারে বড় জৈবিক ডেটা নিয়ে গড়ে উঠছিল, ধরে নিত নমুনা বড়, তাই s প্রায় আসল σ-এর সমান। চার-পাঁচটি নমুনায় সেই অনুমান ভাঙে: s নিজেই অনেক নড়ে, আর ১.৯৬ দিয়ে বানানো interval প্রায়ই খুব সরু হয়।

Gosset কার্ডে লেখা মাপ এলোমেলো করে ছোট দল বানিয়ে হাতে simulation করেছিলেন বলে জানা যায়, আর দেখান যে (x̄ − μ)/(s/√n) একটি মোটা লেজের distribution মানে, যার আকৃতি নমুনার আকারের ওপর নির্ভর করে। কারখানা কর্মীদের নিজের নামে প্রকাশ করতে দিত না বলে সাধারণত বলা হয়, তাই ১৯০৮ সালের Biometrika প্রবন্ধে নাম ছিল “Student”. পরে Ronald Fisher এর গাণিতিক ভিত্তি পরিষ্কার করেন আর “t” নামটি জনপ্রিয় করেন।

আজকের শিক্ষা দুটি। AI-এর বিশাল ডেটাতেও ছোট নমুনার প্রশ্ন ফিরে আসে: নতুন জেলায় ২০টি অর্ডার, বিরল রোগের ৩০টি ছবি, test set-এর একটি ছোট উপদল। আর সরল simulation দিয়ে তত্ত্ব যাচাইয়ের যে অভ্যাস Gosset কার্ডে করেছিলেন, আপনি এই পর্বে NumPy-তে কয়েক লাইনে করেছেন।

মূল উপলব্ধি: σ অজানা আর নমুনা ছোট হলে অনিশ্চয়তা বেশি, আর t-distribution সেই বাড়তি অনিশ্চয়তার সৎ হিসাব; df বড় হলে এটি normal-এ মিশে যায়।

প্র ০২বিজ্ঞানে “replication crisis” কী, আর p-value-এর সঙ্গে এর সম্পর্ক কোথায়? p-value কি তুলে দেওয়া উচিত?

২০০৫ সালে John Ioannidis PLoS Medicine-এ “Why Most Published Research Findings Are False” প্রবন্ধে যুক্তি দেন, ছোট নমুনা, ছোট প্রভাব, অনেক পরীক্ষিত সম্পর্ক, বিশ্লেষণের নমনীয়তা আর “উল্লেখযোগ্য” ফল প্রকাশের চাপ মিলে প্রকাশিত অনেক আবিষ্কারই মিথ্যা হতে পারে। শিরোনামটি বিতর্কিত, হিসাব কিছু অনুমানের ওপর দাঁড়ানো, কিন্তু প্রশ্নটি গুরুতর। ২০১৫ সালে Open Science Collaboration Science-এ মনোবিজ্ঞানের প্রায় একশোটি প্রকাশিত পরীক্ষা আবার চালানোর ফল প্রকাশ করে: মূলগুলোর প্রায় সবই “উল্লেখযোগ্য” ছিল, অথচ পুনরাবৃত্তিতে মাত্র এক-তৃতীয়াংশের কিছু বেশি একই সিদ্ধান্তে পৌঁছায়, আর প্রভাবের আকারও গড়ে অনেক ছোট হয়।

দায় p-value-এর নয়, তার ব্যবহারের: ০.০৫-কে সত্য-মিথ্যার দেয়াল ধরা, শুধু উল্লেখযোগ্য ফল প্রকাশ (publication bias) আর p-hacking. তাই ASA ২০১৬ সালে বিবৃতি দেয়, আর ২০১৯ সালে The American Statistician-এর একটি বিশেষ সংখ্যা “statistically significant” কথাটিই বাদ দেওয়ার পরামর্শ দেয়; একই বছর Nature-এ Amrhein, Greenland আর McShane-এর মন্তব্য-প্রবন্ধে আটশোর বেশি গবেষক একই আহ্বানে সই করেন। সবাই একমত নন: কেউ সীমা ০.০০৫ করার প্রস্তাব দেন (Benjamin ও সহলেখক, ২০১৮), কেউ Bayesian পদ্ধতি পছন্দ করেন, কেউ বলেন ঠিকঠাক বুঝে ব্যবহার করলে p কাজের যন্ত্র। প্রায় সবাই একমত, আগে পরিকল্পনা লেখা (preregistration), পূর্ণ রিপোর্ট আর পুনরাবৃত্তি জরুরি। AI গবেষণাতেও একই চাপ: অনেক seed চেষ্টা করে সেরাটি দেখানো, একই test set-এ বারবার মাপা।

মূল উপলব্ধি: p-value একটি সীমিত কিন্তু কাজের সংকেত; বিপদ আসে দ্বিভাজন, বাছাই করা রিপোর্ট আর গোপন অনেক test থেকে।

প্র ০৩Machine learning মডেল কি correlation শেখে, নাকি কারণ? এতে বাস্তবে কী সমস্যা হতে পারে?

সাধারণ supervised মডেল (পর্ব ৫৫ থেকে) প্রশিক্ষণের ডেটায় যে নকশা ফলের সঙ্গে সবচেয়ে ভালো মেলে, তা-ই শেখে; সেটি কারণ না confounder-এর ছায়া, মডেল আলাদা করতে পারে না। পরিবেশ প্রশিক্ষণের মতো থাকলে এতে সমস্যা নেই: মেঘ বৃষ্টির “কারণ” কি না না জেনেও ভালো পূর্বাভাস দেওয়া যায়। সমস্যা হয় পরিবেশ বদলালে, বা মডেলের ফল দেখে কোনো হস্তক্ষেপ করলে।

গবেষণায় এর পরিচিত নাম shortcut learning: আসল বৈশিষ্ট্যের বদলে একটি সহজ সঙ্গী সংকেত ধরা। প্রকাশিত কয়েকটি গবেষণায় দেখা গেছে, বুকের X-ray থেকে রোগ চেনার কিছু মডেল আংশিকভাবে হাসপাতাল-নির্দিষ্ট চিহ্ন ব্যবহার করছিল, আর অন্য হাসপাতালে নির্ভুলতা কমে; খুঁটিনাটি গবেষণাভেদে আলাদা। বাজারঘরে: মডেল শিখল “কুপন পাওয়া ক্রেতা বেশি কেনেন”, তাই সবাইকে কুপন দেওয়া হলো; কিন্তু আগে কুপন পেতেন শুধু নিয়মিত ক্রেতারা। সম্পর্কটি ক্রেতার ধরনের, কুপনের নয়, তাই নীতি বদলালে প্রত্যাশিত ফল আসে না আর খরচ শুধু বাড়ে।

কারণ নিয়ে কাজের আলাদা শাখা causal inference: Judea Pearl-এর causal graph, Donald Rubin-এর potential outcomes কাঠামো, আর randomised experiment. কোন কাঠামো ভালো, তা নিয়ে পরিসংখ্যানবিদ আর কম্পিউটার বিজ্ঞানীদের মধ্যে বিতর্ক আছে, কিন্তু মূল কথায় মিল: হস্তক্ষেপের প্রশ্নে শুধু পর্যবেক্ষণের correlation যথেষ্ট নয়; হয় এলোমেলো পরীক্ষা, নয় confounder সম্পর্কে স্পষ্ট, লিখিত অনুমান লাগে।

মূল উপলব্ধি: মডেল correlation দিয়ে ভালো অনুমান করতে পারে, কিন্তু “কী বদলালে কী হবে” বলতে এলোমেলো পরীক্ষা বা স্পষ্ট causal অনুমান লাগে।

প্র ০৪CLT এত শক্তিশালী হলে ডেটা বিজ্ঞানে “normal ধরে নেওয়া”-কে কেন সন্দেহের চোখে দেখা হয়?

CLT একটি কথা বলে, আর মানুষ প্রায়ই তার চেয়ে বেশি শোনে। এটি বলে নমুনার গড় বড় n-এ প্রায় normal; বলে না যে ডেটা নিজে normal. বাজারঘরের ডেলিভারি-সময় চিরকাল বাঁকাই থাকবে, তাই “৯৫% অর্ডার গড় ± ২ SD-র মধ্যে পৌঁছাবে” ভুল হতে পারে, যদিও গড়ের CI ঠিক। আর “বড় n” কত বড়, তা বাঁকের ওপর নির্ভর করে: এই পর্বের simulation-এ exponential ডেটায় n = ৩০-এও “৯৫%” interval আসলে প্রায় ৯২%.

শর্তগুলোও ভাঙে। একই ক্রেতার অর্ডার, একই দিনের অর্ডার বা time series (পর্ব ২৬) স্বাধীন নয়; তখন আসল SE σ/√n-এর চেয়ে বড়। আর সসীম variance-এর শর্ত ভাঙার চরম উদাহরণ Cauchy. ১৯৬০-এর দশকে Benoit Mandelbrot তুলার দামের ওঠানামায় normal-এর চেয়ে অনেক ভারী লেজ দেখান; বাজারের বড় ধসগুলো normal মডেলে প্রায় অসম্ভব দেখায় বলে অনেকে যুক্তি দেন, যদিও কোন মডেল ঠিক, তা নিয়ে বিতর্ক চলমান।

ব্যবহারিক অভ্যাস: আগে ছবি দেখুন (পর্ব ২৯), median আর গড়ের পার্থক্য দেখুন, ভারী লেজ সন্দেহ হলে robust মাপ বা log রূপান্তর বিবেচনা করুন, আর নিজের ডেটার মতো simulation চালিয়ে পদ্ধতিটি কতটা টেকে দেখুন। Machine learning-এ গড় loss-কেও কয়েকটি বিশাল ভুল নিয়ন্ত্রণ করতে পারে, তাই ভুলের distribution দেখা ভালো।

মূল উপলব্ধি: CLT গড়ের আচরণের প্রতিশ্রুতি, ডেটার নয়, আর তাও স্বাধীনতা ও সসীম variance-এর শর্তে; নিজের ডেটায় তা কতটা খাটে, simulation দিয়ে যাচাই করা যায়।

প্র ০৫Frequentist confidence interval আর Bayesian credible interval — কোনটি “ঠিক”? সাধারণ মানুষ কোনটি বোঝেন?

পার্থক্য সম্ভাবনার অর্থে। Frequentist পরিসংখ্যানে (Neyman, Egon Pearson, Fisher-এর ঐতিহ্য) সম্ভাবনা মানে বারবার পুনরাবৃত্তিতে দীর্ঘমেয়াদি হার; আসল গড় μ একটি নির্দিষ্ট অজানা সংখ্যা, তাই “μ এই পরিসরে থাকার সম্ভাবনা” কথাটির অর্থই নেই, আর ৯৫% CI-এর প্রতিশ্রুতি পদ্ধতির। Bayesian পরিসংখ্যানে সম্ভাবনা মানে বিশ্বাসের মাত্রা; μ সম্পর্কে আগের বিশ্বাস (prior) ডেটা দিয়ে হালনাগাদ করে পাওয়া যায় posterior, আর ৯৫% credible interval সত্যিই বলে “আমার মডেল আর prior অনুযায়ী μ ৯৫% সম্ভাবনায় এখানে”.

মজার ব্যাপার, অনেক গবেষকও CI-কে Bayesian অর্থে পড়েন। ২০১৪ সালে Rink Hoekstra ও সহকর্মীরা Psychonomic Bulletin & Review-এ ছাত্র আর গবেষকদের CI-এর কয়েকটি ব্যাখ্যা দেখিয়ে ঠিক-ভুল বলতে বলেন; বেশিরভাগ উত্তরদাতা অন্তত একটি ভুল ব্যাখ্যাকে “ঠিক” বলেন, অভিজ্ঞরাও। বড় নমুনা আর দুর্বল prior-এ দুটি interval সংখ্যায় প্রায় সমান হয়; ছোট নমুনা বা শক্ত আগের জ্ঞানে পার্থক্য বড় হতে পারে।

এক শতাব্দীর বিতর্ক থাকলেও আজ বেশিরভাগ ব্যবহারিক পরিসংখ্যানবিদ দুটিই ব্যবহার করেন। Frequentist পথে prior বাছতে হয় না আর ভুলের হার নিয়ন্ত্রিত; Bayesian পথে ফল সরাসরি প্রশ্নের উত্তর দেয় আর আগের জ্ঞান যোগ করা যায়, দাম prior নিয়ে বিতর্ক আর বেশি হিসাব। AI-তে দুটিই আছে: Naive Bayes আর Bayesian network (পর্ব ৫১, ৫২) এক ধারায়, মডেল-তুলনার CI আর A/B test প্রায়ই অন্য ধারায়।

মূল উপলব্ধি: CI পদ্ধতির দীর্ঘমেয়াদি নির্ভুলতার প্রতিশ্রুতি, credible interval prior-সহ বিশ্বাসের বিবৃতি; সংখ্যা প্রায়ই কাছাকাছি, কিন্তু অর্থ গুলিয়ে ফেললে রিপোর্ট ভুল হয়।

অনুশীলন

প্রথমটি হিসাবের, দ্বিতীয়টি আউটপুট অনুমানের, তৃতীয়টি নকশা ও সমালোচনার, শেষটি কোড লেখার।

  1. হিসাব: ছয়টি অর্ডারের ডেলিভারি-দিন: ৩, ৫, ৪, ৬, ২, ১০. হাতে বের করুন: (ক) গড় আর median; (খ) নমুনার variance আর SD (n − 1); (গ) ১০ দিনের অর্ডারের z-score; z > ৩ নিয়মে এটি outlier কি? (ঘ) NumPy-র default percentile-এ Q1 = ৩.২৫, Q3 = ৫.৭৫ ধরে IQR-এর ওপরের বেড়া; (ঙ) গড়ের ৯৫% t-interval (df = ৫-এ t = ২.৫৭১).

    (ক) যোগফল ৩০, গড় = ৩০ / ৬ = ৫; সাজালে ২, ৩, ৪, ৫, ৬, ১০, median = (৪ + ৫) / ২ = ৪.৫. (খ) বিচ্যুতি −২, ০, −১, ১, −৩, ৫; বর্গ ৪, ০, ১, ১, ৯, ২৫, যোগফল ৪০; s2 = ৪০ / ৫ = ৮, s = √৮ ≈ ২.৮২৮. (গ) z = (১০ − ৫) / ২.৮২৮ ≈ ১.৭৭; z > ৩ নিয়মে outlier নয়। ছয়টি মানে |z| কখনো (৬ − ১)/√৬ ≈ ২.০৪-এর বেশি হতেই পারে না। (ঘ) IQR = ২.৫, ওপরের বেড়া ৫.৭৫ + ৩.৭৫ = ৯.৫; ১০ বেড়ার বাইরে, তাই এই নিয়মে চিহ্নিত। (ঙ) SE = ২.৮২৮ / √৬ ≈ ১.১৫৫; ভুলের সীমা ২.৫৭১ × ১.১৫৫ ≈ ২.৯৭; CI ≈ ২.০৩ থেকে ৭.৯৭ দিন. লেখকের NumPy/SciPy-তে মেলানো: 2.032 থেকে 7.968. ছয়টি অর্ডারে interval খুব চওড়া, আর ডেটা বাঁকা বলে এর ৯৫% প্রতিশ্রুতিও দুর্বল।

  2. আউটপুট অনুমান করুন: চালানোর আগে দুটি লাইন লিখুন।
    import numpy as np, pandas as pd
    from scipy import stats
    v = np.array([-2, -1, 0, 1, 2])
    print(round(np.std(v), 3), round(pd.Series(v).std(), 3))
    print(np.corrcoef(v, v**2)[0, 1].round(3),
          stats.spearmanr(v, v**2).statistic.round(3))

    লেখকের যন্ত্রে সত্যিকারের run (NumPy 2.4.6, pandas 3.0.2, SciPy 1.18.0):

    1.414 1.581
    0.0 0.0

    বর্গের যোগফল ৪ + ১ + ০ + ১ + ৪ = ১০. NumPy ৫ দিয়ে ভাগ করে √২ ≈ ১.৪১৪, pandas ৪ দিয়ে √২.৫ ≈ ১.৫৮১. দ্বিতীয় লাইনে y = x2 পুরোপুরি x দিয়ে নির্ধারিত, তবু Pearson আর Spearman দুটিই ০: U-আকারের সম্পর্ক সরলরৈখিকও নয়, একমুখীও নয়। “correlation ০ মানে সম্পর্ক নেই” কথাটি ভুল, এটিই তার প্রমাণ।

  3. নকশা ও সমালোচনা: একটি AI সহকারী নতুন checkout পাতার A/B test নিয়ে এই রিপোর্ট লিখেছে: “আমরা ২০টি metric দেখেছি। ৯ দিন পর ‘গড় অর্ডারের দাম’-এ p = ০.০৪৯ আসায় test থামিয়েছি। তাই ৯৫.১% নিশ্চিত যে নতুন পাতা ভালো। বাকি ১৯টি metric-এ p > ০.০৫, মানে সেগুলোতে নতুন পাতার কোনো প্রভাব নেই। SD হিসাব করেছি np.std দিয়ে।” অন্তত পাঁচটি সমস্যা চিহ্নিত করুন আর ভালো পরিকল্পনার রূপরেখা দিন।
    • Multiple comparisons: ২০টি metric-এ কোনো আসল প্রভাব না থাকলেও অন্তত একটিতে p < ০.০৫ আসার সম্ভাবনা প্রায় ৬৪%.
    • উঁকি দিয়ে থামা: প্রতিদিন দেখে “উল্লেখযোগ্য হলেই থামা” গোপনে অনেক test; নমুনার আকার আগে ঠিক করা উচিত ছিল।
    • p-এর ভুল ব্যাখ্যা: p = ০.০৪৯ মানে “৯৫.১% নিশ্চিত” নয় (ASA-র নীতি ২)।
    • প্রমাণের অভাব ≠ প্রভাব নেই: বাকি ১৯টির p > ০.০৫ শুধু বলে এই ডেটায় যথেষ্ট প্রমাণ নেই।
    • Effect size আর CI নেই, ddof অসংগত: দাম কত টাকা বেড়েছে আর তার অনিশ্চয়তা কত, অজানা; np.std-এর default ddof=0.

    ভালো পরিকল্পনা: একটি প্রধান metric আর নমুনার আকার আগে লেখা, মেয়াদ শেষে একবার বিশ্লেষণ, পার্থক্য, ৯৫% CI আর effect size রিপোর্ট, বাকি metric-এ সংশোধন বা “অনুসন্ধানমূলক” লেবেল।

  4. কোড লিখুন: অংশ ৮-এর মতো একই seed-এ দুই কুরিয়ারের ডেটা বানান (default_rng(42), gamma shape ৪, scale ০.৫৫ আর ০.৭০, আকার ৪০ আর ৩৫, এক দশমিকে round). এবার গড় নয়, median-এর পার্থক্যের জন্য ১০,০০০ শাফলের permutation test লিখুন (শাফলের জন্য আলাদা default_rng(7)). দুই median, পার্থক্য আর p ছাপুন। ফল গড়ের test-এর সঙ্গে মেলে কি? কেন?
    import numpy as np
    rng = np.random.default_rng(42)
    a = rng.gamma(shape=4, scale=0.55, size=40).round(1)
    b = rng.gamma(shape=4, scale=0.70, size=35).round(1)
    obs = np.median(b) - np.median(a)
    pool = np.concatenate([a, b])
    shuf = np.random.default_rng(7).permuted(np.tile(pool, (10_000, 1)), axis=1)
    d = np.median(shuf[:, a.size:], axis=1) - np.median(shuf[:, :a.size], axis=1)
    p = (np.sum(np.abs(d) >= abs(obs)) + 1) / (d.size + 1)
    print(f"median Droot {np.median(a)}  Sobuj {np.median(b)}  diff {obs:.2f}  p={p:.4f}")

    লেখকের যন্ত্রে সত্যিকারের run (NumPy 2.4.6):

    median Droot 2.2  Sobuj 2.1  diff -0.10  p=0.8398

    গড়ে সবুজ প্রায় আধা দিন ধীর, অথচ median-এ সবুজই সামান্য দ্রুত (২.১ বনাম ২.২), আর p = ০.৮৪: median-এর পার্থক্যের কোনো প্রমাণ নেই। মানে সবুজের সাধারণ অর্ডার দ্রুতপথের মতোই, কিন্তু কিছু অর্ডার অনেক দেরিতে যায় (SD ১.৩২ বনাম ০.৭৩), আর সেই লেজ গড় টেনে তোলে। আসল প্রশ্ন তাই “সবুজের দেরির অর্ডারগুলো কোথায়, কেন”.

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

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

ক্রমদুই দলের গড়ের পার্থক্যের জন্য একটি permutation test-এর ধাপগুলো সঠিক ক্রমে সাজান (▲▼ চেপে সরান)

  1. 📝 ডেটা দেখার আগে প্রশ্ন, metric আর test লিখে রাখা
  2. ➖ আসল দুই দলের গড়ের পার্থক্য হিসাব করা
  3. 🧺 দুই দলের সব মান এক ঝুড়িতে মেলানো
  4. 🔀 লেবেল এলোমেলো করে আবার দুই দল বানিয়ে পার্থক্য লেখা, হাজারবার
  5. 📊 কত ভাগ শাফলে পার্থক্য আসলটির মতো বা বেশি চরম, তা গুনে p বের করা
  6. 📏 p-এর সঙ্গে পার্থক্যের আকার আর CI রিপোর্ট করা

ডেলিভারি-দিন [2, 4, 4, 5, 10]-এ np.std(x) আর pd.Series(x).std() কত দেয়?

  • দুটিই 3.0
  • NumPy 3.0, pandas 2.683
  • NumPy 2.683, pandas 3.0
  • NumPy 7.2, pandas 9.0

দশটি অর্ডারের গড় ৪৯৮ টাকা আর median ৪৯৫ টাকা। ২৫,০০০ টাকার একটি অর্ডার যোগ হলে কী ঘটে?

  • দুটিই প্রায় সমান হারে বাড়ে
  • গড় প্রায় ২৭২৫ টাকা হয়, median মাত্র ৫০০ হয়
  • গড় প্রায় একই থাকে, median অনেক বাড়ে
  • median-কে আর সংজ্ঞায়িত করা যায় না

১০০টি অর্ডারের নমুনায় ডেলিভারি-দিনের SD ২. গড়ের standard error কত, আর SE অর্ধেক করতে কতটি অর্ডার লাগবে?

  • ০.০২; ২০০টি
  • ০.২; ২০০টি
  • ২; ৪০০টি
  • ০.২; ৪০০টি

একটি নমুনা থেকে গড় ডেলিভারি-সময়ের ৯৫% confidence interval এল ১.৬৬ থেকে ৩.৩৪ দিন। কোন ব্যাখ্যাটি সঠিক?

  • এই পদ্ধতি বারবার নতুন নমুনায় প্রয়োগ করলে প্রায় ৯৫% interval আসল গড়কে ধরবে
  • আসল গড় ৯৫% সম্ভাবনায় ১.৬৬ থেকে ৩.৩৪-এর মধ্যে
  • ৯৫% অর্ডার ১.৬৬ থেকে ৩.৩৪ দিনে পৌঁছায়
  • নমুনার গড় ৯৫% সম্ভাবনায় এই পরিসরে

দুই কুরিয়ারের তুলনায় Welch t-test দিল p = ০.০৩. কোন বাক্যটি সঠিক?

  • ৯৭% সম্ভাবনায় দুই কুরিয়ারের গড় আলাদা
  • পার্থক্যটি বড় আর ব্যবসার জন্য জরুরি
  • গড় সমান হলে এত বড় বা আরও বড় পার্থক্য কাকতালে আসার সম্ভাবনা প্রায় ৩%
  • ফলটি কাকতালে আসার সম্ভাবনা ৩%

x = ১ থেকে ২০, y = ৩০ × ১.২৫x (ছাড় বাড়লে অর্ডার গুণিতক হারে বাড়ে)। Pearson আর Spearman correlation কেমন হবে?

  • দুটিই ঠিক ১
  • Spearman ঠিক ১, Pearson ১-এর কম
  • Pearson ঠিক ১, Spearman ১-এর কম
  • দুটিই প্রায় ০

কোনো আসল প্রভাব নেই এমন ২০টি স্বাধীন metric-এ প্রতিটিতে ০.০৫ সীমায় test করলে, অন্তত একটিতে “উল্লেখযোগ্য” ফল আসার সম্ভাবনা মোটামুটি কত?

  • ৫%
  • ১০০%
  • প্রায় ০%
  • প্রায় ৬৪%

শব্দকোষ

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

মনে রাখুন

  1. কেন্দ্র: গড় মোটের জন্য, median “সাধারণ” মানের জন্য (robust), mode category-র জন্য; বাঁকা ডেটায় গড় আর median দুটিই দেখান।
  2. ছড়ানো: variance = বিচ্যুতির বর্গের গড়, SD তার বর্গমূল; নমুনায় n − 1 (ddof=1). NumPy-র default 0, pandas-এর 1; robust বিকল্প IQR আর MAD.
  3. Outlier আর correlation: ছোট নমুনায় z > ৩ প্রায় কিছুই ধরে না, IQR-এর বেড়া robust; Pearson সরলরেখা মাপে আর outlier-এ ভাঙে, Spearman একমুখী সম্পর্ক মাপে; correlation কারণ নয়।
  4. CLT আর SE: নমুনার গড়ের SD = σ/√n; বাঁকা ডেটাতেও বড় n-এ গড় প্রায় normal, কিন্তু স্বাধীনতা আর সসীম variance লাগে (Cauchy-তে খাটে না)।
  5. CI আর p-value: x̄ ± t × s/√n; ৯৫% পদ্ধতির হার। p hypothesis সত্য হওয়ার সম্ভাবনা নয়; সঙ্গে effect size আর CI, আর অনেক test-এ সংশোধন।

পরের পর্বে (পর্ব ৩৮): Entropy আর information: অনিশ্চয়তাকে বিটে মাপা, cross-entropy আর KL divergence, আর কেন classification মডেলের loss প্রায়ই log loss.

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

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