我每天都有报纸文章的语料库。语料库中的每个单词都有一个当天出现的频率计数。我一直在尝试寻找一种算法来捕捉这些分离词,类似于Twitter在人们的推文中测量趋势的方式。
例如,假设"衰退"一词在同一组报纸中出现的频率如下:
第一天|衰退| 456
Day 2 |衰退| 2134
第三天|衰退| 3678
而"欧洲"
第一天|欧洲| 67895
第2天|欧洲| 71999
第三天|欧洲| 73321
我想把每天的增长百分比乘以频率总和的对数。然后我将取平均值来得分并比较不同的单词。
在本例中:
衰退= (3.68*8.74+0.72*8.74)/2 = 19.23
欧洲= (0.06*12.27+0.02*12.27)/2 = 0.49
有没有更好的方法来捕捉爆炸性增长?我试着挖掘日常语料库,找出在特定时间段内被提及次数越来越多的术语。请让我知道如果有一个更好的算法。我希望能够找到具有高非恒定加速度的单词。也许求二阶导数更有效。也可能是我把这个弄得太复杂了,在探索频道上看了太多物理节目。如果可能的话,让我知道一个数学例子,谢谢!
首先要注意的是,这可以通过一个局部问题来近似。也就是说,一个"趋势"词实际上只取决于最近的数据。因此,我们可以立即将数据截断到最近的N
天,其中N
是一些实验确定的最优值。这大大减少了我们必须查看的数据量。
事实上,美国国家公共电台的文章是这样建议的。
然后你需要考虑增长。而这正是导数所得到的。首先要做的是对数据进行规范化。所有数据点除以第一个数据点的值。这样一来,一个不常用词的大量增长就不会被一个流行词的相对较小增长所淹没。
对于一阶导数,这样做:
d[i] = (data[i] - data[i+k])/k
表示某实验测定的k
值(在本例中为天数)。同样,二阶导数可以表示为:
d2[i] = (data[i] - 2*data[i+k] + data[i+2k])/(2k)
高阶导数也可以这样表示。然后你需要为这些导数分配某种权重系统。这是一个纯粹的实验过程,它实际上取决于你想要考虑的"趋势"。例如,你可能想让增长加速度的重量是速度的一半。另一件需要注意的事情是,您应该尽最大努力从数据中去除噪声,因为导数对噪声非常敏感。您可以通过仔细选择k
的值以及完全丢弃频率非常低的单词来做到这一点。
我还注意到你乘以了频率的对数和。我认为这是为了给流行词的增长更多的权重(因为更流行的词首先不太可能成为趋势)。衡量一个词受欢迎程度的标准方法是看它的逆文档频率(IDF)。
我会除以一个单词的IDF,给更多流行单词的增长更大的权重。
IDF[word] = log(D/(df[word))
其中D
是文档的总数(例如,对于Twitter,它将是tweet的总数),df[word]
是包含word
的文档的数量(例如,包含一个单词的tweet的数量)。
高IDF对应一个不流行的词,而低IDF对应一个流行的词。
你的方法(以百分比衡量每日增长)的问题在于它忽略了单词的通常"背景水平",正如你的例子所示;"欧洲"的增长速度比"衰退"快,但得分却低得多。
如果单词的背景水平具有良好的分布(高斯分布,或者其他不会偏离平均值太远的分布),那么我认为修改CanSpice的建议将是一个好主意。计算出每个单词的平均值和标准差,使用C-N+1-T
到C-T
的天数,其中C是当前日期,N是要考虑的天数,T是定义趋势的天数。
假设N=90, T=3,那么我们使用大约3个月作为背景,并假设趋势由连续三个峰值定义。例如,在这种情况下,您可以根据卡方p值对单词进行排序,计算方法如下:
(mu, sigma) = fitGaussian(word='europe', startday=C-N+1-3, endday=C-3)
X1 = count(word='europe', day=C-2)
X2 = count(word='europe', day=C-1)
X3 = count(word='europe', day=C)
S = ((X1-mu)/sigma)^2 + ((X2-mu)/sigma)^2 + ((X3-mu)/sigma)^2
p = pval.chisq(S, df=3)
从本质上讲,你可以得到在过去三天中与背景水平相比最极端的单词
我将首先尝试一个简单的解决方案。在相邻的日子之间设置一个简单的加权差应该就可以了。也许在那之前做过记录。你可能得试试举重。例如(-2,-1,1,2)会给出数据爆炸的点。
如果这还不够,你可以尝试斜率过滤(http://www.claysturner.com/dsp/fir_regression.pdf)。由于该算法基于线性回归,因此应该可以对其进行修改,以适应其他类型的回归(例如二次回归)。
所有使用这些过滤技术的尝试都有一个优点,它们可以运行得非常快,并且您应该能够找到提供快速过滤的库。