Я индексирую набор документов с помощью Lucene, указывая TermVector во время индексирования. Затем я извлекаю термины и их частоту, читая индекс и вычисляя векторы оценок TF-IDF для каждого документа. Затем, используя векторы TF-IDF, я вычисляю попарное косинусное сходство между документами, используя уравнение косинусного сходства Википедии .
Это моя проблема: скажем, у меня есть два идентичных документа «A» и «B» в этой коллекции (A и B содержат более 200 предложений). Если я вычисляю попарное косинусное сходство между A и B, это дает мне значение косинуса = 1, что совершенно нормально. Но если я удалю одно предложение из документа «B», это даст мне значение косинусного сходства около 0,85 между этими двумя документами. Документы почти аналогичны, но значения косинуса - нет. Я понимаю, что проблема в уравнении, которое я использую.
Есть ли лучший способ / уравнение, которое я могу использовать для вычисления косинусного сходства между документами?
Отредактировано
Вот как я вычисляю косинусное сходство, doc1[]
и doc2[]
- это векторы TF-IDF для соответствующего документа. вектор содержит только scores
, но не words
private double cosineSimBetweenTwoDocs(float doc1[], float doc2[]) {
double temp;
int doc1Len = doc1.length;
int doc2Len = doc2.length;
float numerator = 0;
float temSumDoc1 = 0;
float temSumDoc2 = 0;
double equlideanNormOfDoc1 = 0;
double equlideanNormOfDoc2 = 0;
if (doc1Len > doc2Len) {
for (int i = 0; i < doc2Len; i++) {
numerator += doc1[i] * doc2[i];
temSumDoc1 += doc1[i] * doc1[i];
temSumDoc2 += doc2[i] * doc2[i];
}
equlideanNormOfDoc1=Math.sqrt(temSumDoc1);
equlideanNormOfDoc2=Math.sqrt(temSumDoc2);
} else {
for (int i = 0; i < doc1Len; i++) {
numerator += doc1[i] * doc2[i];
temSumDoc1 += doc1[i] * doc1[i];
temSumDoc2 += doc2[i] * doc2[i];
}
equlideanNormOfDoc1=Math.sqrt(temSumDoc1);
equlideanNormOfDoc2=Math.sqrt(temSumDoc2);
}
temp = numerator / (equlideanNormOfDoc1 * equlideanNormOfDoc2);
return temp;
}