【发布时间】:2016-03-26 15:09:38
【问题描述】:
我做了一个分类器,你首先用一个包含 A 类文本的文件夹训练分类器,然后用一个包含 B 类文本的文件夹训练分类器。之后,你给分类器一个测试文本,分类器应该猜对A 或 B 类(或 C 或 D ......如果你有更多类别)。
但是,这个程序在某种程度上非常慢,虽然它应该只需要几秒钟,但需要 10 多分钟。我认为故障出在阅读器的某个地方,因为我在步骤之间设置了计时器,这样我就可以找到它。我发现是这两种方法可能导致问题:
public String readText(String path) {
BufferedReader br;
String result = "";
try {
br = new BufferedReader(new FileReader(path));
StringBuilder sb = new StringBuilder();
String line = br.readLine();
while (line != null) {
sb.append(line);
sb.append("\n");
line = br.readLine();
}
result = sb.toString();
br.close();
} catch (IOException e) {
e.printStackTrace();
}
return result;
}
这是读取一个路径的文本并给出结果的方法。 (上)
public void handleTrainDirectory(String folderPath, Category category) {
File folder = new File(folderPath);
File[] listOfFiles = folder.listFiles();
for (File file : listOfFiles){
if (file.isFile()) {
handleTrainText(file.getPath(), category);
}
}
}
这个东西循环遍历我提供的整个文件夹,并完成每个文本所需的所有事情。 (上)
public void handleTrainText(String path, Category category) {
String[] text = handleText(path);
makeVocabulary(text);
List<Integer> wordFrequencies = countWordFrequencies(text);
Text newText = new Text(path, category, wordFrequencies);
trainTexts.add(newText);
}
这就是 handleTrainText 对每个文本所做的事情。 (上)
为了让这篇文章不会太长,我不会在这里给出所有方法,因为我认为失败是在这些方法中的某个地方。如果您想查看我立即提供的其他方法之一,但现在我尽量使这篇文章尽可能清晰。
仅供参考:我正在为一个目录执行此操作,其中只有 300 个小文本文件,单线程,应该只需要几秒钟。
PS:对不起我糟糕的英语,不是我的母语。
编辑:因为你们不太清楚这里发生了什么是由 handleTrainText 调用的其他方法:
public String[] handleText(String path) {
String text = readText(path);
String normalizedText = normalizeText(text);
return tokenizeText(normalizedText);
}
public String normalizeText(String text) {
String fstNormalized = Normalizer
.normalize(text, Normalizer.Form.NFD)
.replaceAll("[^\\p{ASCII}]", "")
.toLowerCase()
.replace("\n", "")
.replaceAll("[0-9]", "")
.replaceAll("[!?;:,.%]", "");
return fstNormalized;
}
public String[] tokenizeText(String normalizedText) {
return normalizedText.split(" ");
}
public List<String> makeVocabulary(String[] tokens) {
for (int i = 0; i < tokens.length; i++)
if (!vocabulary.contains(tokens[i]))
vocabulary.add(tokens[i]);
return vocabulary;
}
【问题讨论】:
-
我的建议是将流直接提供给解析逻辑,无需将所有这些都保存在内存中。加载多个文件后,问题可能是频繁的 GC。
-
所以如果我理解正确的话,程序的所有功能都用一个大方法完成吗?让 Java 更快?
-
我没有看完你的代码,但是从不需要一个大方法,因为你总是可以将一个方法拆分成多个
final方法,这些方法链接起来-互相打电话。 -
Wat 是在 Google 上搜索的“GCs”,但没有逻辑结果 :-)。对不起各位,我是初学者。
-
@TotalCare 我不确定 handleText 的作用。我假设它调用 readText。您在 StringBuilders 中保留文本记忆,而不是直接使用它们来构建您的词汇表。根据您的算法,countWordFrequencies 和 makeVocabulary 需要一段时间。请打印这些在交互之间完成所需的时间。
标签: java performance file-io classification bufferedreader