Я создаю классификатор, который должен прочитать много текстовых документов, но я узнал, что мой метод countWordFrequenties
становится медленнее, чем больше документов, которые он обработал. Этот метод внизу занимает 60 мс (на моем ПК), в то время как чтение, нормализация, токенизация, обновление моего словарного запаса и выравнивание различных списков целых чисел занимает всего 3-5 мс (на моем ПК). Мой метод countWordFrequencies
выглядит следующим образом:
public List<Integer> countWordFrequencies(String[] tokens)
{
List<Integer> wordFreqs = new ArrayList<>(vocabulary.size());
int counter = 0;
for (int i = 0; i < vocabulary.size(); i++)
{
for (int j = 0; j < tokens.length; j++)
if (tokens[j].equals(vocabulary.get(i)))
counter++;
wordFreqs.add(i, counter);
counter = 0;
}
return wordFreqs;
}
Каков наилучший способ ускорить этот процесс? В чем проблема этого метода?
Это мой весь класс, есть еще одна категория классов, это хорошая идея опубликовать это также здесь или вам это не нужно?
public class BayesianClassifier
{
private Map<String,Integer> vocabularyWordFrequencies;
private List<String> vocabulary;
private List<Category> categories;
private List<Integer> wordFrequencies;
private int trainTextAmount;
private int testTextAmount;
private GUI gui;
public BayesianClassifier()
{
this.vocabulary = new ArrayList<>();
this.categories = new ArrayList<>();
this.wordFrequencies = new ArrayList<>();
this.trainTextAmount = 0;
this.gui = new GUI(this);
this.testTextAmount = 0;
}
public List<Category> getCategories()
{
return categories;
}
public List<String> getVocabulary()
{
return this.vocabulary;
}
public List<Integer> getWordFrequencies()
{
return wordFrequencies;
}
public int getTextAmount()
{
return testTextAmount + trainTextAmount;
}
public void updateWordFrequency(int index, Integer frequency)
{
equalizeIntList(wordFrequencies);
this.wordFrequencies.set(index, wordFrequencies.get(index) + frequency);
}
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 String normalizeText(String text)
{
String fstNormalized = Normalizer.normalize(text, Normalizer.Form.NFD);
fstNormalized = fstNormalized.replaceAll("[^\\p{ASCII}]","");
fstNormalized = fstNormalized.toLowerCase();
fstNormalized = fstNormalized.replace("\n","");
fstNormalized = fstNormalized.replaceAll("[0-9]","");
fstNormalized = fstNormalized.replaceAll("[/()!?;:,.%-]","");
fstNormalized = fstNormalized.trim().replaceAll(" +", " ");
return fstNormalized;
}
public String[] handleText(String path)
{
String text = readText(path);
String normalizedText = normalizeText(text);
return tokenizeText(normalizedText);
}
public void createCategory(String name, BayesianClassifier bc)
{
Category newCategory = new Category(name, bc);
categories.add(newCategory);
}
public List<String> updateVocabulary(String[] tokens)
{
for (int i = 0; i < tokens.length; i++)
if (!vocabulary.contains(tokens[i]))
vocabulary.add(tokens[i]);
return vocabulary;
}
public List<Integer> countWordFrequencies(String[] tokens)
{
List<Integer> wordFreqs = new ArrayList<>(vocabulary.size());
int counter = 0;
for (int i = 0; i < vocabulary.size(); i++)
{
for (int j = 0; j < tokens.length; j++)
if (tokens[j].equals(vocabulary.get(i)))
counter++;
wordFreqs.add(i, counter);
counter = 0;
}
return wordFreqs;
}
public String[] tokenizeText(String normalizedText)
{
return normalizedText.split(" ");
}
public void handleTrainDirectory(String folderPath, Category category)
{
File folder = new File(folderPath);
File[] listOfFiles = folder.listFiles();
if (listOfFiles != null)
{
for (File file : listOfFiles)
{
if (file.isFile())
{
handleTrainText(file.getPath(), category);
}
}
}
else
{
System.out.println("There are no files in the given folder" + " " + folderPath.toString());
}
}
public void handleTrainText(String path, Category category)
{
long startTime = System.currentTimeMillis();
trainTextAmount++;
String[] text = handleText(path);
updateVocabulary(text);
equalizeAllLists();
List<Integer> wordFrequencies = countWordFrequencies(text);
long finishTime = System.currentTimeMillis();
System.out.println("That took 1: " + (finishTime-startTime)+ " ms");
long startTime2 = System.currentTimeMillis();
category.update(wordFrequencies);
updatePriors();
long finishTime2 = System.currentTimeMillis();
System.out.println("That took 2: " + (finishTime2-startTime2)+ " ms");
}
public void handleTestText(String path)
{
testTextAmount++;
String[] text = handleText(path);
List<Integer> wordFrequencies = countWordFrequencies(text);
Category category = guessCategory(wordFrequencies);
boolean correct = gui.askFeedback(path, category);
if (correct)
{
category.update(wordFrequencies);
updatePriors();
System.out.println("Kijk eens aan! De tekst is succesvol verwerkt.");
}
else
{
Category correctCategory = gui.askCategory();
correctCategory.update(wordFrequencies);
updatePriors();
System.out.println("Kijk eens aan! De tekst is succesvol verwerkt.");
}
}
public void updatePriors()
{
for (Category category : categories)
{
category.updatePrior();
}
}
public Category guessCategory(List<Integer> wordFrequencies)
{
List<Double> chances = new ArrayList<>();
for (int i = 0; i < categories.size(); i++)
{
double chance = categories.get(i).getPrior();
System.out.println("The prior is:" + chance);
for(int j = 0; j < wordFrequencies.size(); j++)
{
chance = chance * categories.get(i).getWordProbabilities().get(j);
}
chances.add(chance);
}
double max = getMaxValue(chances);
int index = chances.indexOf(max);
System.out.println(max);
System.out.println(index);
return categories.get(index);
}
public double getMaxValue(List<Double> values)
{
Double max = 0.0;
for (Double dubbel : values)
{
if(dubbel > max)
{
max = dubbel;
}
}
return max;
}
public void equalizeAllLists()
{
for(Category category : categories)
{
if (category.getWordFrequencies().size() < vocabulary.size())
{
category.setWordFrequencies(equalizeIntList(category.getWordFrequencies()));
}
}
for(Category category : categories)
{
if (category.getWordProbabilities().size() < vocabulary.size())
{
category.setWordProbabilities(equalizeDoubleList(category.getWordProbabilities()));
}
}
}
public List<Integer> equalizeIntList(List<Integer> list)
{
while (list.size() < vocabulary.size())
{
list.add(0);
}
return list;
}
public List<Double> equalizeDoubleList(List<Double> list)
{
while (list.size() < vocabulary.size())
{
list.add(0.0);
}
return list;
}
public void selectFeatures()
{
for(int i = 0; i < wordFrequencies.size(); i++)
{
if(wordFrequencies.get(i) < 2)
{
vocabulary.remove(i);
wordFrequencies.remove(i);
for(Category category : categories)
{
category.removeFrequency(i);
}
}
}
}
}