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

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

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

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

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

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

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


当前回答

你需要一种算法来衡量一个话题的传播速度——换句话说,如果你把它画出来,你想要显示那些以惊人的速度增长的话题。

这是趋势线的一阶导数,将其作为整体计算的加权因素并不难。

正常化

One technique you'll need to do is to normalize all your data. For each topic you are following, keep a very low pass filter that defines that topic's baseline. Now every data point that comes in about that topic should be normalized - subtract its baseline and you'll get ALL of your topics near 0, with spikes above and below the line. You may instead want to divide the signal by its baseline magnitude, which will bring the signal to around 1.0 - this not only brings all signals in line with each other (normalizes the baseline), but also normalizes the spikes. A britney spike is going to be magnitudes larger than someone else's spike, but that doesn't mean you should pay attention to it - the spike may be very small relative to her baseline.

推导出

一旦你标准化了所有的东西,计算出每个主题的斜率。取两个连续的点,测量差值。正的差异呈上升趋势,负的差异呈下降趋势。然后你可以比较归一化的差异,并找出哪些主题与其他主题相比受欢迎程度上升-每个主题都适用于它自己的“正常”,这可能是与其他主题不同的量级。

这确实是解决这个问题的第一步。您还需要使用更高级的技术(主要是上述算法与其他算法的组合,根据您的需要进行加权),但这应该足以让您开始学习。

关于文章

The article is about topic trending, but it's not about how to calculate what's hot and what's not, it's about how to process the huge amount of information that such an algorithm must process at places like Lycos and Google. The space and time required to give each topic a counter, and find each topic's counter when a search on it goes through is huge. This article is about the challenges one faces when attempting such a task. It does mention the Brittney effect, but it doesn't talk about how to overcome it.

正如Nixuz指出的,这也被称为Z或标准分数。

其他回答

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

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

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

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

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

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

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

如果你只是看推文或状态信息来获取你的主题,你会遇到很多噪音。即使你删除了所有的停止词。获得更好的主题候选子集的一种方法是只关注共享URL的推文/消息,并从这些网页的标题中获得关键字。并且确保你也应用了POS标记来获得名词+名词短语。

网页的标题通常更具有描述性,包含描述页面内容的单词。此外,分享网页通常与分享突发新闻相关(例如,如果像迈克尔·杰克逊这样的名人去世了,你会有很多人分享关于他去世的文章)。

我做过实验,只从标题中选取热门关键词,然后在所有状态信息中计算这些关键词的总数,它们确实消除了很多干扰。如果你这样做,你不需要一个复杂的算法,只是做一个简单的关键字频率排序,你已经完成了一半。

你需要一种算法来衡量一个话题的传播速度——换句话说,如果你把它画出来,你想要显示那些以惊人的速度增长的话题。

这是趋势线的一阶导数,将其作为整体计算的加权因素并不难。

正常化

One technique you'll need to do is to normalize all your data. For each topic you are following, keep a very low pass filter that defines that topic's baseline. Now every data point that comes in about that topic should be normalized - subtract its baseline and you'll get ALL of your topics near 0, with spikes above and below the line. You may instead want to divide the signal by its baseline magnitude, which will bring the signal to around 1.0 - this not only brings all signals in line with each other (normalizes the baseline), but also normalizes the spikes. A britney spike is going to be magnitudes larger than someone else's spike, but that doesn't mean you should pay attention to it - the spike may be very small relative to her baseline.

推导出

一旦你标准化了所有的东西,计算出每个主题的斜率。取两个连续的点,测量差值。正的差异呈上升趋势,负的差异呈下降趋势。然后你可以比较归一化的差异,并找出哪些主题与其他主题相比受欢迎程度上升-每个主题都适用于它自己的“正常”,这可能是与其他主题不同的量级。

这确实是解决这个问题的第一步。您还需要使用更高级的技术(主要是上述算法与其他算法的组合,根据您的需要进行加权),但这应该足以让您开始学习。

关于文章

The article is about topic trending, but it's not about how to calculate what's hot and what's not, it's about how to process the huge amount of information that such an algorithm must process at places like Lycos and Google. The space and time required to give each topic a counter, and find each topic's counter when a search on it goes through is huge. This article is about the challenges one faces when attempting such a task. It does mention the Brittney effect, but it doesn't talk about how to overcome it.

正如Nixuz指出的,这也被称为Z或标准分数。