我通過在索引時指定TermVector來使用Lucene索引一組文檔。 然後,我通過閱讀索引並計算每個文檔的TF-IDF分數向量來檢索詞條及其頻率。然後,使用TF-IDF向量,我使用Wikipedia's cosine similarity equation計算文檔之間的成對餘弦相似度。使用Lucene計算文檔相似度的更好方法
這是我的問題:說我在這個集合中有兩個相同的文檔「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;
}
我想你的代碼有些問題。從200個句子中刪除一個句子應該給你一個> 0.98的數字。爲了驗證它,你可以生成一個隨機矢量,對矢量進行修改並計算餘弦相似度,以查看你得到的結果。對於大小爲1000的矢量和在[10,100]範圍內的隨機數,如果我從矢量中的所有數中減去範圍[10,20]中的一個隨機數,那麼對於我來說,所得到的相似性度量總是> 0.98。 – Helium
我使用Mathematica來驗證案例。這是我的代碼:a = RandomInteger [{10,100},1000]; b = a - RandomInteger [{10,20},1000]; {總計[a],總計[b],總計[a - b], N [(a。b)/(Norm [a] Norm [b])]},這裏是輸出:{55419,40271,15148,0.98811} – Helium
@Mohsen刪除矢量B中的一個句子將減少該矢量中的元素數如果我們在刪除句子後得到一個尺寸爲1000的矢量,矢量B的大小將變成995,現在矢量A的大小爲1000,但是兩個矢量也不會對齊。通過刪除句子,矢量元素從中間移除,但不從矢量的末尾移除。所以如果你可以嘗試從中間刪除矢量元素,你可以觀察0.85值 – Kasun