gpt4 book ai didi

java - 检测字符串中 n-grams 的更快方法?

转载 作者:行者123 更新时间:2023-11-29 06:05:25 30 4
gpt4 key购买 nike

我在 SO 上找到了这个解决方案来检测字符串中的 n-gram:(此处:N-gram generation from a sentence)

import java.util.*;

public class Test {

public static List<String> ngrams(int n, String str) {
List<String> ngrams = new ArrayList<String>();
String[] words = str.split(" ");
for (int i = 0; i < words.length - n + 1; i++)
ngrams.add(concat(words, i, i+n));
return ngrams;
}

public static String concat(String[] words, int start, int end) {
StringBuilder sb = new StringBuilder();
for (int i = start; i < end; i++)
sb.append((i > start ? " " : "") + words[i]);
return sb.toString();
}

public static void main(String[] args) {
for (int n = 1; n <= 3; n++) {
for (String ngram : ngrams(n, "This is my car."))
System.out.println(ngram);
System.out.println();
}
}
}

=> 与毫秒相比,这段代码花费了迄今为止最长的处理时间(检测 1-grams、2-grams、3-grams 和 4grams 我的语料库为 28 秒:4Mb 原始文本)用于其他操作(删除停用词等)

有人知道 Java 中的解决方案比上面介绍的循环解决方案运行速度更快吗? (我在考虑多线程、集合的使用,或者拆分字符串的创造性方法……?)谢谢!

最佳答案

你可以尝试这样的事情:

public class NGram {

private final int n;
private final String text;

private final int[] indexes;
private int index = -1;
private int found = 0;

public NGram(String text, int n) {
this.text = text;
this.n = n;
indexes = new int[n];
}

private boolean seek() {
if (index >= text.length()) {
return false;
}
push();
while(++index < text.length()) {
if (text.charAt(index) == ' ') {
found++;
if (found<n) {
push();
} else {
return true;
}
}
}
return true;
}

private void push() {
for (int i = 0; i < n-1; i++) {
indexes[i] = indexes[i+1];
}
indexes[n-1] = index+1;
}

private List<String> list() {
List<String> ngrams = new ArrayList<String>();
while (seek()) {
ngrams.add(get());
}
return ngrams;
}

private String get() {
return text.substring(indexes[0], index);
}
}

在大约 5mb 的文本上进行测试,它的执行速度似乎比原始代码快 10 倍。这里的主要区别是正则表达式不用于拆分,ngram 字符串不是通过连接创建的。

更新:这是我在上面提到的文本 ngram 1-4 上运行时得到的输出。我使用 2GB 内存运行,以确定运行期间对 GC 的影响。跑了好多次看hotspot编译器的效果。

Loop 01 Code mine ngram 1 time 071ms ngrams 294121
Loop 01 Code orig ngram 1 time 534ms ngrams 294121
Loop 01 Code mine ngram 2 time 016ms ngrams 294120
Loop 01 Code orig ngram 2 time 360ms ngrams 294120
Loop 01 Code mine ngram 3 time 082ms ngrams 294119
Loop 01 Code orig ngram 3 time 319ms ngrams 294119
Loop 01 Code mine ngram 4 time 014ms ngrams 294118
Loop 01 Code orig ngram 4 time 439ms ngrams 294118

Loop 10 Code mine ngram 1 time 013ms ngrams 294121
Loop 10 Code orig ngram 1 time 268ms ngrams 294121
Loop 10 Code mine ngram 2 time 014ms ngrams 294120
Loop 10 Code orig ngram 2 time 323ms ngrams 294120
Loop 10 Code mine ngram 3 time 013ms ngrams 294119
Loop 10 Code orig ngram 3 time 412ms ngrams 294119
Loop 10 Code mine ngram 4 time 014ms ngrams 294118
Loop 10 Code orig ngram 4 time 423ms ngrams 294118

关于java - 检测字符串中 n-grams 的更快方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8701610/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com