วิธีที่ดีที่สุดในการคำนวณหัวข้อหรือแท็กมีแนวโน้มคืออะไร


183

เว็บไซต์หลายแห่งมีสถิติเช่น "หัวข้อที่ร้อนแรงที่สุดใน 24 ชั่วโมงที่ผ่านมา" ตัวอย่างเช่น Topix.com แสดงสิ่งนี้ในส่วน "แนวโน้มข่าว" ที่นั่นคุณสามารถดูหัวข้อที่มีจำนวนการกล่าวถึงที่เติบโตเร็วที่สุด

ฉันต้องการคำนวณ "Buzz" สำหรับหัวข้อด้วย ฉันจะทำสิ่งนี้ได้อย่างไร อัลกอริทึมควรน้ำหนักหัวข้อที่ร้อนน้อยกว่าเสมอ หัวข้อที่ปกติ (เกือบ) ไม่มีใครพูดถึงควรเป็นหัวข้อที่ร้อนแรงที่สุด

Google เสนอ "แนวโน้มร้อนแรง", topix.com แสดง "หัวข้อน่าสนใจ", fav.or.it แสดง "แนวโน้มคำหลัก" - บริการทั้งหมดมีสิ่งหนึ่งที่เหมือนกัน: พวกเขาจะแสดงเฉพาะแนวโน้มที่กำลังมาถึงซึ่งกำลังร้อนแรงอย่างผิดปกติในขณะนี้

คำเช่น "Britney Spears", "weather" หรือ "Paris Hilton" จะไม่ปรากฏในรายการเหล่านี้เพราะพวกเขามักจะร้อนและบ่อยครั้ง บทความนี้เรียกสิ่งนี้ว่า "ปัญหาของ Britney Spears"

คำถามของฉัน: คุณจะเขียนอัลกอริทึมหรือใช้วิธีที่มีอยู่เพื่อแก้ปัญหานี้ได้อย่างไร มีรายการที่มีคำค้นหาใน 24 ชั่วโมงล่าสุดอัลกอริทึมควรแสดง 10 สุด (ตัวอย่าง) สุดร้อนแรง

ฉันรู้ว่าในบทความข้างต้นมีอัลกอริทึมบางชนิดที่กล่าวถึง ฉันพยายามเขียนมันใน PHPแต่ฉันไม่คิดว่ามันจะใช้งานได้ มันเพิ่งพบคนส่วนใหญ่ใช่ไหม?

ฉันหวังว่าคุณสามารถช่วยฉัน (ตัวอย่างการเข้ารหัสจะดีมาก)


4
คำถามที่น่าสนใจอยากรู้อยากเห็นที่คนพูด
mmcdole

14
เหตุผลที่จะใกล้ชิดไม่มีนี้เป็นคำถามที่ถูกต้อง
TStamper

1
นี่เป็นคำถามเดียวกันทั้งหมดและเขายังระบุด้วยว่า! ทำไมผู้คนถึงสนใจมัน!
Darryl Hein

3
ฉันสับสนเล็กน้อยเกี่ยวกับผลลัพธ์ประเภทใดที่คุณกำลังมองหา ดูเหมือนว่าบทความจะระบุว่า "Britney Spears" จะพบอย่างต่อเนื่องในรายการ "ร้อน" เพราะมีผู้ค้นหาคำดังกล่าวจำนวนมาก แต่คำถามของคุณระบุว่าจะไม่ปรากฏในรายการเนื่องจากจำนวนการค้นหาคำนั้นทำ ไม่เพิ่มมากขึ้นเมื่อเวลาผ่านไป (พวกเขายังคงสูง แต่มั่นคง) ผลลัพธ์แบบใดที่คุณพยายามทำให้สำเร็จ "Britney Spears" ควรจัดอันดับสูงหรือต่ำหรือไม่
e.James

1
@eJames "Britney Spears" ไม่ควรอยู่ในอันดับสูงเพราะเธอเป็นคำค้นหาที่สูงและเขากำลังมองหาคำค้นหาที่มีความเร็วสูง
mmcdole

คำตอบ:


103

ปัญหานี้เรียกร้องให้มีคะแนน z หรือคะแนนมาตรฐานซึ่งจะคำนึงถึงค่าเฉลี่ยในอดีตเช่นเดียวกับคนอื่น ๆ ที่พูดถึง แต่ยังรวมถึงค่าเบี่ยงเบนมาตรฐานของข้อมูลประวัตินี้ทำให้แข็งแกร่งกว่าการใช้ค่าเฉลี่ย

ในกรณีของคุณคะแนน z คำนวณโดยสูตรต่อไปนี้โดยที่แนวโน้มจะเป็นอัตราเช่นจำนวนการดู / วัน

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

เมื่อใช้คะแนน z คะแนน z สูงกว่าหรือต่ำกว่าจะมีแนวโน้มที่ผิดปกติมากขึ้นตัวอย่างเช่นถ้าคะแนน z เป็นบวกสูงจากนั้นแนวโน้มจะเพิ่มขึ้นอย่างผิดปกติในขณะที่ถ้ามันเป็นลบมากมันจะล้มลงอย่างผิดปกติ . ดังนั้นเมื่อคุณคำนวณคะแนน z สำหรับแนวโน้มผู้สมัครคะแนนสูงสุด 10 คะแนนจะเกี่ยวข้องกับคะแนน 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()
    
  • การใช้วิธีนี้กระบวนการทำงานของคุณจะเป็นดังนี้ สำหรับแต่ละหัวข้อแท็กหรือหน้าสร้างเขตข้อมูลทศนิยมสำหรับจำนวนวันรวมผลรวมของการดูและผลรวมของการดู squared ในฐานข้อมูลของคุณ หากคุณมีข้อมูลประวัติให้เริ่มต้นฟิลด์เหล่านี้โดยใช้ข้อมูลนั้นมิฉะนั้นเริ่มต้นเป็นศูนย์ ในตอนท้ายของแต่ละวันให้คำนวณคะแนน z โดยใช้จำนวนการดูต่อวันกับข้อมูลในอดีตที่เก็บไว้ในฐานข้อมูลสามฟิลด์ หัวข้อแท็กหรือหน้าเว็บที่มีคะแนน X สูงสุดคือ X "เทรนด์ยอดนิยม" ประจำวันของคุณ ในที่สุดอัพเดตแต่ละฟิลด์ 3 ฟิลด์ด้วยค่าของวันและทำซ้ำกระบวนการในวันพรุ่งนี้

ใหม่เพิ่มเติม

คะแนน z ปกติตามที่กล่าวข้างต้นไม่คำนึงถึงลำดับของข้อมูลและด้วยเหตุนี้คะแนน z สำหรับการสังเกต '1' หรือ '9' จะมีขนาดเท่ากันกับลำดับ [1, 1, 1, 1 , 9, 9, 9, 9] เห็นได้ชัดว่าสำหรับการค้นหาแนวโน้มข้อมูลล่าสุดควรมีน้ำหนักมากกว่าข้อมูลเก่าและด้วยเหตุนี้เราต้องการให้การสังเกต '1' มีคะแนนขนาดใหญ่กว่าการสังเกต '9' เพื่อให้บรรลุนี้ฉันเสนอคะแนนเฉลี่ยลอยตัว ควรมีความชัดเจนว่าวิธีการนี้ไม่รับประกันว่าจะมีความชัดเจนทางสถิติ แต่ควรมีประโยชน์สำหรับการค้นหาแนวโน้มหรือคล้ายกัน ข้อแตกต่างที่สำคัญระหว่างคะแนน 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")

การเปลี่ยนแปลงนี้มีผลในรหัสโซลูชัน fazscore หากไม่มีใครต้องการจัดการกับค่าอนันต์โซลูชันที่ยอมรับได้อาจเปลี่ยนบรรทัดเป็น:

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

1
ไม่รหัสของคุณมีข้อผิดพลาดเล็กน้อยในบรรทัดต่อไปนี้ $ z_score = $ hits_today - ($ average_hits_per_day / $ standard_deviation); มันควรจะเป็น: $ z_score = ($ hits_today- $ average_hits_per_day) / $ standard_deviation; บันทึกการเปลี่ยนแปลงในวงเล็บ
Nixuz

1
@nixuz - ฉันพลาดอะไรไป: fazscore (0.8, map (lambda x: 40, range (0,200))). score (1) == 0 (สำหรับค่าใด ๆ )?
kͩeͣmͮpͥͩ

1
@Nixus - คิดว่าฉันอาจขุดมันขึ้นมาจากหลุมศพ คุณสามารถโพสต์การติดตั้ง PHP ใหม่ได้หรือไม่ pasteการเชื่อมโยงไม่ได้ดูเหมือนจะทำงาน ... ขอบคุณ!
Drewness

1
สำหรับผู้ที่ต้องการฉันตอนนี้มีแบบสอบถาม SQL ที่จะทำ
yeliha

1
การสลายตัวที่นี่เป็นเรื่องง่าย หากคุณต้องการป้อนค่า 2 ค่าให้พูดว่า [10, 20] ด้วยการสลายตัวของ 0.8, AVG คือ 10 * 0.8 + 20 * 0.2 = 12 คุณคาดหวังว่าค่าที่สูงกว่า 15 เนื่องจาก 20 ควรมีน้ำหนักมากกว่า 10 หากมีการสลายตัว มีทางเลือกที่ดีกว่ามากโดยใช้ค่าเฉลี่ยถ่วงน้ำหนักเป็น numpy.average ซึ่งคุณสร้างรายการแบบขนานพร้อมน้ำหนัก ตัวอย่างเช่น: data = range (10,30,10) decay = 0.8 decay_weights = [decay ** a สำหรับ a in a range (len (data), 0, -1)] print np.average (ข้อมูลน้ำหนัก = decay_weights)
Jeroen

93

คุณต้องการอัลกอริทึมที่วัดความเร็วของหัวข้อ - หรือกล่าวอีกนัยหนึ่งถ้าคุณวาดกราฟคุณต้องการแสดงให้เห็นว่ากำลังเกิดขึ้นในอัตราที่เหลือเชื่อ

นี่คืออนุพันธ์อันดับแรกของเส้นแนวโน้มและไม่ยากที่จะรวมเป็นปัจจัยถ่วงน้ำหนักของการคำนวณโดยรวมของคุณ

ปกติ

เทคนิคหนึ่งที่คุณต้องทำคือทำให้ข้อมูลทั้งหมดของคุณเป็นปกติ สำหรับแต่ละหัวข้อที่คุณติดตามให้ใช้ตัวกรองผ่านต่ำมากซึ่งกำหนดพื้นฐานของหัวข้อนั้น ตอนนี้ทุกจุดข้อมูลที่มาในหัวข้อนั้นควรจะเป็นมาตรฐาน - ลบพื้นฐานและคุณจะได้รับหัวข้อทั้งหมดของคุณใกล้ 0 ด้วยเดือยแหลมด้านบนและด้านล่างบรรทัด คุณอาจต้องการแบ่งสัญญาณตามขนาดพื้นฐานของมันซึ่งจะทำให้สัญญาณอยู่ที่ประมาณ 1.0 - นี่ไม่เพียง แต่นำสัญญาณทั้งหมดให้สอดคล้องกัน (ทำให้พื้นฐานปกติ) แต่ยังทำให้เดือยกลับสู่ปกติ เข็มบริทนีย์จะมีขนาดใหญ่กว่าเข็มของคนอื่น แต่นั่นไม่ได้หมายความว่าคุณควรให้ความสนใจกับมัน - เข็มอาจจะมีขนาดเล็กมากเมื่อเทียบกับพื้นฐานของเธอ

การสืบทอดมา

เมื่อคุณทำทุกอย่างให้เป็นมาตรฐานแล้วให้หาความชันของแต่ละหัวข้อ รับสองคะแนนติดต่อกันและวัดความแตกต่าง ความแตกต่างเชิงบวกคือแนวโน้มขึ้นความแตกต่างเชิงลบคือแนวโน้ม จากนั้นคุณสามารถเปรียบเทียบความแตกต่างที่เป็นมาตรฐานและค้นหาว่าหัวข้อใดมีการถ่ายภาพที่ได้รับความนิยมสูงขึ้นเมื่อเทียบกับหัวข้ออื่น ๆ - โดยแต่ละหัวข้อจะปรับให้เหมาะสมกับ 'ปกติ' ของตัวเอง

นี่เป็นครั้งแรกที่ปัญหา มีเทคนิคขั้นสูงเพิ่มเติมที่คุณจะต้องใช้ (ส่วนใหญ่เป็นการรวมกันของข้างต้นกับอัลกอริทึมอื่น ๆ , ถ่วงน้ำหนักเพื่อให้เหมาะกับความต้องการของคุณ) แต่มันควรจะเพียงพอที่จะเริ่มต้น

เกี่ยวกับบทความ

บทความนี้เกี่ยวกับแนวโน้มหัวข้อ แต่ไม่เกี่ยวกับวิธีการคำนวณว่ามีอะไรน่าสนใจและไม่เป็นอย่างไรเป็นเรื่องเกี่ยวกับวิธีการประมวลผลข้อมูลจำนวนมากที่อัลกอริทึมดังกล่าวต้องดำเนินการในสถานที่เช่น Lycos และ Google พื้นที่และเวลาที่ต้องใช้เพื่อให้ตัวนับแต่ละหัวข้อและค้นหาตัวนับของแต่ละหัวข้อเมื่อการค้นหานั้นผ่านไปมาก บทความนี้เป็นเรื่องเกี่ยวกับความท้าทายที่ใบหน้าประสบเมื่อพยายามทำงานดังกล่าว มันพูดถึงเอฟเฟ็กต์ Brittney แต่มันไม่ได้พูดถึงวิธีเอาชนะมัน

ในฐานะที่เป็นจุด Nixuz ออกนี้ยังเรียกว่าเป็น Z หรือคะแนนมาตรฐาน


1
ฉัน upvote นี้ก่อนการแก้ไขและกลับมาและฉันต้องการ upvote อีกครั้ง! เป็นงานที่ดี
mmcdole

ขอบคุณ! ฉันจะทำรหัสหลอก แต่ตอนนี้ฉันไม่มีเวลา บางทีในภายหลังหรืออาจจะเป็นคนอื่นที่จะนำแนวคิดเหล่านี้และใช้มัน ...
อดัมเดวิส

ขอบคุณมาก Adam Davis! ถ้า Nixuz อธิบายเหมือนกันฉันคิดว่าฉันมีทางออกใน PHP: paste.bradleygill.com/index.php?paste_id=9206คุณคิดว่ารหัสนี้ถูกต้องหรือไม่
caw

ไม่ควรเป็นการเร่งความเร็วของหัวข้อแทนที่จะเป็นความเร็วใช่หรือไม่ ตรวจสอบคำตอบสุดท้าย
Sap

17

ชาดเบิร์ชและอดัมเดวิสนั้นถูกต้องซึ่งคุณจะต้องมองย้อนกลับไปเพื่อสร้างพื้นฐาน คำถามของคุณแสดงให้เห็นว่าคุณต้องการดูข้อมูลจาก 24 ชั่วโมงที่ผ่านมาเท่านั้นและนั่นไม่ใช่เรื่องง่าย

วิธีหนึ่งในการให้หน่วยความจำข้อมูลของคุณโดยไม่ต้องค้นหาข้อมูลในอดีตที่มีขนาดใหญ่คือการใช้ค่าเฉลี่ยเคลื่อนที่ชี้แจง ข้อดีของการทำเช่นนี้คือคุณสามารถอัปเดตข้อมูลนี้ได้หนึ่งครั้งต่อรอบระยะเวลาจากนั้นจึงล้างข้อมูลเก่าทั้งหมดดังนั้นคุณจะต้องจำเพียงค่าเดียวเท่านั้น ดังนั้นหากช่วงเวลาของคุณเป็นวันคุณต้องรักษาแอตทริบิวต์ "ค่าเฉลี่ยรายวัน" สำหรับแต่ละหัวข้อซึ่งคุณสามารถทำได้โดย:

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

ที่ไหน a_nจะค่าเฉลี่ยเคลื่อนที่ ณ วันn, B เป็นค่าคงที่บางอย่างระหว่าง 0 และ 1 (ใกล้ชิดกับ 1 อีกต่อไปหน่วยความจำ) และเป็นจำนวนของการเข้าชมในวันที่c_n nความงามคือถ้าคุณดำเนินการปรับปรุงนี้ในตอนท้ายของวันที่nคุณสามารถล้างและc_na_(n-1)

หนึ่งข้อแม้คือว่ามันจะไวต่อสิ่งที่คุณเลือกสำหรับค่าเริ่มต้นของaคุณ

แก้ไข

หากช่วยให้เห็นภาพวิธีการนี้ได้ n = 5 , และa_0 = 1b = .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

ดูไม่เหมือนค่าเฉลี่ยเลยเหรอ? สังเกตว่าค่าอยู่ใกล้กับ 1 ถึงแม้ว่าอินพุตต่อไปของเราคือ 5 เกิดอะไรขึ้น ถ้าคุณขยายคณิตศาสตร์สิ่งที่คุณจะได้รับคือ:

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. ค่า b ที่สูงกว่าค่าใหม่ที่สำคัญน้อยกว่าและค่าเก่าที่ยาวกว่าจะสำคัญ อย่างไรก็ตาม b ที่สูงกว่าคือข้อมูลที่คุณต้องใช้ในการเริ่มต้น a

ฉันคิดว่าสองคุณสมบัติแรกนั้นเป็นสิ่งที่คุณต้องการอย่างแท้จริง เพื่อให้คุณเข้าใจง่ายว่าสามารถนำไปใช้งานได้นี่คือการนำ python มาใช้ (ลบการโต้ตอบกับฐานข้อมูลทั้งหมด):

>>> 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)
Adam Davis

เฮ้รุ่นที่ดีกว่าของคำตอบของฉัน
Joshua

@Adam จริงเหรอ? ฉันไม่คุ้นเคยกับพวกเขา เป็นกรณีพิเศษของ IIR หรือไม่? บทความที่ฉันอ่านไม่ออกดูเหมือนจะไม่ได้จัดทำสูตรที่ลดลงไปเป็นค่าเฉลี่ยเคลื่อนที่ชี้แจงในกรณีที่ง่าย
David Berger

ขอบคุณมากเดวิดเบอร์เกอร์! ถ้าได้ผลมันจะเป็นคำตอบที่ดีสำหรับคำตอบอื่น ๆ ! ฉันมีคำถามบางอย่าง ฉันหวังว่าคุณจะสามารถตอบคำถามเหล่านี้ได้: 1) ปัจจัย b กำหนดว่าข้อมูลเก่าลดน้ำหนักได้เร็วแค่ไหน? 2) วิธีการนี้จะให้ผลลัพธ์ที่เทียบเท่าโดยประมาณเมื่อเทียบกับเพียงแค่เก็บข้อมูลเก่าและคำนวณค่าเฉลี่ยหรือไม่ 3) นี่เป็นสูตรของคุณในคำหรือเปล่า? $ average_value = $ old_average_value * $ smoothing_factor + $ hits_today * (1- $ smoothing_factor)
caw

คะแนน 1 และ 3 ถูกต้อง ดูการแก้ไขของฉันสำหรับการสนทนาที่เหมาะสมยิ่งของ 2
เดวิดเบอร์เกอร์

8

โดยทั่วไป "buzz" สามารถหาได้โดยใช้กลไกการสลายตัวแบบเอ็กซ์โปเนนเชียล / ล็อก สำหรับภาพรวมของวิธีการของ Hacker News, Reddit และอื่น ๆ ที่จัดการสิ่งนี้ในวิธีที่ง่ายดูโพสต์นี้นี้

สิ่งนี้ไม่ได้กล่าวถึงสิ่งที่เป็นที่นิยมเสมอ สิ่งที่คุณกำลังมองหาดูเหมือนจะเป็นคุณสมบัติ " แนวโน้มยอดนิยม " ของ Google สำหรับสิ่งนั้นคุณสามารถหารค่าปัจจุบันด้วยค่าประวัติแล้วลบค่าที่ต่ำกว่าเกณฑ์จุดรบกวน


ใช่ Google Hot Trends เป็นสิ่งที่ฉันกำลังมองหา คุณค่าทางประวัติศาสตร์ควรเป็นอย่างไร ตัวอย่างเช่นค่าเฉลี่ยของ 7 วันล่าสุด?
caw

1
ขึ้นอยู่กับความผันผวนของข้อมูลของคุณ คุณสามารถเริ่มต้นด้วยค่าเฉลี่ย 30 วัน ถ้ามันเป็นวัฏจักร (เช่น Kentucky Derby) มันอาจสมเหตุสมผลที่จะทำการเปรียบเทียบรายปี ฉันจะทดสอบและดูว่าอะไรดีที่สุดในการปฏิบัติ
46490 Jeff Moser

7

ฉันคิดว่าพวกเขาคำสำคัญที่คุณต้องสังเกตคือ "ผิดปกติ" ในการพิจารณาว่าบางสิ่งบางอย่าง "ผิดปกติ" คุณต้องรู้ว่าอะไรเป็นปกติ นั่นคือคุณจะต้องมีข้อมูลประวัติซึ่งคุณสามารถหาค่าเฉลี่ยเพื่อหาอัตราปกติของข้อความค้นหาหนึ่ง ๆ คุณอาจต้องการยกเว้นวันที่ผิดปกติจากการคำนวณค่าเฉลี่ย แต่อีกครั้งที่จะต้องมีข้อมูลเพียงพอแล้วเพื่อให้คุณรู้ว่าจะต้องแยกวันใด

จากตรงนั้นคุณจะต้องตั้งค่าขีด จำกัด (ซึ่งจะต้องมีการทดสอบฉันแน่ใจ) และหากมีบางสิ่งที่อยู่นอกเกณฑ์การค้นหามากกว่าปกติ 50% คุณสามารถพิจารณาว่าเป็น "แนวโน้ม" หรือถ้าคุณต้องการที่จะหา "Top X Trendiest" ตามที่คุณกล่าวถึงคุณเพียงแค่ต้องสั่งซื้อสิ่งต่าง ๆ โดยที่พวกเขาอยู่ห่างจากอัตราปกติเท่าไร

ตัวอย่างเช่นสมมติว่าข้อมูลในอดีตของคุณบอกคุณว่า Britney Spears มักจะได้รับการค้นหา 100,000 ครั้งและ Paris Hilton จะได้รับ 50,000 หากคุณมีวันที่ทั้งคู่ได้รับการค้นหามากกว่า 10,000 ครั้งคุณควรพิจารณาปารีส "ร้อนแรง" มากกว่า Britney เพราะการค้นหาของเธอเพิ่มขึ้นมากกว่าปกติ 20% ในขณะที่ Britney มีเพียง 10%

พระเจ้าฉันไม่อยากจะเชื่อเลยว่าฉันเพิ่งเขียนย่อหน้าเปรียบเทียบ "ความร้อนแรง" ของ Britney Spears กับ Paris Hilton คุณทำอะไรกับฉัน


ขอบคุณ แต่มันจะง่ายเกินไปที่จะสั่งให้พวกเขาเพียงแค่เพิ่มจำนวนมากขึ้นใช่มั้ย
caw

7

ฉันสงสัยว่าเป็นไปได้หรือไม่ที่จะใช้สูตรการเร่งด้วยฟิสิกส์แบบปกติในกรณีเช่นนี้?

v2-v1/t or dv/dt

เราสามารถพิจารณา v1 เป็นไลค์เริ่มต้น / โหวต / จำนวนความคิดเห็นต่อชั่วโมงและ v2 เป็น "ความเร็ว" ปัจจุบันต่อชั่วโมงใน 24 ชั่วโมงที่ผ่านมาหรือไม่

นี่เป็นคำถามมากกว่าคำตอบ แต่ดูเหมือนว่ามันอาจจะใช้ได้ เนื้อหาที่มีการเร่งความเร็วสูงสุดจะเป็นหัวข้อที่ได้รับความนิยม ...

ฉันแน่ใจว่านี่อาจไม่ช่วยแก้ปัญหาของ Britney Spears :-)


มันจะได้ผลเพราะมันจะคำนวณการโหวต / ชอบการเพิ่มขึ้นต่อเวลาและนี่คือสิ่งที่เราต้องการ สามารถแก้ไข "ปัญหาของ Britney spears" ในบางส่วนเนื่องจากข้อความค้นหานี้มีค่าสูงv1และจำเป็นต้องมีค่าที่สูงมากv2ในการพิจารณา "แนวโน้ม" อย่างไรก็ตามอาจมีสูตรและอัลกอริทึมที่ดีกว่าและซับซ้อนกว่านี้ อย่างไรก็ตามมันเป็นตัวอย่างการทำงานพื้นฐาน
caw

ในบริบทที่คุณจำเป็นต้องมีบางสิ่งบางอย่างในฟีด "แนวโน้ม" นี่คือสิ่งที่สมบูรณ์แบบ บางอย่างเช่นแท็บสำรวจที่คุณแสดงรายการสิ่งที่ดีที่สุดบนแพลตฟอร์มในตอนนี้ เมื่อใช้ algo อื่นคุณอาจท้ายด้วยชุดผลลัพธ์ที่ว่างเปล่า
kilianc

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 ถือว่าร้อน แต่ 1,000 ถึง 1,050 ไม่ใช่ หรือการไล่ระดับสีที่ซับซ้อนมากขึ้นซึ่งคำนึงถึงแนวโน้มมากกว่าหนึ่งวันต่อไป


ขอบคุณ. แต่ฉันไม่รู้ว่าการไล่ระดับสีคืออะไรและฉันจะทำงานร่วมกับมันได้อย่างไร ขออภัย!
caw

ขอบคุณ ดังนั้นฉันต้องสร้างเวกเตอร์ที่มีความถี่รายวันใช่มั้ย ค่าสัมพัทธ์น่าจะดีกว่าฉันแน่ใจ ตัวอย่าง: การเติบโตจาก 100 เป็น 110 นั้นไม่ดีเท่ากับการเติบโตจาก 1 เป็น 9 ฉันจะบอกว่า แต่ไม่มีฟังก์ชันเวกเตอร์ที่ฉันสามารถใช้เพื่อค้นหาหัวข้อที่ร้อนแรงที่สุดได้หรือไม่ การประเมินค่าสัมพัทธ์จะไม่พอเพียงใช่ไหม การเติบโตจาก 100 เป็น 200 (100%) นั้นไม่ดีเท่าการเติบโตจาก 20,000 ถึง 39,000!
caw

คุณเพิ่มเว็บไซต์ประเภทใดลงไป @ ข้อเสนอแนะของ Autoplectic เพื่อนับการเปลี่ยนแปลงในการค้นหาแบบวันต่อวันจะไม่ขยายไปถึงบางสิ่งบางอย่างเช่นฟอรัมยอดนิยมซึ่งคุณมีหัวข้อมากมายที่มีหัวข้อใหม่ที่ถูกกำหนดใหม่ในแต่ละวัน
Quantum7

คุณพูดถูกฉันต้องการอัลกอริทึมสำหรับข้อมูลจำนวนมหาศาลหลายพันหัวข้อต่อชั่วโมง
caw

นี่เป็นกลยุทธ์ที่ไม่ดี ด้วยวิธีนี้การเพิ่มขึ้น 50 ครั้งของการค้นหาเกี่ยวกับ Britney Spears นั้นร้อนแรงเท่ากับ +50 การค้นหาเกี่ยวกับการลงประชามติใหม่ในยุโรป
Iman Akbari

4

ฉันทำงานในโครงการที่เป้าหมายของฉันคือการค้นหาหัวข้อยอดนิยมจากสตรีมสด Twitter และทำการวิเคราะห์อารมณ์ในหัวข้อที่ได้รับความนิยม (การค้นหาว่าหัวข้อที่ได้รับความสนใจเป็นบวก / พูดคุยในแง่ลบ) ฉันใช้ Storm เพื่อจัดการสตรีมทวิตเตอร์

ฉันเผยแพร่รายงานของฉันเป็นบล็อกแล้ว: http://sayrohan.blogspot.com/2013/06/finding-trending-topics-and-trending.html

ฉันใช้ยอดรวมและคะแนน Z สำหรับการจัดอันดับแล้ว

วิธีการที่ฉันใช้เป็นบิตทั่วไปและในส่วนการสนทนาฉันได้กล่าวถึงวิธีที่เราสามารถขยายระบบสำหรับแอปพลิเคชันที่ไม่ใช่ Twitter

หวังว่าข้อมูลจะช่วยได้


3

หากคุณดูทวีตหรือข้อความบอกสถานะเพื่อรับหัวข้อคุณจะต้องเจอกับเสียงดังมาก แม้ว่าคุณจะลบคำหยุดทั้งหมด วิธีหนึ่งในการรับชุดย่อยของหัวข้อที่ดีกว่าคือการเน้นเฉพาะทวีต / ข้อความที่ใช้ URL ร่วมกันและรับคำหลักจากชื่อเรื่องของหน้าเว็บเหล่านั้น และตรวจสอบให้แน่ใจว่าคุณใช้การติดแท็ก POS เพื่อรับคำนาม + วลีคำนามเช่นกัน

ชื่อเรื่องของหน้าเว็บมักจะเป็นคำอธิบายที่มากกว่าและมีคำที่อธิบายถึงสิ่งที่หน้านั้นเกี่ยวกับ นอกจากนี้การแบ่งปันหน้าเว็บมักมีความสัมพันธ์กับการแบ่งปันข่าวที่ทำลาย (เช่นถ้าคนดังอย่าง Michael Jackson เสียชีวิตคุณจะได้รับคนจำนวนมากแบ่งปันบทความเกี่ยวกับการตายของเขา)

ฉันใช้การทดสอบที่ฉันใช้เพียงคำหลักยอดนิยมจากชื่อเรื่องจากนั้นรับจำนวนคำหลักทั้งหมดจากข้อความสถานะทั้งหมดและพวกเขาก็กำจัดเสียงรบกวนได้อย่างแน่นอน หากคุณทำเช่นนี้คุณไม่จำเป็นต้องมีอัลกอริทึมที่ซับซ้อนเพียงแค่ทำการเรียงลำดับความถี่คำหลักอย่างง่ายและคุณก็อยู่ตรงนั้น


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));
}

PS, TermBag เป็นชุดคำที่ไม่เรียงลำดับ สำหรับเอกสารแต่ละฉบับคุณสร้างคำศัพท์หนึ่งชุด เพียงนับการเกิดคำ จากนั้นเมธอดoccurrencesจะส่งคืนจำนวนการเกิดขึ้นของคำที่กำหนดและเมธอดsizeจะส่งคืนจำนวนคำทั้งหมด ที่ดีที่สุดคือการทำให้ปกติคำอย่างใดโดยทั่วไปtoLowerCaseจะดีพอ แน่นอนในตัวอย่างข้างต้นคุณจะต้องสร้างเอกสารหนึ่งฉบับโดยมีข้อสงสัยทั้งหมดในวันนี้และอีกข้อหนึ่งเป็นข้อความค้นหาทั้งหมดของปีที่แล้ว


ขออภัยฉันไม่เข้าใจรหัส TermBags คืออะไร มันจะดีถ้าคุณสามารถอธิบายได้ในไม่ช้ารหัสนี้ทำอะไร
caw

1
TermBag เป็นกระเป๋าของคำศัพท์เช่นชั้นควรจะสามารถตอบจำนวนคำทั้งหมดในข้อความและจำนวนที่เกิดขึ้นสำหรับแต่ละคำ
akuhn

0

ความคิดคือการติดตามสิ่งต่าง ๆ และสังเกตเห็นเมื่อพวกเขากระโดดอย่างมีนัยสำคัญเมื่อเทียบกับพื้นฐานของตัวเอง

ดังนั้นสำหรับข้อความค้นหาที่มีมากกว่าหนึ่งช่วงเวลาที่แน่นอนให้ติดตามแต่ละรายการและเมื่อมีการเปลี่ยนแปลงค่าบางอย่าง (พูดเกือบสองเท่า) ของมูลค่าในอดีตมันก็เป็นแนวโน้มร้อนแรงใหม่

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.