У меня есть коллекция текстовых документов в индексе Lucene. В индексе чуть более 4 000 000 документов. Программа выполняет поиск на основе пользовательского запроса и возвращает N документов, соответствующих запросу. Затем идея состоит в том, чтобы выполнить вычисление взаимной информации для терминов в N документах и найти термины, которые тесно связаны с коллекцией в целом.
По сути, по запросу «компьютер» программа должна вернуть список таких терминов, как «компьютер, сеть, программист, клиент, сервер» и так далее. Это должно работать в теории, но я никогда не получаю ожидаемого результата, и я не могу сказать, просто ли я его неправильно реализую, или есть что-то в моих коллекциях, что делает это неэффективным.
Это код:
public class CoOccurrence {
private Map<String, Double> cooccurrenceMatrix = new HashMap<String, Double>();
private int n;
private List<String> terms = new ArrayList<String>();
public CoOccurrence(List<String> abstracts){
n = abstracts.size();
for(int i = 0; i < abstracts.size(); i++){
String[] line = abstracts.get(i).split(" ");
for(String word: line){
if(!Utils.containsDigits(word)){
if(!terms.contains(word)){
terms.add(word);
}
}
}
}
getMutualInformation(abstracts);
}
private void getMutualInformation(List<String> abstracts){
double n = this.n;
double sum;
for(int f1 = 0; f1 < terms.size()-1; f1++){
sum = 0;
for(int f2 = f1 + 1; f2 < terms.size(); f2++){
Bigram bigram = new Bigram(terms.get(f1), terms.get(f2));
//Fetch number of documents that contains both term.f1 and term.f2
double p_xy = docsContainingXandY(bigram, abstracts) / n;
//Fetch number of documents containing term.f1
double p_x = docsContainingX(bigram, abstracts) / n;
//Fetch number of documents containing term.f2
double p_y = docsContainingY(bigram, abstracts) / n;
sum += (p_xy) * Utils.logWithoutNaN( p_xy / (p_x * p_y) );
}
cooccurrenceMatrix.put(terms.get(f1), sum);
}
}
}
Может ли кто-нибудь увидеть, что я выполняю расчеты каким-то ошибочным образом или какие-либо другие ошибки или недоразумения, которые мешают желаемому результату?
РЕДАКТИРОВАТЬ: класс Bigram представляет собой простую оболочку, содержащую две строки: String x, String y.
Класс Util содержит много разных задач, но logWithoutNaN выглядит так:
public static double logWithoutNaN(double value) {
if (value == 0) {
return Math.log(EPSILON);
} else if (value < 0) {
return 0;
}
return Math.log(value);
}
Где ЭПСИЛОН = 0,000001
Что касается вывода: Поиск по слову «компьютер» дает 20 терминов, которые должны быть релевантными, но (в основном) таковыми не являются: дать ассоциации наука дать"
BigGram
иUtils
. Что за ошибка или плохой результат? Предоставьте дополнительную информацию, например трассировку стека. - person aliteralmind   schedule 06.02.2014