インデックス作成時に TermVector を指定して、Lucene を使用してドキュメントのコレクションをインデックス作成しています。次に、インデックスを読み取り、各ドキュメントの TF-IDF スコア ベクトルを計算することで、用語とその頻度を取得します。次に、TF-IDF ベクトルを使用して、ウィキペディアのコサイン類似度方程式を使用して、ドキュメント間のペアワイズ コサイン類似度を計算します。
これが私の問題です。このコレクションに 2 つの同一のドキュメント「A」と「B」があるとします (A と B には 200 を超える文があります)。AとBの間のペアワイズコサイン類似度を計算すると、コサイン値= 1が得られますが、これは完全に問題ありません。しかし、ドキュメント「B」から 1 つの文を削除すると、これら 2 つのドキュメント間のコサイン類似度は約 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;
}