ट्रेंडिंग टॉपिक्स या टैग्स की गणना करने का सबसे अच्छा तरीका क्या है?


183

कई साइट कुछ आंकड़े पेश करती हैं जैसे "पिछले 24 घंटों में सबसे गर्म विषय"। उदाहरण के लिए, Topix.com अपने अनुभाग "समाचार रुझान" में यह दिखाता है। वहां, आप उन विषयों को देख सकते हैं जिनमें उल्लेखों की सबसे तेजी से बढ़ती संख्या है।

मैं एक विषय के लिए इस तरह के "बज़" की भी गणना करना चाहता हूं। मैं ये कैसे करूं? एल्गोरिदम को उन विषयों का वजन करना चाहिए जो हमेशा कम गर्म होते हैं। जिन विषयों में सामान्य रूप से (लगभग) दोपहर का उल्लेख होता है, वे सबसे गर्म होने चाहिए।

Google "हॉट ट्रेंड्स" प्रदान करता है, Topix.com "हॉट टॉपिक्स" दिखाता है, fav.or.it दिखाता है "कीवर्ड ट्रेंड्स" - इन सभी सेवाओं में एक चीज समान है: वे केवल आपको आगामी रुझान दिखाते हैं जो इस समय असामान्य रूप से गर्म हैं।

"ब्रिटनी स्पीयर्स", "वेदर" या "पेरिस हिल्टन" जैसी शर्तें इन सूचियों में दिखाई नहीं देंगी क्योंकि वे हमेशा गर्म और अक्सर होती हैं। यह लेख इसे "द ब्रिटनी स्पीयर्स प्रॉब्लम" कहता है।

मेरा प्रश्न: आप इस समस्या को हल करने के लिए एक एल्गोरिथ्म को कैसे कोड कर सकते हैं या किसी मौजूदा का उपयोग कर सकते हैं? अंतिम 24 घंटों में खोजे गए कीवर्ड के साथ एक सूची होने पर, एल्गोरिथ्म आपको 10 (उदाहरण के लिए) सबसे हॉट दिखाना चाहिए।

मुझे पता है, ऊपर के लेख में, कुछ प्रकार के एल्गोरिथ्म का उल्लेख किया गया है। मैंने इसे PHP में कोड करने की कोशिश की है, लेकिन मुझे नहीं लगता कि यह काम करेगा। यह सिर्फ बहुमत पाता है, है ना?

मुझे आशा है कि आप मेरी मदद कर सकते हैं (कोडिंग उदाहरण महान होंगे)।


4
दिलचस्प सवाल, यह देखने के लिए उत्सुक हैं कि लोगों को क्या कहना है।
mmcdole

14
बंद करने का कोई कारण नहीं, यह एक वैध प्रश्न है
TStamper

1
यह बिल्कुल वही सवाल है और वह यह भी कहता है कि! लोग इसे क्यों उखाड़ रहे हैं!
डेरिल हेन

3
मैं थोड़ा उलझन में हूं कि आप किस प्रकार के परिणाम की तलाश कर रहे हैं। लेख से संकेत मिलता है कि "ब्रिटनी स्पीयर्स" लगातार "हॉट" सूची में मिल जाएगी क्योंकि बहुत से लोग उस शब्द को खोजते हैं, लेकिन आपका प्रश्न बताता है कि यह सूची में दिखाई नहीं देगा क्योंकि उस शब्द के लिए खोज की संख्या है समय के साथ ज्यादा नहीं बढ़ा (वे उच्च, लेकिन स्थिर रहे)। आप किस परिणाम को प्राप्त करने की कोशिश कर रहे हैं? "ब्रिटनी स्पीयर्स" को उच्च या निम्न रैंक चाहिए?
e.James

1
@ जेम्स, "ब्रिटनी स्पीयर्स" को उच्च रैंक नहीं देना चाहिए क्योंकि वह लगातार उच्च खोज शब्द है और वह उच्च वेग के साथ खोज शब्दों की तलाश में है।
mmcdole

जवाबों:


103

यह समस्या एक z- स्कोर या मानक स्कोर के लिए कॉल करती है, जो ऐतिहासिक औसत को ध्यान में रखेगा, जैसा कि अन्य लोगों ने उल्लेख किया है, लेकिन इस ऐतिहासिक डेटा का मानक विचलन भी है, यह औसत का उपयोग करने की तुलना में अधिक मजबूत बनाता है।

आपके मामले में एक z- स्कोर की गणना निम्न सूत्र द्वारा की जाती है, जहां रुझान दर / दृश्य जैसे दिन होगा।

z-score = ([current trend] - [average historic trends]) / [standard deviation of historic trends]

जब z- स्कोर का उपयोग किया जाता है, तो z या स्कोर अधिक असामान्य प्रवृत्ति को कम करता है, इसलिए उदाहरण के लिए यदि z- स्कोर अत्यधिक सकारात्मक है, तो प्रवृत्ति असामान्य रूप से बढ़ रही है, जबकि यदि यह अत्यधिक नकारात्मक है तो यह असामान्य रूप से गिर रहा है । एक बार जब आप सभी उम्मीदवारों के रुझानों के लिए z- स्कोर की गणना करते हैं तो उच्चतम 10 z-स्कोर सबसे असामान्य रूप से बढ़ते हुए z- स्कोर से संबंधित होंगे।

कृपया अधिक जानकारी के लिए विकिपीडिया देखें, z- स्कोर के बारे में।

कोड

from math import sqrt

def zscore(obs, pop):
    # Size of population.
    number = float(len(pop))
    # Average population value.
    avg = sum(pop) / number
    # Standard deviation of population.
    std = sqrt(sum(((c - avg) ** 2) for c in pop) / number)
    # Zscore Calculation.
    return (obs - avg) / std

नमूना आउटपुट

>>> zscore(12, [2, 4, 4, 4, 5, 5, 7, 9])
3.5
>>> zscore(20, [21, 22, 19, 18, 17, 22, 20, 20])
0.0739221270955
>>> zscore(20, [21, 22, 19, 18, 17, 22, 20, 20, 1, 2, 3, 1, 2, 1, 0, 1])
1.00303599234
>>> zscore(2, [21, 22, 19, 18, 17, 22, 20, 20, 1, 2, 3, 1, 2, 1, 0, 1])
-0.922793112954
>>> zscore(9, [1, 2, 0, 3, 1, 3, 1, 2, 9, 8, 7, 10, 9, 5, 2, 4, 1, 1, 0])
1.65291949506

टिप्पणियाँ

  • यदि आप बहुत अधिक इतिहास को ध्यान में नहीं रखना चाहते हैं, तो आप इस पद्धति का उपयोग एक स्लाइडिंग विंडो (पिछले 30 दिनों में) के साथ कर सकते हैं, जो अल्पावधि रुझानों को अधिक स्पष्ट कर देगा और प्रसंस्करण समय में कटौती कर सकता है।

  • प्रति दिन बढ़ते / घटते विचारों के असामान्य मूल्यों का पता लगाने के लिए आप एक दिन से दूसरे दिन के विचारों में परिवर्तन जैसे मूल्यों के लिए एक z- स्कोर का उपयोग कर सकते हैं। यह प्रति दिन के ग्राफ़ के ढलान या व्युत्पन्न का उपयोग करने जैसा है।

  • यदि आप जनसंख्या के वर्तमान आकार, जनसंख्या के वर्तमान कुल और जनसंख्या के x ^ 2 के वर्तमान कुल का ध्यान रखते हैं, तो आपको इन मूल्यों को पुनर्गणना करने की आवश्यकता नहीं है, केवल उन्हें अपडेट करें और इसलिए आपको केवल इसकी आवश्यकता है इतिहास के लिए इन मूल्यों को रखें, प्रत्येक डेटा मूल्य नहीं। निम्न कोड यह प्रदर्शित करता है।

    from math import sqrt
    
    class zscore:
        def __init__(self, pop = []):
            self.number = float(len(pop))
            self.total = sum(pop)
            self.sqrTotal = sum(x ** 2 for x in pop)
        def update(self, value):
            self.number += 1.0
            self.total += value
            self.sqrTotal += value ** 2
        def avg(self):
            return self.total / self.number
        def std(self):
            return sqrt((self.sqrTotal / self.number) - self.avg() ** 2)
        def score(self, obs):
            return (obs - self.avg()) / self.std()
    
  • इस विधि का उपयोग करने से आपका कार्य प्रवाह इस प्रकार होगा। प्रत्येक विषय के लिए, टैग, या पेज एक फ्लोटिंग पॉइंट फ़ील्ड बनाते हैं, जो आपके डेटाबेस में कुल दिनों की संख्या, विचारों का योग और विचारों का योग है। यदि आपके पास ऐतिहासिक डेटा है, तो उस डेटा का उपयोग करके इन फ़ील्ड्स को इनिशियलाइज़ करें, अन्यथा शून्य पर इनिशियलाइज़ करें। प्रत्येक दिन के अंत में, तीन डेटाबेस फ़ील्ड में संग्रहीत ऐतिहासिक डेटा के विरुद्ध दिन के विचारों की संख्या का उपयोग करके z- स्कोर की गणना करें। उच्चतम X z- स्कोर वाले विषय, टैग या पृष्ठ, दिन के आपके X "हॉटेस्ट ट्रेंड" हैं। अंत में दिन के मूल्य के साथ 3 क्षेत्रों में से प्रत्येक को अपडेट करें और कल प्रक्रिया को दोहराएं।

नया जोड़

सामान्य z- स्कोर जैसा कि ऊपर चर्चा की गई है, डेटा के क्रम को ध्यान में नहीं रखते हैं और इसलिए '1' या '9' के अवलोकन के लिए z- स्कोर के अनुक्रम के विरुद्ध समान परिमाण होगा [1, 1, 1, 1 , ९, ९, ९, ९]। स्पष्ट रूप से प्रवृत्ति खोजने के लिए, सबसे वर्तमान डेटा में पुराने डेटा की तुलना में अधिक वजन होना चाहिए और इसलिए हम चाहते हैं कि '1' अवलोकन '9' अवलोकन की तुलना में बड़ा परिमाण स्कोर हो। इसे प्राप्त करने के लिए मैंने एक फ्लोटिंग औसत z- स्कोर का प्रस्ताव रखा। यह स्पष्ट होना चाहिए कि यह विधि सांख्यिकीय ध्वनि होने की गारंटी नहीं है, लेकिन प्रवृत्ति खोजने या समान के लिए उपयोगी होनी चाहिए। मानक z- स्कोर और फ्लोटिंग औसत z- स्कोर के बीच मुख्य अंतर औसत जनसंख्या मूल्य और औसत जनसंख्या मान की गणना के लिए एक फ्लोटिंग औसत का उपयोग है। विवरण के लिए कोड देखें:

कोड

class fazscore:
    def __init__(self, decay, pop = []):
        self.sqrAvg = self.avg = 0
        # The rate at which the historic data's effect will diminish.
        self.decay = decay
        for x in pop: self.update(x)
    def update(self, value):
        # Set initial averages to the first value in the sequence.
        if self.avg == 0 and self.sqrAvg == 0:
            self.avg = float(value)
            self.sqrAvg = float((value ** 2))
        # Calculate the average of the rest of the values using a 
        # floating average.
        else:
            self.avg = self.avg * self.decay + value * (1 - self.decay)
            self.sqrAvg = self.sqrAvg * self.decay + (value ** 2) * (1 - self.decay)
        return self
    def std(self):
        # Somewhat ad-hoc standard deviation calculation.
        return sqrt(self.sqrAvg - self.avg ** 2)
    def score(self, obs):
        if self.std() == 0: return (obs - self.avg) * float("infinity")
        else: return (obs - self.avg) / self.std()

नमूना IO

>>> fazscore(0.8, [1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, 9]).score(1)
-1.67770595327
>>> fazscore(0.8, [1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, 9]).score(9)
0.596052006642
>>> fazscore(0.9, [2, 4, 4, 4, 5, 5, 7, 9]).score(12)
3.46442230724
>>> fazscore(0.9, [2, 4, 4, 4, 5, 5, 7, 9]).score(22)
7.7773245459
>>> fazscore(0.9, [21, 22, 19, 18, 17, 22, 20, 20]).score(20)
-0.24633160155
>>> fazscore(0.9, [21, 22, 19, 18, 17, 22, 20, 20, 1, 2, 3, 1, 2, 1, 0, 1]).score(20)
1.1069362749
>>> fazscore(0.9, [21, 22, 19, 18, 17, 22, 20, 20, 1, 2, 3, 1, 2, 1, 0, 1]).score(2)
-0.786764452966
>>> fazscore(0.9, [1, 2, 0, 3, 1, 3, 1, 2, 9, 8, 7, 10, 9, 5, 2, 4, 1, 1, 0]).score(9)
1.82262469243
>>> fazscore(0.8, [40] * 200).score(1)
-inf

अपडेट करें

जैसा कि डेविड केम्प ने सही ढंग से कहा, यदि निरंतर मूल्यों की एक श्रृंखला दी जाती है और फिर एक मनाया मूल्य के लिए एक zscore जो अन्य मूल्यों से भिन्न होता है, तो अनुरोध किया जाता है कि परिणाम संभवतः गैर-शून्य होना चाहिए। वास्तव में लौटाया गया मूल्य अनंत होना चाहिए। इसलिए मैंने इस लाइन को बदल दिया,

if self.std() == 0: return 0

सेवा:

if self.std() == 0: return (obs - self.avg) * float("infinity")

यह परिवर्तन फ़ैज़कोर समाधान कोड में परिलक्षित होता है। यदि कोई अनंत मूल्यों से निपटना नहीं चाहता है, तो एक स्वीकार्य समाधान इसके बजाय लाइन को बदलने के लिए हो सकता है:

if self.std() == 0: return obs - self.avg

1
नहीं, आपके कोड में एक छोटी सी गलती है, निम्न पंक्ति पर। $ z_score = $ hits_today - ($ औसत_hits_per_day / $ standard_deviation); यह होना चाहिए: $ z_score = ($ hits_today- $ औसत_hits_per_day) / $ standard_deviation; कोष्ठक में परिवर्तन पर ध्यान दें।
निक्सुज

1
@nixuz - क्या मुझे कुछ याद आ रहा है: fazscore (0.8, मैप (लैम्ब्डा x: 40, रेंज (0,200)))। स्कोर (1) == 0 (किसी भी मान के लिए)?
k --e'mͮpͥ ͩ

1
@ निक्सस - सोचा था कि मैं इसे कब्र से खोद सकता हूं। क्या आप इस के PHP कार्यान्वयन को फिर से पोस्ट कर सकते हैं? pasteलिंक काम करने लगते हैं नहीं है ... धन्यवाद!
19

1
जो कोई भी इसे पसंद करेगा, मेरे पास अब ऐसा करने के लिए SQL क्वेरी है।
तूएलिहा

1
यहां क्षय काउंटर सहज है; यदि आप 2 मान दर्ज करते हैं, तो 0.8 के क्षय के साथ [10, 20] कहें, AVG 10 * 0.8 + 20 * 0.2 * 12 है। आप 15 से ऊपर के मूल्य की उम्मीद करेंगे, क्योंकि क्षय होने पर 20 का वजन 10 से अधिक होना चाहिए। वहाँ एक बहुत बेहतर विकल्प उपलब्ध है, जो कि आप वेट के साथ एक समानांतर सूची बनाते हैं। उदाहरण के लिए: डेटा = रेंज (10,30,10) का क्षय = 0.8 डेसीव्यूइट्स = [क्षय ** के लिए रेंज (लेन (डेटा), 0, -1) के लिए] प्रिंट np.aiture (डेटा, वज़न =ay_weights)
जीरो

93

आपको एक एल्गोरिथ्म की आवश्यकता होती है जो किसी विषय के वेग को मापता है - या दूसरे शब्दों में, यदि आप इसे ग्राफ करते हैं तो आप उन्हें दिखाना चाहते हैं जो अविश्वसनीय दर से बढ़ रहे हैं।

यह ट्रेंड लाइन का पहला व्युत्पन्न है, और यह आपके समग्र गणना के भारित कारक के रूप में शामिल करना मुश्किल नहीं है।

सामान्य

आपको अपनी एक तकनीक को अपने सभी डेटा को सामान्य करने की आवश्यकता होगी। आपके द्वारा अनुसरण किए जा रहे प्रत्येक विषय के लिए, बहुत कम पास वाला फ़िल्टर रखें जो उस विषय की आधार रेखा को परिभाषित करता है। अब उस विषय के बारे में आने वाले प्रत्येक डेटा बिंदु को सामान्य किया जाना चाहिए - इसकी आधार रेखा को घटाएं और आप अपने सभी विषयों को 0 के पास, लाइन के ऊपर और नीचे स्पाइक्स के साथ प्राप्त करेंगे। इसके बजाय आप सिग्नल को इसके बेसलाइन परिमाण द्वारा विभाजित करना चाह सकते हैं, जो सिग्नल को लगभग 1.0 तक लाएगा - यह न केवल सभी संकेतों को एक दूसरे के साथ लाइन में लाता है (बेसलाइन को सामान्य करता है), बल्कि स्पाइक्स को भी सामान्य करता है। एक ब्रिटनी स्पाइक किसी और के स्पाइक की तुलना में बड़ा होने वाला है, लेकिन इसका मतलब यह नहीं है कि आपको इस पर ध्यान देना चाहिए - स्पाइक उसके आधार रेखा के सापेक्ष बहुत छोटा हो सकता है।

निकाले जाते हैं

एक बार जब आप सब कुछ सामान्य कर लेते हैं, तो प्रत्येक विषय के ढलान का पता लगाएं। लगातार दो अंक लें, और अंतर को मापें। एक सकारात्मक अंतर चल रहा है, एक नकारात्मक अंतर नीचे चल रहा है। फिर आप सामान्यीकृत मतभेदों की तुलना कर सकते हैं, और यह पता लगा सकते हैं कि अन्य विषयों की तुलना में लोकप्रियता में कौन से विषय ऊपर की ओर शूटिंग कर रहे हैं - प्रत्येक विषय के लिए उपयुक्त है कि यह 'सामान्य' हो, जो अन्य विषयों से भिन्न क्रम का परिमाण हो।

यह वास्तव में समस्या का पहला पास है। अधिक उन्नत तकनीकें हैं, जिनका आपको उपयोग करने की आवश्यकता होगी (अधिकतर अन्य एल्गोरिदम के साथ उपरोक्त संयोजन, आपकी आवश्यकताओं के अनुरूप भारित) लेकिन यह आपको आरंभ करने के लिए पर्याप्त होना चाहिए।

लेख के बारे में

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

जैसा कि निक्सज़ बताते हैं कि इसे जेड या स्टैंडर्ड स्कोर भी कहा जाता है ।


1
मैंने इसे पहले संपादित किया, और वापस आ गया और मैं इसे फिर से बढ़ाना चाहता था! अच्छा काम
mmcdole

धन्यवाद! मैं छद्म कोड करूँगा, लेकिन मेरे पास अभी समय नहीं है। शायद बाद में, या शायद कोई और इन अवधारणाओं को ले जाएगा और इसे लागू करेगा ...
एडम डेविस

बहुत बहुत धन्यवाद, एडम डेविस! यदि निक्सुज़ ने वास्तव में ऐसा ही वर्णन किया है, तो मुझे लगता है कि मुझे PHP में एक समाधान मिला है: paste.bradleygill.com/index.php?paste_id=9206 क्या आपको लगता है कि यह कोड सही है?
कांव-कांव

क्या यह वेग के बजाय विषय का त्वरण नहीं होना चाहिए? पिछले जवाब की जाँच करें
एसएपी

17

चाड बर्च और एडम डेविस सही हैं कि आपको बेसलाइन स्थापित करने के लिए पीछे देखना होगा। आपका प्रश्न, जैसा कि वाक्यांशबद्ध है, सुझाव देता है कि आप केवल पिछले 24 घंटों से डेटा देखना चाहते हैं, और यह काफी उड़ नहीं पाएगा।

ऐतिहासिक डेटा के एक बड़े शरीर के लिए क्वेरी किए बिना अपने डेटा को कुछ मेमोरी देने का एक तरीका एक घातीय चलती औसत का उपयोग करना है इसका लाभ यह है कि आप इसे प्रति बार एक बार अपडेट कर सकते हैं और फिर सभी पुराने डेटा को फ्लश कर सकते हैं, इसलिए आपको केवल एक मूल्य याद रखना होगा। इसलिए यदि आपकी अवधि एक दिन है, तो आपको प्रत्येक विषय के लिए "दैनिक औसत" विशेषता बनाए रखनी होगी, जिसे आप निम्न कर सकते हैं:

a_n = a_(n-1)*b + c_n*(1-b)

a_nदिन के रूप में चलती औसत कहां है n, बी 0 और 1 के बीच कुछ स्थिर है (1 के करीब, लंबी मेमोरी) और c_nदिन पर हिट की संख्या है n। सुंदरता यह है कि यदि आप दिन के अंत में इस अपडेट को करते हैं n, तो आप फ्लश कर सकते हैं c_nऔर a_(n-1)

एक चेतावनी यह है कि आप अपने प्रारंभिक मूल्य के लिए जो भी चुनेंगे, वह शुरू में संवेदनशील होगा a

संपादित करें

यदि यह इस दृष्टिकोण की कल्पना करने में मदद करता है n = 5, तो a_0 = 1, और b = .9

मान लें कि नए मान 5,0,0,1,4 हैं:

a_0 = 1
c_1 = 5 : a_1 = .9*1 + .1*5 = 1.4
c_2 = 0 : a_2 = .9*1.4 + .1*0 = 1.26
c_3 = 0 : a_3 = .9*1.26 + .1*0 = 1.134
c_4 = 1 : a_4 = .9*1.134 + .1*1 = 1.1206
c_5 = 4 : a_5 = .9*1.1206 + .1*5 = 1.40854

औसत की तरह यह बहुत ज्यादा नहीं दिखता है? ध्यान दें कि हमारा अगला इनपुट 5 होने के बावजूद मान 1 के करीब कैसे रहा? यदि आप गणित का विस्तार करते हैं, तो आपको क्या मिलेगा:

a_n = (1-b)*c_n + (1-b)*b*c_(n-1) + (1-b)*b^2*c_(n-2) + ... + (leftover weight)*a_0

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

यदि आप उपरोक्त सूत्र का अध्ययन करते हैं, तो आपको इस उपयोग के बारे में कुछ बातों का एहसास होना चाहिए:

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

मुझे लगता है कि पहली दो विशेषताएं वही हैं जो आप देख रहे हैं। आपको इसे लागू करने के लिए सरल होने का एक विचार देना है, यहाँ एक अजगर कार्यान्वयन है (सभी डेटाबेस इंटरैक्शन माइनस):

>>> class EMA(object):
...  def __init__(self, base, decay):
...   self.val = base
...   self.decay = decay
...   print self.val
...  def update(self, value):
...   self.val = self.val*self.decay + (1-self.decay)*value
...   print self.val
... 
>>> a = EMA(1, .9)
1
>>> a.update(10)
1.9
>>> a.update(10)
2.71
>>> a.update(10)
3.439
>>> a.update(10)
4.0951
>>> a.update(10)
4.68559
>>> a.update(10)
5.217031
>>> a.update(10)
5.6953279
>>> a.update(10)
6.12579511
>>> a.update(10)
6.513215599
>>> a.update(10)
6.8618940391
>>> a.update(10)
7.17570463519

1
इसे अनंत आवेग प्रतिक्रिया फिल्टर (IIR)
एडम डेविस

अरे मेरे जवाब का एक बेहतर संस्करण।
जोशुआ

@ अदम सच? मैं उनसे परिचित नहीं हूँ। क्या यह एक IIR का विशेष मामला है? जिन लेखों पर मैं विचार कर रहा हूं, वे ऐसे सूत्र प्रदान नहीं करते हैं जो सरल मामले में एक घातीय चलती औसत को कम करते हैं।
डेविड बर्जर

बहुत बहुत धन्यवाद, डेविड बर्जर! यदि यह काम करता है, तो यह अन्य उत्तरों के लिए एक बढ़िया अतिरिक्त होगा! हालांकि मेरे कुछ सवाल हैं। मुझे आशा है कि आप उन्हें जवाब दे सकते हैं: 1) क्या कारक बी परिभाषित करता है कि पुराना डेटा तेजी से वजन कम कर रहा है? 2) क्या यह दृष्टिकोण पुराने डेटा को स्टोर करने और औसत की गणना करने की तुलना में लगभग समान परिणाम देगा? ३) क्या यह आपका सूत्र है शब्दों में? $ average_value = $ old_average_value * $ smoothing_factor + $ hits_today * (1 $ smoothing_factor)
कांव-कांव

अंक 1 और 3 सही हैं। 2 की एक बारीक चर्चा के लिए मेरा संपादन देखें।
डेविड बर्जर

8

आमतौर पर "बज़" को कुछ प्रकार के घातांक / लॉग क्षय तंत्र का उपयोग करके समझा जाता है। हैकर न्यूज, रेडिट और अन्य लोगों ने इसे कैसे सरल तरीके से हैंडल किया, इसके अवलोकन के लिए, इस पोस्ट को देखें ।

यह उन चीजों को पूरी तरह से संबोधित नहीं करता है जो हमेशा लोकप्रिय हैं। आप जो देख रहे हैं, वह Google के " हॉट ट्रेंड्स " फ़ीचर जैसा है । उसके लिए, आप वर्तमान मूल्य को एक ऐतिहासिक मूल्य से विभाजित कर सकते हैं और फिर उन लोगों को घटा सकते हैं जो कुछ शोर सीमा से नीचे हैं।


हां, Google का हॉट ट्रेंड वही है जिसकी मुझे तलाश है। ऐतिहासिक मूल्य क्या होना चाहिए? उदाहरण के लिए पिछले 7 दिनों का औसत मूल्य?
कांव-कांव

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

7

मुझे लगता है कि वे महत्वपूर्ण शब्द जो आपको नोटिस करने की आवश्यकता है "असामान्य रूप से" है। यह निर्धारित करने के लिए कि कब कुछ "असामान्य" है, आपको यह जानना होगा कि सामान्य क्या है। यही है, आपको ऐतिहासिक डेटा की आवश्यकता है, जिसे आप किसी विशेष क्वेरी की सामान्य दर का पता लगाने के लिए औसत कर सकते हैं। आप औसत गणना से असामान्य दिनों को बाहर करना चाह सकते हैं, लेकिन फिर से पहले से ही पर्याप्त डेटा रखने की आवश्यकता होगी, ताकि आप यह जान सकें कि किन दिनों को बाहर करना है।

वहां से, आपको एक थ्रेशोल्ड सेट करना होगा (जिसमें प्रयोग की आवश्यकता होगी, मुझे यकीन है), और अगर कुछ सीमा से बाहर जाता है, तो सामान्य से 50% अधिक खोजें, आप इसे "ट्रेंड" मान सकते हैं। या, यदि आप "टॉप एक्स ट्रेंडीएस्ट" का उल्लेख करने में सक्षम होना चाहते हैं, तो आपको बस चीजों को ऑर्डर करने की आवश्यकता है (प्रतिशत-वार) वे अपने सामान्य दर से दूर हैं।

उदाहरण के लिए, मान लें कि आपके ऐतिहासिक डेटा ने आपको बताया है कि ब्रिटनी स्पीयर्स को आमतौर पर 100,000 खोजें मिलती हैं, और पेरिस हिल्टन को आमतौर पर 50,000 मिलते हैं। यदि आपके पास एक दिन है, जहां वे दोनों सामान्य से 10,000 से अधिक खोज प्राप्त करते हैं, तो आपको ब्रिटनी की तुलना में पेरिस "हॉटटर" पर विचार करना चाहिए, क्योंकि उसकी खोजों में सामान्य से 20% अधिक वृद्धि हुई, जबकि ब्रिटनी केवल 10% थीं।

भगवान, मुझे विश्वास नहीं हो रहा है कि मैंने ब्रिटनी स्पीयर्स और पेरिस हिल्टन की "हॉटनेस" की तुलना करते हुए एक पैराग्राफ लिखा है। आपने मेरे साथ क्या किया?


धन्यवाद, लेकिन यह थोड़ा आसान होगा कि उन्हें सिर्फ उनकी आनुपातिक वृद्धि से ऑर्डर करना आसान होगा?
कांव-कांव

7

मैं सोच रहा था कि क्या इस तरह के मामले में नियमित भौतिकी त्वरण सूत्र का उपयोग करना संभव है?

v2-v1/t or dv/dt

हम पिछले 24 घंटों में v1 को प्रारंभिक पसंद / वोट / प्रति-टिप्पणी-प्रति घंटा और v2 को वर्तमान "वेग" प्रति घंटा होने पर विचार कर सकते हैं?

यह उत्तर की तुलना में अधिक प्रश्न जैसा है, लेकिन ऐसा लगता है कि यह सिर्फ काम कर सकता है। उच्चतम त्वरण वाली कोई भी सामग्री ट्रेंडिंग टॉपिक होगी ...

मुझे यकीन है कि यह ब्रिटनी स्पीयर्स समस्या का समाधान नहीं हो सकता है :-)


यह काम करेगा, क्योंकि यह केवल वोट की गणना करता है / प्रति समय वृद्धि की तरह, और यही हमें चाहिए। यह भागों में "ब्रिटनी स्पीयर्स समस्या" को हल कर सकता है क्योंकि इस खोज शब्द में हमेशा एक उच्च v1होता है और v2"ट्रेंडिंग" माना जाने के लिए बहुत अधिक आवश्यकता होगी । हालांकि, ऐसा करने के लिए बेहतर और अधिक परिष्कृत सूत्र और एल्गोरिदम हैं। फिर भी, यह एक बुनियादी काम करने का उदाहरण है।
कांव-कांव

एक संदर्भ में जहां आपको "ट्रेंडिंग" फ़ीड में हमेशा कुछ होना चाहिए, यह एकदम सही है। एक एक्सप्लोर टैब जैसा कुछ है जहां आप सूचीबद्ध करते हैं कि अभी प्लेटफ़ॉर्म पर सबसे अच्छा क्या है। एक अलग एल्गो का उपयोग करके, आप एक खाली परिणाम सेट कर सकते हैं।
किलियनक

5

शायद विषय आवृत्ति का एक सरल ढाल काम करेगा - बड़ी सकारात्मक ढाल = लोकप्रियता में तेजी से बढ़ रहा है।

सबसे आसान तरीका यह होगा कि आप हर दिन सर्च किए जाने वाले नंबर को बिन करें, इसलिए आपको कुछ पसंद है

searches = [ 10, 7, 14, 8, 9, 12, 55, 104, 100 ]

और फिर पता करें कि यह दिन-प्रतिदिन कितना बदल गया:

hot_factor = [ b-a for a, b in zip(searches[:-1], searches[1:]) ]
# hot_factor is [ -3, 7, -6, 1, 3, 43, 49, -4 ]

और बस थोड़े दिनों के लिए लागू करें ताकि उन दिनों में जहां वृद्धि हुई थी> 50 को 'हॉट' माना जाता है। यदि आप चाहें, तो आप इसे और अधिक जटिल बना सकते हैं। पूर्ण अंतर के बजाय आप सापेक्ष अंतर ले सकते हैं ताकि 100 से 150 तक जाना गर्म माना जाता है, लेकिन 1000 से 1050 तक नहीं। या एक अधिक जटिल ढाल जो खाते के रुझानों को अगले एक दिन से अधिक समय तक ध्यान में रखता है।


धन्यवाद। लेकिन मुझे ठीक से पता नहीं है कि एक ढाल क्या है और मैं इसके साथ कैसे काम कर सकता हूं। माफ़ करना!
caw

धन्यवाद। तो मैं एक वेक्टर बनाया है जिसमें दैनिक आवृत्ति, सही है? सापेक्ष मूल्य बेहतर होंगे, मुझे यकीन है। उदाहरण: १०० से ११० तक की वृद्धि १ से ९ की वृद्धि जितनी अच्छी नहीं है, मैं कहूंगा। लेकिन क्या कोई वेक्टर फ़ंक्शन नहीं है जिसका उपयोग मैं सबसे गर्म विषयों को खोजने के लिए कर सकता हूं? केवल सापेक्ष मूल्यों का मूल्यांकन ही पर्याप्त नहीं होगा, है ना? 100 से 200 की वृद्धि (100%) 20,000 से 39,000 तक की वृद्धि के रूप में अच्छी नहीं है !?
caw

आप इसे किस तरह की वेब साइट से जोड़ रहे हैं? @ ऑटोप्लेक्टिक का सुझाव दिन-प्रतिदिन खोजों में परिवर्तन को गिनने के लिए एक लोकप्रिय मंच की तरह कुछ नहीं होगा, जहां आपके पास हर दिन परिभाषित होने वाले नए विषयों के हजारों विषय हैं।
क्वांटम 7

आप सही हैं, मुझे प्रति घंटे हजारों विषयों के लिए भारी मात्रा में डेटा की आवश्यकता है।
कांव-कांव

यह एक खराब रणनीति है। इस तरह, ब्रिटनी स्पीयर्स के बारे में 50 खोजों की कुल वृद्धि यूरोप में एक नए जनमत संग्रह के बारे में +50 खोजों के रूप में गर्म है।
इमान अकबरी

4

मैंने एक प्रोजेक्ट पर काम किया था, जहां मेरा उद्देश्य लाइव ट्विटर स्ट्रीम से ट्रेंडिंग टॉपिक्स ढूंढ रहा था और ट्रेंडिंग टॉपिक्स पर भी भावुक विश्लेषण कर रहा था (यदि ट्रेंडिंग टॉपिक पॉजिटिव / नेगेटिवली बात की जाए तो)। मैंने ट्विटर स्ट्रीम को संभालने के लिए स्टॉर्म का इस्तेमाल किया है।

मैंने अपनी रिपोर्ट एक ब्लॉग के रूप में प्रकाशित की है: http://sayrohan.blogspot.com/2013/06/finding-trending-topics-and-trending.html

मैंने रैंकिंग के लिए कुल गणना और जेड-स्कोर का उपयोग किया है।

जिस दृष्टिकोण का मैंने उपयोग किया है वह थोड़ा सामान्य है, और चर्चा अनुभाग में, मैंने उल्लेख किया है कि हम गैर-ट्विटर एप्लिकेशन के लिए सिस्टम का विस्तार कैसे कर सकते हैं।

आशा है कि जानकारी से मदद मिलेगी।


3

यदि आप अपने विषयों को प्राप्त करने के लिए बस ट्वीट्स, या स्टेटस मैसेज देखते हैं, तो आप बहुत शोर मचा सकते हैं। भले ही आप सभी स्टॉप शब्द हटा दें। विषय उम्मीदवारों का एक बेहतर सबसेट पाने का एक तरीका केवल ट्वीट्स / संदेशों पर ध्यान केंद्रित करना है जो एक यूआरएल साझा करते हैं, और उन वेब पेजों के शीर्षक से कीवर्ड प्राप्त करते हैं। और सुनिश्चित करें कि आप संज्ञाएं + संज्ञा वाक्यांश प्राप्त करने के लिए पीओएस टैगिंग लागू करते हैं।

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

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


2

आप अंतिम तिथि या वर्ष के साथ वर्तमान तिथि की तुलना करने के लिए लॉग-लाइबिलिटी-अनुपात का उपयोग कर सकते हैं। यह सांख्यिकीय रूप से ध्वनि है (यह देखते हुए कि आपकी घटनाओं को आम तौर पर वितरित नहीं किया जाता है, जिसे आपके प्रश्न से माना जाता है)।

बस logLR द्वारा अपनी सभी शर्तों को क्रमबद्ध करें और शीर्ष दस चुनें।

public static void main(String... args) {
    TermBag today = ...
    TermBag lastYear = ...
    for (String each: today.allTerms()) {
        System.out.println(logLikelihoodRatio(today, lastYear, each) + "\t" + each);
    }
} 

public static double logLikelihoodRatio(TermBag t1, TermBag t2, String term) {
    double k1 = t1.occurrences(term); 
    double k2 = t2.occurrences(term); 
    double n1 = t1.size(); 
    double n2 = t2.size(); 
    double p1 = k1 / n1;
    double p2 = k2 / n2;
    double p = (k1 + k2) / (n1 + n2);
    double logLR = 2*(logL(p1,k1,n1) + logL(p2,k2,n2) - logL(p,k1,n1) - logL(p,k2,n2));
    if (p1 < p2) logLR *= -1;
    return logLR;
}

private static double logL(double p, double k, double n) {
    return (k == 0 ? 0 : k * Math.log(p)) + ((n - k) == 0 ? 0 : (n - k) * Math.log(1 - p));
}

पुनश्च, एक टर्मबाग शब्दों का एक अनियंत्रित संग्रह है। प्रत्येक दस्तावेज़ के लिए आप शर्तों का एक बैग बनाते हैं। बस शब्दों की घटनाओं को गिनें। तब विधि occurrencesकिसी दिए गए शब्द की घटनाओं की संख्या लौटाती है, और विधि sizeशब्दों की कुल संख्या को वापस करती है। किसी भी तरह शब्दों को सामान्य करना सबसे अच्छा है, आमतौर पर toLowerCaseयह काफी अच्छा है। बेशक, उपरोक्त उदाहरणों में आप आज के सभी प्रश्नों के साथ एक दस्तावेज बनाएंगे, और पिछले साल के सभी प्रश्नों के साथ।


क्षमा करें, मुझे कोड समझ में नहीं आ रहा है। TermBags क्या हैं? यह बहुत अच्छा होगा यदि आप शीघ्र ही समझा सकते हैं कि यह कोड क्या करता है।
कांव-कांव

1
एक टर्मबाग शब्दों का एक बैग है, अर्थात कक्षा को पाठ में शब्दों की कुल संख्या और प्रत्येक शब्द के लिए घटनाओं की संख्या का जवाब देने में सक्षम होना चाहिए।
आकुहन

0

यह विचार ऐसी चीजों और सूचनाओं पर नज़र रखने का है, जब वे अपनी आधार रेखा की तुलना में महत्वपूर्ण रूप से कूदते हैं।

इसलिए, एक निश्चित सीमा से अधिक वाले प्रश्नों के लिए, प्रत्येक को ट्रैक करें और जब यह अपने ऐतिहासिक मूल्य के कुछ मूल्य (लगभग दोगुना) में बदल जाए, तो यह एक नया हॉट ट्रेंड है।

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