वास्तविक समय में माध्य और मानक विचलन का निर्धारण करना


31

वास्तविक समय के लिए सिग्नल के औसत और मानक विचलन को खोजने के लिए आदर्श तरीका क्या होगा। जब कोई सिग्नल 3 मानक विचलन से अधिक समय की निश्चित मात्रा के लिए बंद था, तो मैं एक नियंत्रक को ट्रिगर करने में सक्षम होना चाहता हूं।

मैं मान रहा हूं कि एक समर्पित डीएसपी यह बहुत तत्परता से करेगा, लेकिन क्या कोई "शॉर्टकट" है जिसे कुछ जटिल की आवश्यकता नहीं हो सकती है?


क्या आप सिग्नल के बारे में कुछ जानते हैं? क्या यह स्थिर है?

@ टिम कहते हैं कि यह स्थिर है। मेरी अपनी जिज्ञासा के लिए, एक गैर-स्थिर संकेत के प्रभाव क्या होंगे?
jonsca

3
यदि यह स्थिर है, तो आप बस एक रनिंग माध्य और मानक विचलन की गणना कर सकते हैं। यदि समय के साथ माध्य और मानक विचलन भिन्न होता है तो चीजें अधिक जटिल होंगी।

5
बहुत संबंधित: en.wikipedia.org/wiki/…
डॉ। Belisarius

जवाबों:


36

जेसन आर के जवाब में एक दोष है, जो नूथ के "कंप्यूटर प्रोग्रामिंग के कला" खंड में चर्चा की गई है। 2. समस्या तब आती है जब आपके पास एक मानक विचलन होता है जो कि माध्य का एक छोटा सा अंश होता है: E (x ^ 2) की गणना - (E (x) ^ 2) फ्लोटिंग पॉइंट राउंडिंग त्रुटियों के लिए गंभीर संवेदनशीलता से ग्रस्त है।

आप खुद भी इसे पायथन लिपि में आज़मा सकते हैं:

ofs = 1e9
A = [ofs+x for x in [1,-1,2,3,0,4.02,5]] 
A2 = [x*x for x in A]
(sum(A2)/len(A))-(sum(A)/len(A))**2

मुझे -128.0 एक उत्तर के रूप में मिलता है, जो स्पष्ट रूप से कम्प्यूटेशनल रूप से मान्य नहीं है, क्योंकि गणित भविष्यवाणी करता है कि परिणाम अप्रमाणिक होना चाहिए।

ननथ रनिंग माध्य और मानक विचलन की गणना के लिए एक दृष्टिकोण का आविष्कार करता है (मुझे आविष्कारक का नाम याद नहीं है) जो कुछ इस प्रकार है:

 initialize:
    m = 0;
    S = 0;
    n = 0;

 for each incoming sample x:
    prev_mean = m;
    n = n + 1;
    m = m + (x-m)/n;
    S = S + (x-m)*(x-prev_mean);

और फिर प्रत्येक चरण के बाद, का मान mमाध्य है, और मानक विचलन की गणना इस आधार पर sqrt(S/n)या की जा सकती है कि मानक विचलन sqrt(S/n-1)की आपकी पसंदीदा परिभाषा क्या है।

जो समीकरण मैं ऊपर लिख रहा हूं वह नूथ में एक की तुलना में थोड़ा अलग है, लेकिन यह कम्प्यूटेशनल रूप से समकक्ष है।

जब मेरे पास कुछ और मिनट होंगे, तो मैं उपरोक्त सूत्र को पायथन में कोड कर दूंगा और दिखाऊंगा कि आपको एक नॉनवेजिव उत्तर मिलेगा (यह उम्मीद सही मूल्य के करीब है)।


अद्यतन: यहाँ यह है

test1.py:

import math

def stats(x):
  n = 0
  S = 0.0
  m = 0.0
  for x_i in x:
    n = n + 1
    m_prev = m
    m = m + (x_i - m) / n
    S = S + (x_i - m) * (x_i - m_prev)
  return {'mean': m, 'variance': S/n}

def naive_stats(x):
  S1 = sum(x)
  n = len(x)
  S2 = sum([x_i**2 for x_i in x])
  return {'mean': S1/n, 'variance': (S2/n - (S1/n)**2) }

x1 = [1,-1,2,3,0,4.02,5] 
x2 = [x+1e9 for x in x1]

print "naive_stats:"
print naive_stats(x1)
print naive_stats(x2)

print "stats:"
print stats(x1)
print stats(x2)

परिणाम:

naive_stats:
{'variance': 4.0114775510204073, 'mean': 2.0028571428571427}
{'variance': -128.0, 'mean': 1000000002.0028572}
stats:
{'variance': 4.0114775510204073, 'mean': 2.0028571428571431}
{'variance': 4.0114775868357446, 'mean': 1000000002.0028571}

आप ध्यान देंगे कि अभी भी कुछ राउंडिंग त्रुटि है, लेकिन यह खराब नहीं है, जबकि naive_statsसिर्फ पुक।


संपादित करें: सिर्फ विकिपीडिया का हवाला देते हुए बेलिसरियस की टिप्पणी पर ध्यान दिया गया जिसमें नथ एल्गोरिथ्म का उल्लेख है।


1
उदाहरण कोड के साथ विस्तृत जवाब के लिए +1। फ्लोटिंग-पॉइंट कार्यान्वयन की आवश्यकता होने पर यह दृष्टिकोण मेरे उत्तर में बताए गए से बेहतर है।
जेसन आर

1
कोई इसे C ++ कार्यान्वयन के लिए भी देख सकता है: johndcook.com/standard_deviation.html
रुई

1
हाँ, यह बात है। वह सटीक समीकरणों का उपयोग करता है जो नथ उपयोग करता है। यदि आप मेरे तरीके का उपयोग करते हैं तो आप कुछ हद तक अनुकूलन कर सकते हैं और प्रारंभिक पुनरावृत्ति बनाम बाद के पुनरावृत्तियों की जांच करने से बच सकते हैं।
जेसन एस

"नथुथ चल रहे अर्थ की गणना के लिए एक दृष्टिकोण (मुझे आविष्कारक का नाम याद नहीं है) का हवाला देता है" - यह वेलफोर्ड की विधि है , वैसे।
जेसन एस

मैंने इससे संबंधित एक प्रश्न पोस्ट किया है अगर कोई मदद करने में सक्षम है: dsp.stackexchange.com/questions/31812/…
जोनाथन

13

वास्तविक समय के लिए सिग्नल के औसत और मानक विचलन को खोजने के लिए आदर्श तरीका क्या होगा। जब कोई सिग्नल 3 मानक विचलन से अधिक समय की निश्चित मात्रा के लिए बंद था, तो मैं एक नियंत्रक को ट्रिगर करने में सक्षम होना चाहता हूं।

इस तरह की स्थितियों में सही दृष्टिकोण आमतौर पर एक घातीय भारित औसत और मानक विचलन की गणना करना है। तेजी से भारित औसत, मतलब और विचरण के अनुमान में दे रही है हाल ही में नमूना प्रति पक्षपाती रहे हैं आप मतलब और विचरण का अनुमान है जो पिछले से अधिक सेकंडτ है, जो शायद तुम क्या चाहते है, बल्कि सभी नमूनों से अधिक सामान्य अंकगणित औसत की तुलना में अभी तक देखा है।

फ़्रीक्वेंसी डोमेन में, "एक्सपोनेंशली वेटेड रनिंग एवरेज" केवल एक वास्तविक पोल है। टाइम डोमेन में इसे लागू करना सरल है।

समय डोमेन कार्यान्वयन

चलो meanऔर meansqमतलब की मौजूदा अनुमान हो सकता है और संकेत के वर्ग का मतलब है। हर चक्र पर, नए नमूने के साथ इन अनुमानों को अपडेट करें x:

% update the estimate of the mean and the mean square:
mean = (1-a)*mean + a*x
meansq = (1-a)*meansq + a*(x^2)

% calculate the estimate of the variance:
var = meansq - mean^2;

% and, if you want standard deviation:
std = sqrt(var);

यहां एक स्थिर है जो रनिंग औसत की प्रभावी लंबाई निर्धारित करता है। कैसे चयन करने के लिए एक "विश्लेषण" में नीचे वर्णित है।0<<1

एक संकेत कार्यक्रम के रूप में ऊपर वर्णित एक संकेत-प्रवाह आरेख के रूप में भी दर्शाया जा सकता है:

यहां छवि विवरण दर्ज करें

विश्लेषण

yमैं=एक्समैं+(1-)yमैं-1एक्समैंमैंyमैंz

एच(z)=1-(1-)z-1

IIR फिल्टर को अपने-अपने ब्लॉक में संघनित करना, आरेख अब इस तरह दिखता है:

यहां छवि विवरण दर्ज करें

z=रोंटीटीरों=1/टी1-(1-)-रोंटी=0रों=1टीलॉग(1-)

=1-exp{2πटीτ}

संदर्भ


1
0 > a > 1

यह जेसन आर के दृष्टिकोण के समान है। यह विधि कम सटीक होगी लेकिन मेमोरी पर थोड़ी तेज और कम होगी। यह दृष्टिकोण एक घातीय खिड़की का उपयोग करके समाप्त होता है।
शनरफ

ओह! बेशक मेरा मतलब था 0 < a < 1। यदि आपके सिस्टम में tmie का नमूना है Tऔर आप औसत समय स्थिर रखना चाहते हैं tau, तो चुनें a = 1 - exp (2*pi*T/tau)
nibot 20

मुझे लगता है कि यहां कोई गलती हो सकती है। एकल-पोल फ़िल्टर में DC पर 0 dB का लाभ नहीं होता है और चूंकि आप रैखिक डोमेन में एक फ़िल्टर लागू कर रहे हैं और एक वर्ग में डोमेन लाभ E <x> और E <x ^ 2> के लिए भिन्न है। मैं अपने उत्तर में अधिक विस्तार से बताता हूं
हिलमार

यह डीसी में 0 डीबी हासिल करता है। स्थानापन्न z=1में (डीसी) H(z) = a/(1-(1-a)/z)और आपको मिल 1.
nibot

5

एक विधि जो मैंने एक एम्बेडेड प्रोसेसिंग एप्लिकेशन में पहले इस्तेमाल की है वह ब्याज के संकेत के योग और योग के वर्गों को बनाए रखने के लिए है:

एक्स,मैं=Σकश्मीर=0मैंएक्स[कश्मीर]=एक्स,मैं-1+एक्स[मैं],एक्स,-1=0

एक्स2,मैं=Σकश्मीर=0मैंएक्स2[कश्मीर]=एक्स2,मैं-1+एक्स2[मैं],एक्स2,-1=0

मैंमैं

μ~=एक्समैंमैं+1

σ~=एक्समैं2मैं+1-μ~2

या आप उपयोग कर सकते हैं:

σ~=एक्समैं2मैं-μ~2

निर्भर करता है कि आप किस मानक विचलन अनुमान पद्धति को पसंद करते हैं । ये समीकरण विचरण की परिभाषा पर आधारित हैं :

σ2=(एक्स2)-((एक्स))2

मैंने अतीत में सफलतापूर्वक इनका उपयोग किया है (हालाँकि मैं केवल विचरण अनुमान से संबंधित था, मानक विचलन से नहीं), हालाँकि आपको संचयकर्ता के बारे में सावधान रहना होगा जो आप संचयकों को पकड़ने के लिए उपयोग करते हैं यदि आप योग करने जा रहे हैं समय की लंबी अवधि; आप अतिप्रवाह नहीं चाहते हैं।

संपादित करें: अतिप्रवाह पर उपरोक्त टिप्पणी के अलावा, यह ध्यान दिया जाना चाहिए कि फ्लोटिंग-पॉइंट अंकगणित में कार्यान्वित होने पर यह संख्यात्मक रूप से मजबूत एल्गोरिथम नहीं है, संभवतः अनुमानित आंकड़ों में बड़ी त्रुटियां पैदा कर सकता है। उस मामले में बेहतर दृष्टिकोण के लिए जेसन एस के जवाब को देखें।


1
एक्स,मैं=एक्स[मैं]+एक्स,मैं-1, एक्स,0=एक्स[0]मैंएक्स

हाँ, यह बेहतर है। मैंने पुनरावर्ती कार्यान्वयन को अधिक स्पष्ट बनाने के लिए फिर से लिखने की कोशिश की।
जेसन आर

2
-1 जब मेरे पास ऐसा करने के लिए पर्याप्त प्रतिनिधि हैं: तो इसमें संख्यात्मक समस्याएं हैं। नुथ वॉल्यूम देखें। 2
जेसन एस

σμ2σ2=(एक्स2)-((एक्स))2

2
@ जैसन: मैं इस बात से असहमत हूं कि तकनीक स्वाभाविक रूप से दोषपूर्ण है, हालांकि मैं आपकी बात से सहमत हूं कि फ्लोटिंग पॉइंट में लागू होने पर यह संख्यात्मक रूप से मजबूत तरीका नहीं है। मुझे अधिक स्पष्ट होना चाहिए था कि मैंने इसे एक ऐसे एप्लिकेशन में सफलतापूर्वक उपयोग किया है जो पूर्णांक अंकगणित का उपयोग करता है । पूर्णांक (या भिन्नात्मक संख्याओं के नियत-बिंदु कार्यान्वयन) अंकगणित उस समस्या से ग्रस्त नहीं होता है जिसे आपने बताया है कि सटीकता का नुकसान होता है। उस संदर्भ में, यह एक उपयुक्त विधि है जिसमें प्रति नमूने कम संचालन की आवश्यकता होती है।
जेसन आर

3

ऊपर दिए गए पसंदीदा उत्तर के समान (जेसन एस।), और नॉट (Vol.2, p 232) से लिए गए फॉर्मूले से भी प्राप्त किया जा सकता है, एक मान को बदलने के लिए एक फार्मूला भी निकाला जा सकता है, अर्थात एक चरण में मान निकालें और जोड़ें । मेरे परीक्षणों के अनुसार, दो-चरण हटाने / जोड़ने के संस्करण की तुलना में प्रतिस्थापन बेहतर परिशुद्धता प्रदान करता है।

नीचे दिए गए कोड जावा में हैं, meanऔर जेसन के पोस्ट में और ऊपर s("वैश्विक" सदस्य चर) अपडेट किए जाते हैं । मान विंडो आकार को संदर्भित करता है ।mscountn

/**
 * Replaces the value {@code x} currently present in this sample with the
 * new value {@code y}. In a sliding window, {@code x} is the value that
 * drops out and {@code y} is the new value entering the window. The sample
 * count remains constant with this operation.
 * 
 * @param x
 *            the value to remove
 * @param y
 *            the value to add
 */
public void replace(double x, double y) {
    final double deltaYX = y - x;
    final double deltaX = x - mean;
    final double deltaY = y - mean;
    mean = mean + deltaYX / count;
    final double deltaYp = y - mean;
    final double countMinus1 = count - 1;
    s = s - count / countMinus1 * (deltaX * deltaX - deltaY * deltaYp) - deltaYX * deltaYp / countMinus1;
}

3

जेसन और निबोट का उत्तर एक महत्वपूर्ण पहलू में भिन्न होता है: जेसन की विधि std dev की गणना करती है और पूरे सिग्नल के लिए (y = 0 से) का अर्थ है, जबकि निबोट की "रनिंग" गणना है, अर्थात यह नमूनों से मजबूत हाल के नमूनों का वजन अधिक है सुदूर अतीत।

चूंकि एप्लिकेशन को समय के एक फ़ंक्शन के रूप में std dev और माध्य की आवश्यकता प्रतीत होती है, निबोट की विधि संभवतः अधिक उपयुक्त एक है (इस विशिष्ट एप्लिकेशन के लिए)। हालांकि, वास्तविक मुश्किल हिस्सा सही समय पर वजन प्राप्त करने के लिए होगा। निबोट का उदाहरण एक साधारण एकल पोल फिल्टर का उपयोग करता है।

[एक्स]एक्स[n][एक्स2]एक्स[n]2

लोपास फ़िल्टर का विकल्प आपके द्वारा आपके संकेत और आपके अनुमान के लिए आवश्यक समय रिज़ॉल्यूशन के बारे में पता करके निर्देशित किया जा सकता है। कम कटऑफ आवृत्तियों और उच्चतर क्रम में बेहतर सटीकता होगी लेकिन धीमी प्रतिक्रिया समय होगा।

चीजों को जटिल करने के लिए आगे एक फिल्टर रैखिक डोमेन में और दूसरा वर्ग डोमेन में लगाया जाता है। स्क्वेरिंग करने से सिग्नल की वर्णक्रमीय सामग्री में काफी बदलाव आता है ताकि आप स्क्वर्ट डोमेन में एक अलग फ़िल्टर का उपयोग करना चाहें।

समय के कार्य के रूप में माध्य, rms और std देव का अनुमान लगाने के तरीके पर एक उदाहरण दिया गया है।

%% example
fs = 44100; n = fs; % 44.1 kHz sample rate, 1 second
% signal: white noise plus a low frequency drift at 5 Hz)
x = randn(n,1) + sin(2*pi*(0:n-1)'*5/fs);
% mean estimation filter: since we are looking for effects in the 5 Hz range we use maybe a
% 25 Hz filter, 2nd order so it's not too sluggish
[b,a] = butter(2,25*2/fs);
xmeanEst = filter(b,a,x);
% now we estimate x^2, since most frequency double we use twice the bandwidth
[b,a] = butter(2,50*2/fs);
x2Est = filter(b,a,x.^2);
% std deviation estimate
xstd = sqrt(x2Est)-xmeanEst;
% and plot it
h = plot([x, xmeanEst sqrt(x2Est) xstd]);
grid on;
legend('x','E<x>','sqrt(E<x^2>)','Std dev');
set(h(2:4),'Linewidth',2);

1
मेरे उत्तर में फ़िल्टर से मेल खाती है y1 = filter(a,[1 (1-a)],x);
nibot

1
चल रहे आंकड़ों और समग्र नमूने के आंकड़ों के बीच अंतर पर अच्छा बिंदु। मेरे कार्यान्वयन को एक चलती हुई खिड़की पर जमा करके चलने वाले आँकड़ों की गणना करने के लिए संशोधित किया जा सकता है, जो कुशलतापूर्वक भी किया जा सकता है (प्रत्येक समय कदम पर, प्रत्येक संचयकर्ता से खिड़की से बाहर निकलने वाले समय के नमूने को घटाएं)।
जेसन आर

nibot, क्षमा करें आप सही हैं और मैं गलत था। मैं इसे अभी दूर कर दूंगा
हिल्मर

1
+1 को x और x ^ 2 के लिए अलग-अलग फ़िल्टरिंग सुझाने के लिए
nibot
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.