我有大量的文字数据。我的整个数据库是UTF-8的文本格式
我需要在我的整个文本数据上列出最重复的短语。
例如我的愿望输出如下:
{
'a': 423412341,
'this': 423412341,
'is': 322472341,
'this is': 222472341,
'this is a': 122472341,
'this is a my': 5235634
}
处理和存储每个短语占用巨大的数据库。 例如存储在MySQL或MongoDB中。 问题是有没有更有效的数据库或算法来找到这个结果? Solr,Elasticsearch等......
我认为每个短语中最多10个单词对我有好处。
答案 0 :(得分:4)
我建议合并来自两个字段的提示:Streaming Algorithms和Apriori Algorithm From Market-Basket Analysis。
让我们从找到 k 最常见的单个单词而不将整个语料库加载到内存中的问题开始。一个非常简单的算法采样(参见Finding Frequent Items in Data Streams])可以很容易地完成。此外,它非常适合并行实现(如下所述)。关于top-k查询的工作量很多,包括一些关于分布式版本的工作(参见,例如Efficient Top-K Query Calculation in Distributed Networks)。
现在解决 k 最常见的短语(可能是多个短语)的问题。显然,最常见的长度为 l + 1 的短语必须包含最常用的短语 l 作为前缀,因为在短语中附加单词不能增加其受欢迎程度。因此,一旦你拥有 k 最常用的单个单词,你就可以只扫描语料库(这更快)来构建最常用的长度为2的短语。使用它,你可以构建最多频繁的长度为3的短语,依此类推。停止条件是当长度为 l + 1 的短语不会驱逐任何长度为 l 的短语时。
采样算法的简短描述
这是一个非常简单的算法,它很有可能找到频率至少 f 的顶级 k 项。它分两个阶段运作:第一个找到候选元素,第二个计算它们。
在第一阶段,从语料库中随机选择 ~log(n)/ f 单词(请注意,这远远小于 n )。概率很高,所有想要的单词都出现在这些单词的集合中。
在第二阶段,维护这些候选元素计数的字典;扫描语料库,并计算出现次数。
输出第二阶段产生的项目的顶部 k 。
请注意,第二阶段非常适合并行实现。如果将文本分区为不同的段,并计算每个段中的出现次数,则可以在最后轻松组合词典。
答案 1 :(得分:1)
您是否考虑过使用https://github.com/jselbie/xkcdclock?
假设您可以访问适当的基础架构,这似乎非常适合它。您将需要一个将行分为多个单词标记的标记生成器,最多10个单词。我认为这不是什么大问题。 MR作业的结果将是C1 || C2
-----------------
a || 1
b || 1
c || 1
a || 0
b || 0
c || 0
d || 0
对,您可以将其传递给另一个作业以在频率上对它们进行排序(一个选项)。在考虑其他解决方案之前,我建议您阅读Hadoop / MapReduce。您也可以使用HBase存储任何中间输出。
Google的MapReduce原文MapReduce。
答案 2 :(得分:1)
将其标记为1到10个单词,并按标记长度插入10个SQL表。确保在带有字符串标记的列上使用哈希索引。然后只需在每个表上调用 SELECT token,COUNT(*) FROM tablename GROUP BY token
并将结果转储到某处并等待。
INSERT...ON DUPLICATE KEY UPDATE
)。不过,你绝对应该使用哈希索引。
之后只根据出现次数排序并合并来自这10个表的数据(你可以一步完成,但这会给内存带来更多压力)。
警惕Ami Tavory建议的启发式方法,如果选择错误的参数,就会得到错误的结果(在一些经典术语或短语中可以看到采样算法的缺陷 - 例如" habeas corpus" - habeas和corpus都不会被选为频繁的,但作为一个2个单词的短语,它可能会高于你通过追加/加入普通单词得到的一些短语。肯定没有必要将它们用于较小长度的标记,只有在经典方法失败时才会使用它们(花费太多时间或内存)。
答案 3 :(得分:0)
艾米·塔沃里(Amy Tavori)的最高回答是:
很显然,长度为l + 1的最常用短语必须包含长度为l的最频繁的短语作为前缀,因为将一个单词附加到短语不能增加其流行度。
虽然将单词附加到短语确实不会增加其流行度,但没有理由假设2克的频率受1克的频率限制。为了说明,请考虑以下语料库(专门为说明这一点而构建):
在这里,将存在一个棘手的语料库;一个非常奇怪的,有时是一个隐秘的语料库可能会让您目瞪口呆。特别是因为我的技巧性语料库与您期望的模式不匹配;它也不像鱼,船,向日葵或非常漂亮的小猫。狡猾的语料库将使名为Ami Tavory的用户感到惊讶;从现在开始跟随一年或一个月或一分钟,这个棘手的语料库将很有趣。
看看最常见的单词,我们得到:
1-Gram Frequency
------ ---------
a 12
will 6
corpus 5
tricksy 4
or 3
from 2
it 2
the 2
very 2
you 2
Ami Tavori建议的方法将识别最上面的1克“ a”,并将搜索范围缩小到带有前缀“ a”的2克。但是从以前的语料库看,最上面的2克是:
2-Gram Frequency
------ ---------
corpus will 5
tricksy corpus 4
or a 3
a very 2
转到3克,整个语料库中只有一个重复的3克,即:
3-Gram Frequency
------ ---------
tricksy corpus will 4
泛化:您不能使用顶部的m-gram直接外推到顶部的(m + 1)-gram。您可以做的是扔掉最底层的m-gram,尤其是根本不重复的m-gram,然后看所有能做到的。这会使范围缩小一点。
答案 4 :(得分:-1)
这可以大大简化。您根本不需要数据库。只需将全文存储在文件中即可。然后编写一个PHP脚本来打开并读取文件内容。使用PHP regex函数提取匹配项。将总数保存在全局变量中。将结果写入另一个文件。而已。