औसत निरपेक्ष विचलन और बड़े डेटा सेट के लिए ऑनलाइन एल्गोरिथ्म


16

मुझे थोड़ी समस्या है जो मुझे बेहोश कर रही है। मुझे एक बहुभिन्नरूपी श्रृंखला की ऑनलाइन अधिग्रहण प्रक्रिया के लिए प्रक्रिया लिखना है। हर बार अंतराल पर (उदाहरण के लिए 1 सेकंड), मुझे एक नया नमूना मिलता है, जो मूल रूप से आकार एन का एक अस्थायी बिंदु वेक्टर है। मुझे जो ऑपरेशन करना है वह थोड़ा मुश्किल है:

  1. प्रत्येक नए नमूने के लिए, मैं उस नमूने के लिए केंद्रांश की गणना करता हूं (वेक्टर को सामान्य करके ताकि तत्व 1 के बराबर हो जाएं)।

  2. मैं उसी तरह से औसत प्रतिशत सदिश की गणना करता हूं, लेकिन पिछले मूल्यों का उपयोग कर रहा हूं।

  3. प्रत्येक पिछले मूल्य के लिए, मैं चरण 2 पर गणना की गई वैश्विक औसत प्रतिशत सदिश के साथ उस नमूने से संबंधित सदिश वेक्टर के पूर्ण विचलन की गणना करता हूं। इस तरह, पूर्ण विचलन हमेशा 0 के बीच एक संख्या है (जब वेक्टर औसत के बराबर होता है वेक्टर) और 2 (जब यह कुल अलग है)।

  4. पिछले सभी नमूनों के लिए विचलन के औसत का उपयोग करते हुए, मैं औसत निरपेक्ष विचलन की गणना करता हूं, जो फिर से 0 और 2 के बीच की संख्या है।

  5. मैं पता लगाने के लिए औसत निरपेक्ष विचलन का उपयोग करता हूं कि क्या कोई नया नमूना अन्य नमूनों के साथ संगत है (चरण 4 में गणना की गई संपूर्ण सेट के औसत निरपेक्ष विचलन के साथ इसकी पूर्ण विचलन की तुलना करके)।

चूँकि हर बार एक नया नमूना वैश्विक औसत परिवर्तन (और इसलिए औसत विचलन परिवर्तन के रूप में अच्छी तरह से) एकत्र किया जाता है, क्या इस मूल्य की गणना करने का एक तरीका है कि पूरे डेटा को कई बार स्कैन किए बिना गणना की जाए? (वैश्विक औसत प्रतिशत की गणना के लिए एक समय, और पूर्ण विचलन एकत्र करने के लिए एक समय)। ठीक है, मुझे पता है कि पूरे सेट को स्कैन किए बिना वैश्विक औसत की गणना करना बिल्कुल आसान है, क्योंकि मुझे बस प्रत्येक आयाम के योग को संग्रहीत करने के लिए एक अस्थायी वेक्टर का उपयोग करना है, लेकिन मतलब निरपेक्ष विचलन के बारे में क्या? इसकी गणना में abs()ऑपरेटर शामिल है , इसलिए मुझे पिछले सभी डेटा तक पहुंचने की आवश्यकता है!

आपकी सहायता के लिए धन्यवाद।

जवाबों:


6

यदि आप कुछ अशुद्धि को स्वीकार कर सकते हैं, तो बिनिंग काउंट द्वारा इस समस्या को आसानी से हल किया जा सकता है । यही है, कुछ लार्जिश नंबर ( M = 1000 कहें ) को चुनें, फिर कुछ पूर्णांक B B को I , j के लिए i = 1 M और j = 1 N से प्रारंभ करें , जहाँ N , वेक्टर का आकार, शून्य है। फिर जब आप देखते हैं कश्मीर एक percentual वेक्टर के वें अवलोकन, वेतन वृद्धि बी मैं , जे अगर j इस सदिश का वें तत्व के बीच है (MM=1000Bi,ji=1Mj=1NNkBi,jj और आई / एम ,वेक्टरके एन तत्वोंपर पाशन। (मैं मान रहा हूं कि आपके इनपुट वैक्टर गैर-नकारात्मक हैं, इसलिए जब आप अपने 'प्रतिशत' की गणना करते हैं, तो वैक्टर [ 0 , 1 ] श्रेणी में होते हैं।)(i1)/Mi/MN[0,1]

किसी भी समय, आप बिन से मतलब वेक्टर, और मतलब पूर्ण विचलन का अनुमान लगा सकते हैं। ऐसे वैक्टरों को देखने के बाद , माध्य का j तत्व ˉ X j = 1 द्वारा अनुमानित किया जाता हैKjऔरjth तत्व का अर्थ पूर्ण विचलन1 है

X¯j=1Kii1/2MBi,j,
j
1Ki|Xj¯i1/2M|Bi,j

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


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

@gianluca: ऐसा लगता है कि आपके पास 1. बहुत अधिक डेटा है, 2. सीमित स्मृति संसाधन, 3. उच्च परिशुद्धता की आवश्यकताएं। मैं देख सकता हूं कि यह समस्या आपको क्यों निकाल रही है! शायद, जैसा कि @kwak द्वारा उल्लेख किया गया है, आप प्रसार के कुछ अन्य माप की गणना कर सकते हैं: एमएडी, आईक्यूआर, मानक विचलन। उन सभी में दृष्टिकोण हैं जो आपकी समस्या के लिए काम कर सकते हैं।
Shabbychef

gianluca:> हमें स्मृति, सरणियों और सटीकता के आकार के बारे में अधिक मात्रात्मक विचार दें। यह अच्छी तरह से हो सकता है कि आपके प्रश्न का सबसे अच्छा उत्तर दिया जाएगा @ stackoverflow हालांकि।
user603

4

मैंने अतीत में निम्न दृष्टिकोण का उपयोग कुशलता से अनुपस्थिति विचलन की गणना करने के लिए किया है (ध्यान दें, यह एक प्रोग्रामर दृष्टिकोण है, न कि एक सांख्यिकीविद्, इसलिए अप्रत्यक्ष रूप से shabbychef की तरह चतुर चाल हो सकती है जो अधिक कुशल हो सकती है)।

चेतावनी: यह एक ऑनलाइन एल्गोरिथ्म नहीं है। इसके लिए O(n)स्मृति की आवश्यकता होती है। इसके अलावा, इसमें O(n)डेटासेट के लिए सबसे खराब स्थिति है [1, -2, 4, -8, 16, -32, ...](जैसे कि पूर्ण पुनर्गणना के समान)। [1]

हालाँकि, क्योंकि यह अभी भी कई उपयोग के मामलों में अच्छा प्रदर्शन करता है, यह यहाँ पोस्ट करने लायक हो सकता है। उदाहरण के लिए, प्रत्येक आइटम के आते ही -100 और 100 के बीच 10000 यादृच्छिक संख्याओं की पूर्ण अवमूल्यन की गणना करने के लिए , मेरा एल्गोरिथ्म एक सेकंड से भी कम समय लेता है, जबकि पूर्ण पुनर्गणना में 17 सेकंड से अधिक समय लगता है (मेरी मशीन पर, प्रति मशीन अलग-अलग होगी और इनपुट डेटा के अनुसार)। आपको हालाँकि पूरे सदिश को स्मृति में बनाए रखना होगा, जो कुछ उपयोगों के लिए एक बाधा हो सकती है। एल्गोरिथ्म की रूपरेखा निम्नानुसार है:

  1. पिछले मापों को संग्रहीत करने के लिए एक एकल वेक्टर होने के बजाय, तीन क्रमबद्ध प्राथमिकता वाले कतारों (कुछ मिनट / अधिकतम ढेर) का उपयोग करें। ये तीन सूचियाँ इनपुट को तीन में विभाजित करती हैं: माध्य से अधिक आइटम, माध्य से कम वस्तु और माध्य के बराबर आइटम।
  2. (लगभग) हर बार जब आप किसी आइटम को जोड़ते हैं, तो हमें बदलाव की आवश्यकता होती है। महत्वपूर्ण बात यह है कि विभाजन की छँटाई प्रकृति है जिसका अर्थ है कि सूची में प्रत्येक आइटम को पुनरावृत्ति के लिए स्कैन करने के बजाय, हमें केवल उन वस्तुओं को पढ़ना होगा जो हम आगे बढ़ रहे हैं। हालांकि सबसे खराब स्थिति में इसके लिए अभी भी O(n)कदम संचालन की आवश्यकता होगी , कई उपयोग-मामलों के लिए ऐसा नहीं है।
  3. कुछ चतुर बहीखाते का उपयोग करते हुए, हम यह सुनिश्चित कर सकते हैं कि हर समय, जब पुनरावृत्ति हो रही हो और नई वस्तुओं को जोड़ते समय विचलन की सही गणना की जाए।

कुछ नमूना कोड, अजगर में, नीचे है। ध्यान दें कि यह केवल आइटम को सूची में जोड़ने की अनुमति देता है, हटाए नहीं। यह आसानी से जोड़ा जा सकता है, लेकिन जिस समय मैंने यह लिखा था मुझे इसकी कोई आवश्यकता नहीं थी। प्राथमिकता कतारों अपने आप को लागू करने के बजाय, मैं का इस्तेमाल किया है sortedlist डैनियल Stutzbach उत्तम से blist पैकेज है, जो उपयोग बी + ट्री आंतरिक रूप से है।

एमआईटी लाइसेंस के तहत लाइसेंस प्राप्त इस कोड पर विचार करें । यह काफी अनुकूलित या पॉलिश नहीं किया गया है, लेकिन मेरे लिए अतीत में काम किया है। नए संस्करण यहां उपलब्ध होंगे । यदि आपके कोई प्रश्न हैं, या कोई बग ढूंढते हैं तो मुझे बताएं।

from blist import sortedlist
import operator

class deviance_list:
    def __init__(self):
        self.mean =  0.0
        self._old_mean = 0.0
        self._sum =  0L
        self._n =  0  #n items
        # items greater than the mean
        self._toplist =  sortedlist()
        # items less than the mean
        self._bottomlist = sortedlist(key = operator.neg)
        # Since all items in the "eq list" have the same value (self.mean) we don't need
        # to maintain an eq list, only a count
        self._eqlistlen = 0

        self._top_deviance =  0
        self._bottom_deviance =  0

    @property
    def absolute_deviance(self):
        return self._top_deviance + self._bottom_deviance

    def append(self,  n):
        # Update summary stats
        self._sum += n
        self._n +=  1
        self._old_mean =  self.mean
        self.mean =  self._sum /  float(self._n)

        # Move existing things around
        going_up = self.mean > self._old_mean
        self._rebalance(going_up)

        # Add new item to appropriate list
        if n >  self.mean:
            self._toplist.add(n)
            self._top_deviance +=  n -  self.mean
        elif n == self.mean: 
            self._eqlistlen += 1
        else:
            self._bottomlist.add(n)
            self._bottom_deviance += self.mean -  n


    def _move_eqs(self,  going_up):
        if going_up:
            self._bottomlist.update([self._old_mean] *  self._eqlistlen)
            self._bottom_deviance += (self.mean - self._old_mean) * self._eqlistlen
            self._eqlistlen = 0
        else:
            self._toplist.update([self._old_mean] *  self._eqlistlen)
            self._top_deviance += (self._old_mean - self.mean) * self._eqlistlen
            self._eqlistlen = 0


    def _rebalance(self, going_up):
        move_count,  eq_move_count = 0, 0
        if going_up:
            # increase the bottom deviance of the items already in the bottomlist
            if self.mean !=  self._old_mean:
                self._bottom_deviance += len(self._bottomlist) *  (self.mean -  self._old_mean)
                self._move_eqs(going_up)


            # transfer items from top to bottom (or eq) list, and change the deviances
            for n in iter(self._toplist):
                if n < self.mean:
                    self._top_deviance -= n -  self._old_mean
                    self._bottom_deviance += (self.mean -  n)
                    # we increment movecount and move them after the list
                    # has finished iterating so we don't modify the list during iteration
                    move_count +=  1
                elif n == self.mean:
                    self._top_deviance -= n -  self._old_mean
                    self._eqlistlen += 1
                    eq_move_count +=  1
                else:
                    break
            for _ in xrange(0,  move_count):
                self._bottomlist.add(self._toplist.pop(0))
            for _ in xrange(0,  eq_move_count):
                self._toplist.pop(0)

            # decrease the top deviance of the items remain in the toplist
            self._top_deviance -= len(self._toplist) *  (self.mean -  self._old_mean)
        else:
            if self.mean !=  self._old_mean:
                self._top_deviance += len(self._toplist) *  (self._old_mean -  self.mean)
                self._move_eqs(going_up)
            for n in iter(self._bottomlist): 
                if n > self.mean:
                    self._bottom_deviance -= self._old_mean -  n
                    self._top_deviance += n -  self.mean
                    move_count += 1
                elif n == self.mean:
                    self._bottom_deviance -= self._old_mean -  n
                    self._eqlistlen += 1
                    eq_move_count +=  1
                else:
                    break
            for _ in xrange(0,  move_count):
                    self._toplist.add(self._bottomlist.pop(0))
            for _ in xrange(0,  eq_move_count):
                self._bottomlist.pop(0)

            # decrease the bottom deviance of the items remain in the bottomlist
            self._bottom_deviance -= len(self._bottomlist) *  (self._old_mean -  self.mean)


if __name__ ==  "__main__":
    import random
    dv =  deviance_list()
    # Test against some random data,  and calculate result manually (nb. slowly) to ensure correctness
    rands = [random.randint(-100,  100) for _ in range(0,  1000)]
    ns = []
    for n in rands: 
        dv.append(n)
        ns.append(n)
        print("added:%4d,  mean:%3.2f,  oldmean:%3.2f,  mean ad:%3.2f" %
              (n, dv.mean,  dv._old_mean,  dv.absolute_deviance / dv.mean))
        assert sum(ns) == dv._sum,  "Sums not equal!"
        assert len(ns) == dv._n,  "Counts not equal!"
        m = sum(ns) / float(len(ns))
        assert m == dv.mean,  "Means not equal!"
        real_abs_dev = sum([abs(m - x) for x in ns])
        # Due to floating point imprecision, we check if the difference between the
        # two ways of calculating the asb. dev. is small rather than checking equality
        assert abs(real_abs_dev - dv.absolute_deviance) < 0.01, (
            "Absolute deviances not equal. Real:%.2f,  calc:%.2f" %  (real_abs_dev,  dv.absolute_deviance))

[१] यदि लक्षण बने रहते हैं, तो अपने चिकित्सक को देखें।


2
मुझे कुछ याद आ रहा है: यदि आपको "पूरे वेक्टर को मेमोरी में बनाए रखना है," यह "ऑनलाइन" एल्गोरिथम के रूप में कैसे योग्य है?
whuber

@ जब तक नहीं, कुछ याद नहीं है, मुझे लगता है कि यह ऑनलाइन एल्गोरिथ्म नहीं है। इसके लिए O(n)मेमोरी की आवश्यकता होती है, और सबसे खराब स्थिति में प्रत्येक आइटम के लिए O (n) समय लगता है। सामान्य रूप से वितरित डेटा (और शायद अन्य वितरण) में यह काफी कुशलता से काम करता है।
बजे

3

XXXss2/π


यह एक दिलचस्प विचार है। आप इसे पूरक कर सकते हैं, शायद, आउटलेर की ऑनलाइन पहचान के साथ और अनुमान को संशोधित करने के लिए उन का उपयोग करें जैसे आप साथ जाते हैं।
whuber

आप शायद मानक विचलन की गणना के लिए Welford की विधि का उपयोग कर सकते हैं जिसे मैंने अपने दूसरे उत्तर में प्रलेखित किया था।
बजे

1
हालांकि, इस बात पर ध्यान देना चाहिए कि इस तरह के स्पष्ट MAD जैसे अनुमानकर्ताओं की मजबूती खो सकती है, जो कभी-कभी सरल विकल्प के खिलाफ अपनी पसंद के अनुसार ड्राइविंग करते हैं।
क्वार्ट्ज

2

एमएडी (एक्स) केवल दो समवर्ती मध्ययुगीन संगणना है, जिनमें से प्रत्येक को बिनमेडियन एल्गोरिथ्म के माध्यम से ऑनलाइन बनाया जा सकता है ।

आप संबंधित पेपर के साथ-साथ C और FORTRAN कोड को यहां ऑनलाइन पा सकते हैं

(यह सिर्फ Shabbychef के चालाक चाल के शीर्ष पर एक चालाक चाल का उपयोग है, स्मृति को बचाने के लिए)।

परिशिष्ट:

क्वांटमों की गणना के लिए पुराने बहु-पास तरीकों की एक मेजबान मौजूद है। एक लोकप्रिय दृष्टिकोण को बनाए रखने / टिप्पणियों बेतरतीब ढंग से धारा से चयनित और रिकर्सिवली गणना quantiles के निर्धारणात्मक आकार जलाशय अद्यतन करने के लिए है (देखें यह इस जलाशय पर समीक्षा)। यह (संबंधित और संबंधित) दृष्टिकोण ऊपर प्रस्तावित एक द्वारा छोड़े गए हैं।


क्या आप MAD और दो मध्यस्थों के बीच संबंध को विस्तार या संदर्भ दे सकते हैं?
क्वार्ट्ज

medi=1n|ximedi=1n|

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

मुझे विवरण के लिए द्विपदीय पत्र पर वापस जाना होगा ... लेकिन माध्यिका का एक गणना मूल्य दिया गया है (मैं=1nएक्समैं) और का एक नया मूल्य एक्सn+1 एल्गोरिथ्म गणना कर सकता है मैं=1n+1एक्समैं से ज्यादा तेज हे(n) बिन को पहचान कर किसके लिए एक्सn+1अंतर्गत आता है। मैं यह नहीं देखता कि पागल गणना में बाहरी अंतर्दृष्टि के लिए इस अंतर्दृष्टि को कैसे सामान्य नहीं किया जा सकता है।
user603

1

निम्नलिखित एक गलत अनुमान प्रदान करता है, हालांकि अशुद्धि इनपुट डेटा के वितरण पर निर्भर करेगा। यह एक ऑनलाइन एल्गोरिथ्म है, लेकिन केवल पूर्ण विचलन का अनुमान लगाता है। यह 1960 में Welford द्वारा वर्णित ऑनलाइन विचरण की गणना के लिए एक प्रसिद्ध एल्गोरिथ्म पर आधारित है । उसका एल्गोरिथ्म, आर में अनुवादित, जैसा दिखता है:

M2 <- 0
mean <- 0
n <- 0

var.online <- function(x){
    n <<- n + 1
    diff <- x - mean
    mean <<- mean + diff / n
    M2 <<- M2 + diff * (x - mean)
    variance <- M2 / (n - 1)
    return(variance)
}

यह आर के बिलिन विचरण समारोह के समान ही कार्य करता है:

set.seed(2099)
n.testitems <- 1000
n.tests <- 100
differences <- rep(NA, n.tests)
for (i in 1:n.tests){
        # Reset counters
        M2 <- 0
        mean <- 0
        n <- 0

        xs <- rnorm(n.testitems)
        for (j in 1:n.testitems){
                v <- var.online(xs[j])
        }

        differences[i] <- abs(v - var(xs))

}
summary(differences)
     Min.   1st Qu.    Median      Mean   3rd Qu.      Max. 
0.000e+00 2.220e-16 4.996e-16 6.595e-16 9.992e-16 1.887e-15 

पूर्ण विचलन की गणना करने के लिए एल्गोरिथ्म को संशोधित करना बस एक अतिरिक्त sqrtकॉल शामिल है । हालाँकि, sqrtपरिणाम में परिलक्षित होने वाली अशुद्धियाँ प्रस्तुत करती हैं:

absolute.deviance.online <- function(x){
    n <<- n + 1
    diff <- x - mean
    mean <<- mean + diff / n
    a.dev <<- a.dev + sqrt(diff * (x - mean))
    return(a.dev)
}

त्रुटियों की गणना, ऊपर की गणना के लिए की तुलना में बहुत अधिक है:

    Min.  1st Qu.   Median     Mean  3rd Qu.     Max. 
0.005126 0.364600 0.808000 0.958800 1.360000 3.312000 

हालाँकि, आपके उपयोग के मामले के आधार पर, त्रुटि की यह परिमाण स्वीकार्य हो सकती है।

historgram of differences


यह निम्नलिखित कारण के लिए सटीक उत्तर नहीं देता है: Σमैंएक्समैंΣमैंएक्समैं। आप पूर्व की गणना कर रहे हैं, जबकि ओपी बाद वाला चाहता है।
shabbychef

मैं इस बात से सहमत हूं कि यह तरीका अक्षम्य है। हालांकि, मैं अनुभवहीनता के आपके निदान से असहमत हूं। विचरण की गणना के लिए Welford की विधि, जिसमें sqrt भी नहीं है, एक समान त्रुटि है। हालांकि, जैसा कि nबड़ा होता है, error/nगायब हो जाता है छोटा, आश्चर्यजनक रूप से जल्दी से।
23

Welford की विधि में कोई sqrt नहीं है क्योंकि यह विचलन की गणना कर रहा है, न कि मानक विचलन का। Sqrt लेने से ऐसा लगता है जैसे आप मानक विचलन का अनुमान लगा रहे हैं, न कि निरपेक्ष विचलन का। क्या मैं कुछ भूल रहा हूँ?
शाबाइशेफ

@ शब्बीशेफ वेलफोर्ड का प्रत्येक पुनरावृत्ति पूर्ण विचलन के लिए नए डेटापॉइंट के योगदान की गणना कर रहा है, चुकता। इसलिए मैं पूर्ण योगदान को वापस पाने के लिए प्रत्येक योगदान की वर्गमूल लेता हूं। आप उदाहरण के लिए, ध्यान दें कि मैं डेल्टा के वर्गमूल को इससे पहले कि मैं इसे विचलन योग में जोड़ दूं, बजाय मानक विचलन के मामले में आगे ले जाऊं।
5

3
मैं समस्या को देखता हूं; Welfords इस विधि के साथ समस्या को अस्पष्ट करता है: माध्य के अंतिम अनुमान के बजाय माध्य के ऑनलाइन अनुमान का उपयोग किया जा रहा है। जबकि Welford की विधि विचरण के लिए सटीक (राउंडऑफ़ तक) है, यह विधि नहीं है। समस्या आवेग के कारण नहीं हैsqrt । ऐसा इसलिए है क्योंकि यह रनिंग माध्य अनुमान का उपयोग करता है। यह देखने के लिए कि यह कब टूट जाएगा, xs <- sort(rnorm(n.testitems)) जब मैं आपके कोड के साथ यह कोशिश करता हूं (इसे वापस करने के लिए ठीक करने के बाद a.dev / n), मुझे 9% -16% के आदेश पर सापेक्ष त्रुटियां मिलती हैं। तो यह विधि क्रमपरिवर्तन नहीं है, जो तबाही का कारण बन सकता है ...
shabbychef
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.