计算大数据集上的术语频率

时间:2014-02-04 23:14:52

标签: java algorithm performance text

我想从更大的数据集中计算大型列表的术语频率。

(对)列表的格式为

  

{        
       source_term0,target_term0;
       source_term1,target_term1;
       ......        source_termX,target_termX
}

其中X约为390万。

搜索数据集(对)的格式为

  

{        
       source_sentence0,target_sentence0;
       source_sentence1,target_sentence1;
       ......        source_sentenceY,target_sentenceY
}

Y约为1200万。

当source_termN出现在source_sentenceM中并且target_termN出现在target_sentenceM中时,计算术语频率。

我的挑战是计算时间。我可以运行嵌套循环,但需要很长时间才能完成。只是想知道这种情况有更好的算法吗?

3 个答案:

答案 0 :(得分:1)

执行此操作的一种方法是根据源句和目标语句构建发布列表。也就是说,对于源句子,你有一个字典,其中包含术语和术语出现的源句列表。你对目标句子做同样的事情。

所以给出了这个:

source_sentence1 = "Joe married Sue."
target_sentence1 = "The bridge is blue."
source_sentence2 = "Sue has big feet."
target_sentence2 = "Blue water is best."

然后你有:

source_sentence_terms:
    joe, [1]
    married,[1]
    sue,[1,2]
    has,[2]
    big,[2]
    feet,[2]
target_sentence_temrs
    the,[1]
    bridge,[1]
    is,[1]
    blue,[1,2]
    water,[2]
    is,[2]
    best,[2]

现在您可以浏览搜索字词了。让我们说你的第一对是:

source_term1=sue, target_term1=bridge

你看起来在source_sentence_terms中“起诉”了,你得到了列表[1,2],这意味着该术语出现在这两个源句中。

您在target_sentence_terms中查看“桥接”,并获得列表[1]

现在,您可以在这两个列表上设置交集,然后结束[1]

根据句子构建发布列表是O(n),其中n是所有句子中的单词总数。你只需要做一次。

对于每对,您执行两次哈希表查找。那些是O(1)。设置交集是O(m + n),其中mn是各个集合的大小。很难说这些集合有多大。这取决于整体术语的频率,以及您是否查询频繁的术语。

答案 1 :(得分:0)

想到一个想法:对整个数据集进行排序。基本上,一个好的排序算法是O(nlogn)。你说你目前在O(n ^ 2),所以这将是一个改进。现在,当数据被排序。您可以线性迭代它们。

我不确定我是否理解你的情况,所以这可能不合适。

答案 2 :(得分:0)

Map<String, Map<String, Integer>> terms = new HashMap<>();
for each sourceTerm, targetTerm {
    // Java 7 or earlier
    Map<String, Integer> targetTerms = terms.get(sourceTerm);
    if (targetTerms == null)
        terms.put(sourceTerm, targetTerms = new HashMap<>());
    // Java 8
    Map<String, Integer> targetTerms =
        terms.computeIfAbsent(sourceTerm, HashMap::new);
    targetTerms.put(targetTerm, 0);
}

for each sourceSentence, targetSentence {
    String[] sourceSentenceTerms = sourceSentence.split("\\s+");
    String[] targetSentenceTerms = targetSentence.split("\\s+");
    for (String sourceSentenceTerm : sourceSentenceTerms) {
        for (String targetSentenceTerm : targetSentenceTerms) {
            Map<String, Integer> targetTerms = terms.get(sourceSentenceTerm);
            if (targetTerms != null) {
                // Java 7 or earlier
                Integer termFreq = targetTerms.get(targetSentenceTerm);
                if (termFreq != null)
                    targetTerms.put(targetSentenceTerm, termFreq + 1);
                // Java 8
                targetTerms.computeIfPresent(targetSentenceTerm,
                        (_, f) -> f + 1);
            }
        }
    }