我想从更大的数据集中计算大型列表的术语频率。
(对)列表的格式为
{
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中时,计算术语频率。
我的挑战是计算时间。我可以运行嵌套循环,但需要很长时间才能完成。只是想知道这种情况有更好的算法吗?
答案 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),其中m
和n
是各个集合的大小。很难说这些集合有多大。这取决于整体术语的频率,以及您是否查询频繁的术语。
答案 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);
}
}
}