许多网站提供一些统计数据,如“过去24小时内最热门的话题”。例如,Topix.com在其“新闻趋势”部分显示了这一点。在那里,你可以看到被提及次数增长最快的话题。

我也想为一个主题计算这样的“嗡嗡声”。我怎么能这样做呢?算法应该对热点较少的话题进行加权。通常(几乎)没有人提及的话题应该是最热门的话题。

谷歌提供“热门趋势”,topix.com显示“热门话题”,fav.or.it显示“关键字趋势”——所有这些服务都有一个共同点:他们只向你展示当前异常热门的即将到来的趋势。

像“布兰妮·斯皮尔斯”、“天气”或“帕丽斯·希尔顿”这样的词不会出现在这些榜单中,因为它们总是热门且频繁。这篇文章称之为“小甜甜布兰妮问题”。

我的问题是:如何编写算法或使用现有算法来解决这个问题?有一个在过去24小时内搜索的关键字列表,算法应该向您显示10个(例如)最热门的关键字。

我知道,在上面的文章中,提到了某种算法。我试着在PHP中编码,但我不认为它会工作。它只是找到了大多数人,不是吗?

我希望你能帮助我(代码示例将是伟大的)。


当前回答

我认为你需要注意的关键词是“不正常”。为了确定什么时候“不正常”,你必须知道什么是正常的。也就是说,您将需要历史数据,可以对其求平均值以找出特定查询的正常速率。您可能希望从平均计算中排除不正常的日子,但这同样需要有足够的数据,这样您就知道应该排除哪些日子。

在此基础上,你必须设置一个阈值(我确信这需要实验),如果有东西超出了阈值,比如搜索量比正常情况多50%,你就可以认为这是一个“趋势”。或者,如果你想像你提到的那样找到“最流行的X”,你只需要根据它们与正常比率的距离(百分比)来排序。

例如,假设你的历史数据告诉你,布兰妮·斯皮尔斯(Britney Spears)通常获得10万次搜索,帕丽斯·希尔顿(Paris Hilton)通常获得5万次搜索。如果有一天她们的搜索量都比平时多了1万次,那么你应该认为帕里斯比布兰妮更“热”,因为她的搜索量比平时多了20%,而布兰妮的搜索量只增加了10%。

天啊,我真不敢相信我刚刚写了一段比较布兰妮·斯皮尔斯和帕丽斯·希尔顿的“性感”的段落。你对我做了什么?

其他回答

也许一个简单的话题频率梯度就能起作用——大的正梯度=快速增长的受欢迎程度。

最简单的方法是将每天的搜索次数归位,这样你就有了

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不是。或者是考虑到不止一天的趋势的更复杂的梯度。

通常情况下,“嗡嗡声”是通过某种形式的指数/对数衰减机制计算出来的。有关Hacker News、Reddit和其他网站如何简单处理这个问题的概述,请参阅这篇文章。

这并没有完全解决总是受欢迎的事情。你要找的似乎是谷歌的“热门趋势”功能。为此,您可以将当前值除以历史值,然后减去低于某个噪声阈值的值。

您可以使用对数概率比来比较当前日期与上个月或去年。这在统计上是合理的(假设你的事件不是正态分布,这是从你的问题中假设的)。

只需按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就足够了。当然,在上面的示例中,您将创建一个包含当前所有查询的文档,以及一个包含去年所有查询的文档。

我想知道在这种情况下是否有可能使用常规的物理加速度公式?

v2-v1/t or dv/dt

我们可以认为v1是每小时的初始点赞/投票/评论数,v2是过去24小时内每小时的当前“速度”?

这更像是一个问题,而不是一个答案,但似乎它可能会起作用。任何加速最快的内容都将成为热门话题……

我相信这并不能解决布兰妮的问题:-)

I had worked on a project, where my aim was finding Trending Topics from Live Twitter Stream and also doing sentimental analysis on the trending topics (finding if Trending Topic positively/negatively talked about). I've used Storm for handling twitter stream. I've published my report as a blog: http://sayrohan.blogspot.com/2013/06/finding-trending-topics-and-trending.html I've used Total Count and Z-Score for the ranking. The approach that I've used is bit generic, and in the discussion section, I've mentioned that how we can extend the system for non-Twitter Application. Hope the information helps.