পাঠ ৪৮ · ৫৭-এর মধ্যে · মডিউল ১১
Home / Courses / Digital Signal Processing / র‍্যান্ডম সিগন্যাল

র‍্যান্ডম সিগন্যাল — স্টেশনারিটি ও এরগোডিসিটি

Random signals — stationarity & ergodicity
১১ মিনিট পড়া মধ্যম-উচ্চ · Intermediate-Advanced Python কোডসহ সম্পূর্ণ বাংলায়

এই পাঠে যা শিখবেন

  • র‍্যান্ডম (স্টোকাস্টিক) সিগন্যাল কী এবং কেন ডিটারমিনিস্টিক সিগন্যালের গাণিতিক টুল যথেষ্ট নয়
  • ওয়াইড-সেন্স স্টেশনারিটি (WSS) — গড় ও অটোকোরিলেশন সময়ের সাথে অপরিবর্তিত থাকার শর্ত
  • এরগোডিসিটি — কেন একটি একক রিয়েলাইজেশন থেকে গণনা করা সময়-গড় নির্ভরযোগ্য হতে পারে
  • একটি সত্যিকারের ডেমো — উইন্ডোভিত্তিক পরিসংখ্যান দিয়ে স্টেশনারি বনাম নন-স্টেশনারি সিকোয়েন্স আলাদা করা

১ · র‍্যান্ডম সিগন্যাল কী

এই কোর্সের L01 থেকে L47 পর্যন্ত আমরা যেসব সিগন্যাল ব্যবহার করেছি — সাইন-তরঙ্গ, ইমপালস রেসপন্স, ফিল্টার আউটপুট — সবই ডিটারমিনিস্টিক: একটি নির্দিষ্ট সূত্র (যেমন math.sin(2*pi*f*n/fs)) দিয়ে সম্পূর্ণ নির্ধারিত, একই ইনপুট দিলে বারবার ঠিক একই আউটপুট পাওয়া যায়। কিন্তু বাস্তব জগতের অনেক গুরুত্বপূর্ণ সিগন্যাল — থার্মাল নয়েজ, মাইক্রোফোনের পটভূমি হিস, একটি চ্যানেলের হস্তক্ষেপ — এভাবে বর্ণনা করা যায় না। এগুলোকে বলা হয় র‍্যান্ডম সিগন্যালRandom / stochastic signal — একটি সিগন্যাল যার ভবিষ্যৎ মান নিশ্চিতভাবে জানা যায় না, বরং সম্ভাব্যতার বণ্টন (probability distribution) দিয়ে বর্ণনা করা হয়। বা স্টোকাস্টিক প্রসেস — এদের প্রতিটি স্যাম্পলের মান একটি সম্ভাব্যতা বণ্টন থেকে আসে, নির্দিষ্ট সূত্র থেকে নয়। M10-এ (L44, PSD এস্টিমেশন) আমরা ইতিমধ্যে random.gauss দিয়ে নয়েজ যোগ করে দেখেছি — এই মডিউলে (M11) আমরা সেই র‍্যান্ডম সিগন্যালগুলোকে আরও পদ্ধতিগতভাবে বিশ্লেষণ করব।

২ · স্টেশনারিটি (Stationarity)

একটি র‍্যান্ডম প্রসেসকে ওয়াইড-সেন্স স্টেশনারি (WSS) বলা হয় যদি এর গড় (mean) সময়ের সাথে ধ্রুবক থাকে এবং এর অটোকোরিলেশন শুধুমাত্র দুটি সময়বিন্দুর মধ্যকার ব্যবধানের উপর নির্ভর করে, নিজস্ব পরম অবস্থানের উপর নয়। ব্যবহারিকভাবে এর একটি সহজ পরিণতি — যদি একটি সিকোয়েন্স স্টেশনারি হয়, তাহলে এর যেকোনো যথেষ্ট বড় "উইন্ডো" (উপ-অংশ) থেকে হিসাব করা গড় ও ভ্যারিয়েন্স সিকোয়েন্সের শুরুতে, মাঝে, বা শেষে হিসাব করলেও মোটামুটি একই থাকা উচিত — কারণ প্রসেসের অন্তর্নিহিত পরিসংখ্যানিক নিয়ম বদলায় না। এটাই আমাদের নিচের ডেমোর মূল ধারণা।

WSS-এর দুই শর্ত
(১) $E[x[n]]$ ধ্রুবক (n-নির্ভর নয়), (২) $E[x[n]x[n+k]]$ শুধু ল্যাগ $k$-এর উপর নির্ভর করে, $n$-এর উপর নয়।
উইন্ডো-ভিত্তিক যাচাই
সিকোয়েন্সটিকে কয়েকটি উপ-উইন্ডোতে ভাগ করে প্রতিটির নমুনা-গড় ও নমুনা-ভ্যারিয়েন্স গণনা করলে — স্টেশনারি হলে এগুলো প্রায় সমান হবে, না হলে স্পষ্ট পার্থক্য দেখা যাবে।
নন-স্টেশনারি বাস্তব উদাহরণ
একটি বক্তৃতার সিগন্যাল, একটি ইঞ্জিনের কম্পন যার গতি বাড়ছে, বা একটি ফেডিং রেডিও চ্যানেল — এসব সাধারণত নন-স্টেশনারি, কারণ এদের পরিসংখ্যানিক আচরণ সময়ের সাথে বদলায়।

নিচের কোড সেলে দুটি সিকোয়েন্স তৈরি করা হয়েছে — উভয়ই random.gauss দিয়ে, একই দৈর্ঘ্যের (৬০ স্যাম্পল), একই ফিক্সড সিড দিয়ে, যাতে ফলাফল পুনরুৎপাদনযোগ্য হয়। প্রথমটি সত্যিকারের স্টেশনারি — পুরো সিকোয়েন্স জুড়েই mu=2.0, sigma=1.5 দিয়ে জেনারেট করা। দ্বিতীয়টি ইচ্ছাকৃতভাবে নন-স্টেশনারি — n=20-এর আগে mu=0.0, sigma=0.5, আর n=20-এর পর থেকে mu=6.0, sigma=3.0 দিয়ে তৈরি। প্রতিটি সিকোয়েন্সকে তিনটি সমান উইন্ডোতে (প্রতিটি ২০ স্যাম্পল) ভাগ করে statistics মডিউল দিয়ে প্রতিটি উইন্ডোর গড় ও ভ্যারিয়েন্স গণনা করা হয়েছে।

Python
import random, statistics

# --- স্টেশনারি-সদৃশ র‍্যান্ডম সিকোয়েন্স ---
random.seed(42)
N = 60
mu, sigma = 2.0, 1.5
x_stationary = [random.gauss(mu, sigma) for _ in range(N)]

window = 20
print("স্টেশনারি সিকোয়েন্স -- উইন্ডো-ভিত্তিক পরিসংখ্যান (mu=2.0, sigma=1.5 সারা সিকোয়েন্সে স্থির):")
for start in range(0, N, window):
    w = x_stationary[start:start+window]
    m = statistics.mean(w)
    v = statistics.variance(w)
    print(f"  window [{start}:{start+window}] -> mean={m:.4f}  variance={v:.4f}")

overall_mean = statistics.mean(x_stationary)
overall_var = statistics.variance(x_stationary)
print(f"সার্বিক: mean={overall_mean:.4f} variance={overall_var:.4f}")

print()

# --- নন-স্টেশনারি সিকোয়েন্স: mean ও variance জেনারেশনের মাঝপথে বদলে যায় ---
random.seed(42)
x_nonstationary = []
change_point = 20
for n in range(N):
    if n < change_point:
        x_nonstationary.append(random.gauss(0.0, 0.5))
    else:
        x_nonstationary.append(random.gauss(6.0, 3.0))

print(f"নন-স্টেশনারি সিকোয়েন্স -- উইন্ডো-ভিত্তিক পরিসংখ্যান (mean/var বদলায় n={change_point}-এ):")
for start in range(0, N, window):
    w = x_nonstationary[start:start+window]
    m = statistics.mean(w)
    v = statistics.variance(w)
    print(f"  window [{start}:{start+window}] -> mean={m:.4f}  variance={v:.4f}")

    
স্টেশনারি সিকোয়েন্সের তিনটি উইন্ডোর গড় (২.০৩৮৭, ১.৬৪৪৫, ২.৩৭৯০) সবই সত্যিকারের প্যারামিটার mu=2.0-এর কাছাকাছি ঘোরাফেরা করছে (ছোট নমুনা-আকারের কারণে সামান্য ওঠানামাসহ), আর ভ্যারিয়েন্সও (০.৯৭৮৪, ২.৩২০০, ১.৫৪২২) সত্যিকারের sigma²=2.25-এর আশেপাশে থাকছে — কোনো নিয়মতান্ত্রিক প্রবণতা (trend) নেই। কিন্তু নন-স্টেশনারি সিকোয়েন্সে প্রথম উইন্ডোর গড় ০.০১২৯ থেকে দ্বিতীয় ও তৃতীয় উইন্ডোয় লাফিয়ে ৫.২৮৯১ ও ৬.৭৫৮১-এ পৌঁছেছে — একটি স্পষ্ট, নিয়মতান্ত্রিক পরিবর্তন, যা প্রমাণ করে এই সিকোয়েন্সের পরিসংখ্যানিক আচরণ সময়ের সাথে সত্যিই বদলেছে।

৩ · এরগোডিসিটি (Ergodicity)

স্টেশনারিটি বলে একটি প্রসেসের পরিসংখ্যান সময়ের সাথে বদলায় না, কিন্তু বাস্তবে আমাদের কাছে সাধারণত একটিমাত্র রেকর্ডেড রিয়েলাইজেশন থাকে (যেমন একটি একক মাইক্রোফোন রেকর্ডিং) — অসংখ্য সমান্তরাল "মহাবিশ্ব"-এর একগুচ্ছ রেকর্ডিং (এনসেম্বল) নয়। এরগোডিসিটিErgodicity — একটি স্টেশনারি প্রসেসের বৈশিষ্ট্য যেখানে একটি একক, যথেষ্ট দীর্ঘ রিয়েলাইজেশনের সময়-গড় সম্পূর্ণ এনসেম্বলের গড়ের সমান হয়। মানে — একটি একক, যথেষ্ট দীর্ঘ রিয়েলাইজেশনের উপর সময়ের সাপেক্ষে গড় নিলে তা এনসেম্বল-গড়ের (থিওরেটিক্যাল প্রত্যাশিত মান) সমান হয়ে যায়। এই ধরে নেওয়ার কারণেই আমরা উপরের ডেমোতে একটিমাত্র সিকোয়েন্সের উইন্ডো-ভিত্তিক নমুনা-গড়/ ভ্যারিয়েন্স হিসাব করে "প্রকৃত" পরিসংখ্যানিক আচরণ সম্পর্কে সিদ্ধান্ত নিতে পেরেছি — যদি প্রসেসটি এরগোডিক না হতো, তাহলে একটি একক রেকর্ডিং থেকে গণনা করা পরিসংখ্যান বিভ্রান্তিকর হতে পারত। ব্যবহারিক DSP-তে (L49-এর SNR হিসাব, L44-এর PSD এস্টিমেশন) আমরা প্রায় সবসময় স্টেশনারিটি ও এরগোডিসিটি — দুটোই — ধরে নিই, যদি না স্পষ্ট প্রমাণ থাকে সিগন্যাল সময়ের সাথে বদলাচ্ছে (যেমন উপরের নন-স্টেশনারি উদাহরণে)।

মূল কথা · Key takeaway

স্টেশনারিটি ও এরগোডিসিটি — দুটোই অনুমান (assumption), প্রমাণ নয় — কিন্তু উপরের ডেমোর মতো উইন্ডো-ভিত্তিক পরিসংখ্যান দিয়ে সেই অনুমান সত্যি কি না তা যাচাই করা যায়। এই ধারণাগুলোই M11-এর বাকি তিনটি পাঠের ভিত্তি — L49-এ SNR হিসাবের জন্য আমরা নয়েজকে একটি স্টেশনারি র‍্যান্ডম প্রসেস হিসেবে ধরব, L50-এর ম্যাচড ফিল্টারে ব্যাকগ্রাউন্ড নয়েজ স্টেশনারি ধরে নিয়ে ডিটেকশন থ্রেশহোল্ড ঠিক করা হয়, আর L51-এর ওয়েনার ফিল্টার সিগন্যাল ও নয়েজের পরিসংখ্যান (ভ্যারিয়েন্স) জানা আছে ধরে নিয়ে অপটিমাল গেইন বের করে।

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

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

প্র ০১ উপরের ডেমোতে স্টেশনারি সিকোয়েন্সের তিনটি উইন্ডোর গড় (২.০৩৮৭, ১.৬৪৪৫, ২.৩৭৯০) নিজেরাও একে অপরের থেকে ভিন্ন — একদম সমান নয়। তাহলে এটি স্টেশনারি নয় বলা কি ভুল?

না, স্টেশনারিটির মানে এই নয় যে প্রতিটি নমুনা-পরিসংখ্যান বিটে-বিটে সমান হবে — মাত্র ২০টি স্যাম্পলের একটি ছোট উইন্ডো থেকে হিসাব করা নমুনা-গড় সবসময় সত্যিকারের গড় থেকে কিছুটা ওঠানামা করবে, এটাই পরিসংখ্যানের স্বাভাবিক নমুনা-বিচ্যুতি (sampling variability)। মূল প্রশ্ন হলো — এই ওঠানামা কি এলোমেলো (কোনো দিকনির্দেশ ছাড়া), নাকি একটি নিয়মতান্ত্রিক প্রবণতা অনুসরণ করছে? স্টেশনারি ক্ষেত্রে এটি এলোমেলো (২.০৩ → ১.৬৪ → ২.৩৮, কোনো একমুখী প্রবণতা নেই), অথচ নন-স্টেশনারি ক্ষেত্রে এটি স্পষ্টভাবে একমুখী বেড়ে গেছে (০.০১ → ৫.২৯ → ৬.৭৬)।

প্র ০২ যদি উইন্ডোর আকার ২০ স্যাম্পলের বদলে মাত্র ২ স্যাম্পল করা হতো, তাহলে কি স্টেশনারি বনাম নন-স্টেশনারি পার্থক্য করা সহজ হতো, নাকি কঠিন?

কঠিন হতো। মাত্র ২টি স্যাম্পল দিয়ে হিসাব করা নমুনা-গড়/ভ্যারিয়েন্সে নমুনা-বিচ্যুতি (random noise) অনেক বড় হয়ে যায় — প্রকৃত পরিসংখ্যানিক পরিবর্তনের সংকেত সেই এলোমেলো ওঠানামার নিচে চাপা পড়ে যেতে পারে। সাধারণ নিয়ম: যত বড় উইন্ডো, নমুনা-পরিসংখ্যান তত বেশি নির্ভরযোগ্যভাবে সত্যিকারের (থিওরেটিক্যাল) মানের কাছাকাছি থাকে — কিন্তু উইন্ডো খুব বড় হলে সময়ের সাথে দ্রুত ঘটা পরিবর্তন (যেমন n=২০-এর কাছাকাছি হঠাৎ পরিবর্তন) আলাদা করা কঠিন হয়ে যায়। এটি একটি ট্রেড-অফ, ঠিক যেমন M10-এর STFT-তে (L45) সময়-ফ্রিকোয়েন্সি রেজোলিউশন ট্রেড-অফ দেখা গিয়েছিল।

প্র ০৩ একটি বক্তৃতা (স্পিচ) সিগন্যাল সাধারণত নন-স্টেশনারি বলে গণ্য হয় (উচ্চারণ বদলালে ফ্রিকোয়েন্সি বৈশিষ্ট্য বদলায়) — তাহলে M10-এর STFT (L45) কেন এখনো কাজ করে?

STFT পুরো সিগন্যালকে একসাথে স্টেশনারি ধরে না — এটি সিগন্যালকে ছোট ছোট ওভারল্যাপিং ফ্রেমে ভাগ করে (যেমন ২০-৩০ মিলিসেকেন্ড), আর প্রতিটি ছোট ফ্রেমের ভেতরে সিগন্যালকে প্রায় স্থানীয়ভাবে স্টেশনারি (locally / short-time stationary) ধরে নেয়। এই অনুমান বক্তৃতার জন্য বাস্তবসম্মত, কারণ একটি একক ধ্বনির (phoneme) উচ্চারণকাল এত ছোট সময়সীমার মধ্যে ফ্রিকোয়েন্সি বৈশিষ্ট্য প্রায় স্থির থাকে — এটাই STFT-এর মূল কৌশল, L45-এ বিস্তারিত দেখা হয়েছিল।

অনুশীলন

  1. চিন্তা করুন: উপরের কোড সেলে change_point = 20-কে change_point = 40 -এ বদলালে, তিনটি উইন্ডোর ([0:20], [20:40], [40:60]) মধ্যে কোনগুলো "পুরনো" পরিসংখ্যান (mu=0.0, sigma=0.5) দেখাবে আর কোনটি "নতুন" (mu=6.0, sigma=3.0) পরিসংখ্যান দেখাবে বলে আপনার ধারণা?

    change_point=40 মানে n=০ থেকে ৩৯ পর্যন্ত পুরনো পরিসংখ্যান, n=৪০ থেকে ৫৯ পর্যন্ত নতুন পরিসংখ্যান। তাই উইন্ডো [0:20] ও [20:40] — দুটোই সম্পূর্ণভাবে পুরনো পরিসংখ্যানের (mean ≈ 0, variance ≈ 0.25), শুধু [40:60] উইন্ডোটি সম্পূর্ণভাবে নতুন পরিসংখ্যানের (mean ≈ 6, variance ≈ 9) দেখাবে।

  2. পরীক্ষা করুন: উপরের কোড সেলে change_point-কে ৪০-এ বদলে Run চেপে আপনার হিসেব যাচাই করুন।

    রান করলে দেখা যাবে প্রথম দুই উইন্ডোর গড় প্রায় শূন্যের কাছাকাছি (ছোট এলোমেলো ওঠানামাসহ) এবং ভ্যারিয়েন্স প্রায় ০.২৫-এর কাছাকাছি থাকবে, আর তৃতীয় উইন্ডোতেই হঠাৎ গড় প্রায় ৬-এর কাছে ও ভ্যারিয়েন্স বড় (প্রায় ৯-এর কাছাকাছি) দেখাবে — অর্থাৎ পরিবর্তনের বিন্দু (change point) যেখানেই বসানো হোক না কেন, উইন্ডো-ভিত্তিক পরিসংখ্যান সেই পরিবর্তনটি সত্যিই ধরে ফেলে।

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

আগের পাঠ
অ্যাডাপটিভ ফিল্টার — LMS অ্যালগরিদমের ভিত্তি