인기 주제 또는 태그를 계산하는 가장 좋은 방법은 무엇입니까?


183

많은 사이트에서 "지난 24 시간 동안 가장 인기있는 주제"와 같은 통계를 제공합니다. 예를 들어 Topix.com은 "뉴스 트렌드"섹션에이를 표시합니다. 여기에서 가장 많이 인용되는 주제를 볼 수 있습니다.

주제에 대한 "버즈"도 계산하고 싶습니다. 어떻게해야합니까? 알고리즘은 항상 뜨겁지 않은 주제에 가중치를 부여해야합니다. 일반적으로 (거의) 아무도 언급하지 않는 주제는 가장 인기있는 주제 여야합니다.

Google은 "Hot Trends", topix.com은 "Hot Topics"를, fav.or.it는 "Keyword Trends"를 보여줍니다. 이러한 모든 서비스에는 공통점이 있습니다.

"브리트니 스피어스", "날씨"또는 "파리 힐튼"과 같은 용어는 항상 뜨겁고 자주 있기 때문에이 목록에 나타나지 않습니다. 이 기사는 이것을 "브리트니 스피어스 문제"라고 부릅니다.

내 질문 : 어떻게 알고리즘을 코딩하거나 기존 알고리즘을 사용 하여이 문제를 해결할 수 있습니까? 지난 24 시간 동안 검색된 키워드 목록이 있으면 알고리즘은 가장 인기있는 10 개의 키워드를 표시해야합니다.

위의 기사에서 일종의 알고리즘이 언급되어 있음을 알고 있습니다. PHP로 코드를 작성하려고했지만 작동하지 않을 것이라고 생각합니다. 그것은 단지 대다수를 발견하지 않습니까?

나는 당신이 나를 도울 수 있기를 바랍니다 (코딩 예제가 좋을 것입니다).


4
흥미로운 질문, 사람들이 무엇을 말해야하는지 궁금합니다.
mmcdole

14
종료 할 이유가 없습니다. 이것은 유효한 질문입니다
TStamper

1
이것은 정확히 같은 질문이며 그는 심지어 그 사실을 진술합니다! 사람들이 왜 그것을지지 하는가!
Darryl Hein

3
나는 당신이 찾고있는 결과 유형에 대해 약간 혼란 스럽습니다. 이 기사는 많은 사람들이 해당 용어를 검색하기 때문에 "Britney Spears"가 "Hot"목록에서 지속적으로 발견 될 것으로 보이지만, 귀하의 질문에 따르면 해당 용어에 대한 검색 횟수가 목록에 나타나지 않습니다. 시간이 지남에 따라 많이 증가하지 않습니다 (높은 상태로 유지되지만 꾸준히 유지됩니다). 어떤 결과를 달성하려고합니까? "Britney Spears"가 높거나 낮아야합니까?
e.James 2009

1
@eJames, "Britney Spears"는 검색 용어가 높고 속도가 빠른 검색어를 찾고 있기 때문에 순위가 높아서는 안됩니다.
mmcdole 2009

답변:


103

이 문제는 다른 사람들이 언급했듯이 이력 데이터의 표준 편차뿐만 아니라 이력 데이터의 표준 편차를 고려하여 평균을 사용하는 것보다 더 강력한 z 점수 또는 표준 점수를 요구합니다.

귀하의 경우 z- 점수는 다음 공식으로 계산되며 추세는 조회 / 일과 같은 비율입니다.

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

z- 점수가 사용될 때 z- 점수가 높거나 낮을수록 추세가 비정상적으로 증가하므로, 예를 들어 z- 점수가 매우 긍정적이면 추세가 비정상적으로 상승하는 반면, 매우 음수이면 비정상적으로 하락합니다. . 따라서 모든 후보 트렌드에 대해 z- 점수를 계산하면 최고 10 개의 z- 점수가 가장 비정상적으로 증가하는 z- 점수와 관련됩니다.

z- 점수에 대한 자세한 내용 은 Wikipedia 를 참조하십시오 .

암호

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()
    
  • 이 방법을 사용하면 작업 흐름은 다음과 같습니다. 각 주제, 태그 또는 페이지에 대해 데이터베이스에서 총 일 수,보기 합계 및보기 합계에 대해 부동 소수점 필드를 작성하십시오. 기록 데이터가있는 경우 해당 데이터를 사용하여 이러한 필드를 초기화하고 그렇지 않으면 0으로 초기화하십시오. 하루가 끝나면 세 개의 데이터베이스 필드에 저장된 히스토리 데이터에 대한 일 수를 사용하여 z 점수를 계산하십시오. Xz 점수가 가장 높은 주제, 태그 또는 페이지는 오늘의 X "호스트 트렌드"입니다. 마지막으로 3 개의 각 필드를 일 값으로 업데이트하고 내일 프로세스를 반복하십시오.

새로운 추가

위에서 논의 된 일반적인 z- 점수는 데이터의 순서를 고려하지 않으므로 '1'또는 '9'의 관측에 대한 z- 점수가 시퀀스 [1, 1, 1, 1에 대해 동일한 크기를 갖습니다. , 9, 9, 9, 9]. 추세 찾기의 경우 가장 최신 데이터는 이전 데이터보다 가중치가 높아야하므로 '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

최신 정보

David Kemp가 올바르게 지적했듯이 일련의 상수 값이 주어지면 다른 값과 다른 관측 값에 대한 zscore가 요청되면 결과는 아마도 0이 아니어야합니다. 실제로 반환 된 값은 무한대 여야합니다. 그래서 나는이 줄을 바꿨다.

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 쿼리가 있습니다.
thouliha

1
여기서 부패는 직관적이지 않습니다. 붕괴가 0.8 인 [10, 20]과 같은 2 개의 값을 입력하면 AVG는 10 * 0.8 + 20 * 0.2 = 12입니다. 붕괴가 발생하면 20의 무게가 10보다 커야하므로 15 이상의 값을 예상 할 수 있습니다. 가중치가있는 병렬 목록을 만드는 numpy.average의 가중 평균을 사용하여 훨씬 더 나은 대안을 사용할 수 있습니다. 예를 들면 다음과 같습니다. data = range (10,30,10) decay = 0.8 decay_weights = [범위 내에서 decay ** a (len (data), 0, -1)] print np.average (data, weights = decay_weights)
Jeroen

93

주제의 속도를 측정하는 알고리즘이 필요합니다. 다시 말하면 그래프를 작성하면 놀라운 속도로 올라가는 것을 보여주고 싶습니다.

이것은 추세선의 첫 번째 파생물이며 전체 계산의 가중 요소로 통합하는 것은 어렵지 않습니다.

정규화

당신이해야 할 한 가지 기술은 모든 데이터를 정규화하는 것입니다. 관심있는 각 주제에 대해 해당 주제의 기준을 정의하는 매우 낮은 통과 필터를 유지하십시오. 이제 해당 주제에 관한 모든 데이터 포인트가 정규화되어야합니다. 기준선을 빼면 모든 주제가 0에 가까워지고 위와 아래에 급상승이 발생합니다. 대신 신호를 기준선 크기로 나누면 신호가 약 1.0이됩니다. 이렇게하면 모든 신호가 서로 일치 할뿐 아니라 (기준선을 정규화 함) 스파이크도 정규화됩니다. 브리트니 스파이크가 다른 사람의 스파이크보다 크기가 크지 만주의를 기울여야한다는 의미는 아닙니다. 스파이크가 기준선에 비해 매우 작을 수 있습니다.

파생

모든 것을 정규화 한 후에는 각 주제의 기울기를 파악하십시오. 연속 된 두 점을 취하여 차이를 측정합니다. 양의 차이는 추세가 증가하고 음의 차이는 추세가 감소합니다. 그런 다음 정규화 된 차이점을 비교하고 다른 주제와 비교하여 인기가 높아지고있는 주제를 확인할 수 있습니다. 각 주제는 다른 주제와는 다른 순서로 나타날 수있는 자체 '정상'에 맞게 조정됩니다.

이것은 실제로 문제의 첫 번째 단계입니다. 더 많은 고급 기술이 필요하지만 (주로 위 알고리즘과 다른 알고리즘을 조합하여 필요에 맞게 가중치를 부여 함) 시작하기에 충분해야합니다.

기사에 대해

이 기사는 주제 동향에 관한 것이지만 인기있는 것과 그렇지 않은 것을 계산하는 방법에 관한 것이 아니라 Lycos 및 Google과 같은 곳에서 그러한 알고리즘이 처리해야하는 방대한 양의 정보를 처리하는 방법에 관한 것입니다. 각 주제에 카운터를 제공하고 검색 할 때 각 주제의 카운터를 찾는 데 필요한 공간과 시간은 엄청납니다. 이 기사는 그러한 작업을 시도 할 때 직면하는 문제에 관한 것입니다. 브리트니 효과에 대해서는 언급하지만 그것을 극복하는 방법에 대해서는 이야기하지 않습니다.

마찬가지로 Nixuz 지적 이 또한 Z 또는라고도 표준 점수 .


1
나는 이것을 편집하기 전에 이것을 찬성했고, 되돌아 와서 다시 찬성하고 싶었다! 좋은 일
mmcdole

감사! 나는 의사 코드를 할 것이지만 지금은 시간이 없습니다. 어쩌면 나중에 또는 다른 누군가가 이러한 개념을 취하여 구현할 것입니다.
Adam Davis

대단히 감사합니다, Adam Davis! Nixuz가 실제로 똑같이 묘사했다면 PHP에 솔루션 이 있다고 생각합니다 . paste.bradleygill.com/index.php?paste_id=9206 이 코드가 맞다고 생각하십니까?
caw

속도가 아니라 주제의 가속이 아니어야합니까? 마지막 답변을 확인하십시오
Soap

17

차드 버치 (Chad Birch)와 아담 데이비스 (Adam Davis)는 기준을 세우기 위해 뒤를 돌아보아야한다는 점에서 맞습니다. 문구에 따르면 귀하의 질문에 따르면 지난 24 시간 동안의 데이터 만보 고 싶어하지만 비행이 쉽지는 않습니다.

많은 양의 기록 데이터를 쿼리하지 않고 데이터에 메모리를 제공하는 한 가지 방법은 지수 이동 평균 을 사용하는 것 입니다. 이것의 장점은 기간 당 한 번만 업데이트 한 다음 모든 이전 데이터를 플러시 할 수 있으므로 단일 값만 기억하면된다는 것입니다. 따라서 기간이 하루 인 경우 각 주제에 대해 "일일 평균"속성을 유지해야합니다.

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

a_n요일의 이동 평균은 어디에서 n, b는 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. b가 높을수록 새로운 값이 덜 중요하고 더 오래된 값이 중요합니다. 그러나 b가 높을수록 a의 초기 값을 낮추기 위해 더 많은 데이터가 필요합니다.

처음 두 가지 특성이 정확히 당신이 찾고있는 것이라고 생각합니다. 간단한 구현 아이디어를 제공하기 위해 다음은 파이썬 구현입니다 (모든 데이터베이스 상호 작용 제외).

>>> 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

아담 정말요? 나는 그들에게 익숙하지 않다. IIR의 특별한 경우입니까? 내가 감추고있는 기사는 간단한 경우에 지수 이동 평균으로 낮추는 공식을 제공하지 않는 것 같습니다.
David Berger

대단히 감사합니다, David Berger! 작동하면 다른 답변에 큰 도움이 될 것입니다! 그래도 몇 가지 질문이 있습니다. 나는 당신이 그들에게 대답 할 수 있기를 바랍니다 : 1) 요인 b는 오래된 데이터의 체중이 얼마나 빨리 감소하는지 정의합니까? 2)이 방법은 단순히 기존 데이터를 저장하고 평균을 계산하는 것과 비교하여 대략 동등한 결과를 제공합니까? 3) 이것이 당신의 공식입니까? $ average_value = $ old_average_value * $ smoothing_factor + $ hits_today * (1- $ smoothing_factor)
caw

포인트 1과 3이 맞습니다. 2에 대한 약간의 미묘한 논의에 대한 내 편집을 참조하십시오.
David Berger

8

일반적으로 "버즈"는 지수 / 로그 붕괴 메커니즘의 일부 형식을 사용하여 파악됩니다. Hacker News, Reddit 및 기타 사용자가이를 간단한 방법으로 처리하는 방법에 대한 개요는 이 게시물을 참조하십시오 .

이것은 항상 인기있는 것들을 완전히 다루지는 않습니다. 찾고있는 것은 Google의 " 핫 트렌드 "기능 과 같은 것 같습니다 . 이를 위해 현재 값을 기록 값으로 나눈 다음 노이즈 임계 값보다 낮은 값을 뺄 수 있습니다.


예, Google의 인기 트렌드는 내가 찾는 바로 그 것입니다. 역사적 가치는 무엇인가? 예를 들어 지난 7 일의 평균값은?
caw

1
데이터의 변동성에 따라 다릅니다. 평균 30 일로 시작할 수 있습니다. 주기적 일 경우 (예 : Kentucky Derby) 매년 비교하는 것이 좋습니다. 실험하고 실제로 가장 잘 작동하는 것을 보았습니다.
Jeff Moser

7

나는 그들이 당신이 주목해야 할 핵심 단어는 "정상적으로"라고 생각합니다. 어떤 것이 "비정상"인지 확인하려면 무엇이 정상인지 알아야합니다. 즉, 특정 쿼리의 정상 비율을 찾기 위해 평균을 내릴 수있는 기록 데이터가 필요합니다. 평균 계산에서 비정상적인 일을 제외하고 싶을 수도 있지만, 아직 충분한 데이터가 필요하므로 제외 할 일을 알 수 있습니다.

여기에서 임계 값을 설정해야합니다 (실험이 필요합니다). 만약 임계 값을 벗어나는 것이 정상보다 검색이 50 % 더 많다면이를 "추세"라고 생각할 수 있습니다. 또는 위에서 언급 한 "최고 X 최신 유행"을 찾으려면 정상 속도에서 얼마나 떨어져 있는지 (백분율 기준) 사물을 주문하면됩니다.

예를 들어, 과거 데이터에 따르면 브리트니 스피어스는 일반적으로 10 만 건의 검색을, 파리 힐튼은 보통 5 만 건의 검색을 받았다고 가정합니다. 둘 다 평소보다 10,000 번 더 검색을받는 날이 있다면 브리트니보다 파리가 "호터"라고 생각해야합니다. 브리트니의 검색은 평소보다 20 % 더 증가한 반면 브리트니는 10 %에 불과했습니다.

하나님, 나는 브리트니 스피어스와 패리스 힐튼의 "뜨거움"을 비교 한 단락을 썼다는 것을 믿을 수 없습니다. 나 한테 무슨 짓을 한거야?


고마워요.하지만 조금씩 증가하는 것만으로는 주문하기가 너무 쉬울까요?
caw

7

그런 경우 규칙적인 물리 가속 공식을 사용할 수 있는지 궁금합니다.

v2-v1/t or dv/dt

v1을 시간당 초기 좋아요 / 투표 / 설명 횟수로 간주하고 v2를 지난 24 시간 동안 시간당 현재 "속도"로 간주 할 수 있습니까?

이것은 답변보다 질문과 비슷하지만 효과가있는 것 같습니다. 가장 빠른 가속을 가진 모든 컨텐츠가 인기 주제가 될 것입니다 ...

이것이 브리트니 스피어스 문제를 해결할 수 없을 것이라고 확신합니다 :-)


그것은 시간당 투표 / 같은 증가를 계산하기 때문에 효과가 있으며 이것이 우리에게 필요한 것입니다. 이 검색어는 항상 높고 "트 렌딩"으로 간주 되려면 v1매우 높아야 하므로 "Britney spears 문제"를 부분적으로 해결할 수 v2있습니다. 그러나이 작업을 수행하는 데 더 우수하고 정교한 수식과 알고리즘이있을 수 있습니다. 그럼에도 불구하고 기본적인 작업 예입니다.
caw

항상 "트 렌딩"피드에 무언가가 필요한 상황에서는 이것이 완벽합니다. 플랫폼에서 가장 좋은 것을 나열하는 탐색 탭과 같은 것. 다른 알고리즘을 사용하면 빈 결과 집합이 생길 수 있습니다.
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으로가는 것은 뜨거운 것으로 간주되지만 1000에서 1050은 그렇지 않습니다. 또는 하루 이상의 요즘 추세를 고려한보다 복잡한 기울기입니다.


감사합니다. 그러나 나는 그라디언트가 무엇인지, 어떻게 그라디언트를 사용할 수 있는지 정확히 알지 못합니다. 죄송합니다!
caw

감사. 일일 빈도가 포함 된 벡터를 만들어야합니다. 상대 값이 더 좋을 것입니다. 예 : 100에서 110으로의 성장은 1에서 9 로의 성장만큼 좋지 않습니다. 그러나 가장 인기있는 주제를 찾는 데 사용할 수있는 벡터 함수가 있습니까? 상대 값 만 평가하는 것만으로는 충분하지 않습니까? 100에서 200으로의 성장 (100 %)은 20,000에서 39,000으로의 성장만큼 좋지 않습니다!
caw

어떤 종류의 웹 사이트에 이것을 추가하고 있습니까? 매일의 검색 변화를 계산하는 @Autoplectic의 제안은 매일 새로운 주제가 정의되어있는 수천 개의 주제가있는 인기있는 포럼과 같이 적합하지 않습니다.
Quantum7

맞습니다. 시간당 수천 개의 주제, 엄청난 양의 데이터에 대한 알고리즘이 필요합니다.
caw

이것은 나쁜 전략입니다. 이런 식으로 Britney Spears에 대한 총 50 개의 검색 증가는 유럽의 새로운 국민 투표에 대한 +50 검색만큼이나 뜨겁습니다.
Iman Akbari

4

필자의 목표는 Live Twitter Stream에서 Trending Topics를 찾고 Trending 주제에 대한 감상적 분석을 수행하는 프로젝트를 진행했습니다. Twitter 스트림을 처리하기 위해 Storm을 사용했습니다.

보고서를 블로그로 게시했습니다 : http://sayrohan.blogspot.com/2013/06/finding-trending-topics-and-trending.html

순위에 Total Count와 Z-Score를 사용했습니다.

내가 사용한 접근법은 약간 일반적이며 토론 섹션에서 비 Twitter 응용 프로그램을 위해 시스템을 확장하는 방법에 대해 언급했습니다.

정보가 도움이되기를 바랍니다.


3

주제를 얻기 위해 트윗이나 상태 메시지를 살펴보면 많은 소음이 발생합니다. 모든 중지 단어를 제거하더라도. 주제 후보의 더 나은 하위 집합을 얻는 한 가지 방법은 URL을 공유하는 트윗 / 메시지에만 집중하고 해당 웹 페이지의 제목에서 키워드를 얻는 것입니다. 그리고 POS 태깅을 적용하여 명사 + 명사구도 가져옵니다.

웹 페이지의 제목은 일반적으로보다 설명이 많으며 페이지의 내용을 설명하는 단어를 포함합니다. 또한 웹 페이지를 공유하는 것은 일반적으로 속보 뉴스를 공유하는 것과 관련이 있습니다 (즉, Michael Jackson과 같은 유명인이 사망하면 많은 사람들이 자신의 죽음에 관한 기사를 공유하게됩니다).

제목에서 인기있는 키워드 만 가져 와서 모든 상태 메시지에서 해당 키워드의 총 수를 가져 오는 실험을 진행했으며 많은 소음을 제거했습니다. 이 방법을 사용하면 복잡한 알고리즘이 필요하지 않고 키워드 빈도를 간단한 순서로 정렬하면 중간 정도입니다.


2

log-likelihood-ratios를 사용하여 현재 날짜와 지난 달 또는 연도를 비교할 수 있습니다. 이것은 통계적으로 건전합니다 (이벤트가 정상적으로 분배되지 않았기 때문에 귀하의 질문에서 가정).

모든 용어를 logLR로 정렬하고 상위 10 개를 선택하십시오.

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좋으며 일반적으로 충분합니다. 물론, 위의 예에서 오늘의 모든 쿼리가있는 문서와 작년의 모든 쿼리가있는 문서를 만듭니다.


죄송합니다. 코드를 이해하지 못합니다. TermBag 란 무엇입니까? 이 코드의 기능을 간단히 설명 할 수 있다면 좋을 것입니다.
caw

1
TermBag는 용어의 백입니다. 즉, 클래스는 텍스트의 총 단어 수와 각 단어의 발생 횟수에 대답 할 수 있어야합니다.
akuhn

0

아이디어는 그러한 것들을 추적하고 자신의 기준과 비교하여 그들이 크게 뛰어 올 때 알 수 있습니다.

따라서 특정 임계 값을 초과하는 쿼리의 경우 각 쿼리를 추적하고 이전 값의 거의 두 배 (예 : 거의 두 배)로 변경되면 새로운 핫 트렌드입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.