2010-02-23 141 views
3

我開發了一些基於TF * IDF的java程序來計算餘弦相似度。它工作得很好。但有一個問題.... :(java餘弦相似度問題

例如: 如果我有以下兩個矩陣,我要計算餘弦相似度它不起作用爲行長度不

doc 1 
1 2 3 
4 5 6 

doc 2 
1 2 3 4 5 6 
7 8 5 2 4 9 

相同如果行和colums的長度是相同的,然後我的程序工作得很好,但它沒有,如果行和列不在相同的長度。

任何提示???

回答

3

我不知道你的實現,但cosine distance的兩個向量等於這些向量的歸一化點積。

兩個矩陣的點積可以表示爲a。 b = a T b。因此,如果矩陣具有不同的長度,則不能用點積來標識餘弦。

現在使用標準的TF * IDF方法時,矩陣中的術語應該由term, document索引,因此任何未出現在文檔中的術語在矩陣中應顯示爲零。

現在你的設置方式似乎表明你的兩個文檔有兩個不同的矩陣。我不確定這是否是您的意圖,但似乎不正確。

另一方面,如果你的矩陣之一應該是你的查詢,那麼它應該是一個向量而不是矩陣,以便轉置產生正確的結果。

TF-IDF的完整解釋如下:

好吧,在經典的TF-IDF你構建一個術語文檔矩陣a。矩陣a中的每個值的特徵爲 i,j其中i是該術語並且j是該文件。該值是本地,全局和歸一化權重的組合(儘管如果您規範化文檔,則歸一化權重應爲1)。因此,一個 I,J = F I,J * d/d ,其中f I,J是字i在DOC j頻率,D是文檔尺寸,和d 是其中包含術語i的文檔的數量。

您的查詢是指定爲0​​的術語的向量。對於您的查詢中的每個術語b i,q參考查詢q的術語i。 b i,q = f i,q其中f i,q是查詢q中的術語i的頻率。在這種情況下,每個查詢都是一個向量,多個查詢形成一個矩陣。

然後,我們可以計算每個單位向量,以便當我們取得點積時,它將產生正確的餘弦。爲了實現單位矢量,我們將矩陣a和查詢b除以它們的Frobenius norm

最後,我們可以通過對給定查詢採用向量b的轉置來執行餘弦距離。因此每個計算一個查詢(或向量)。這表示爲b T a。最終結果是一個向量,每個術語的得分越高,得分越高表示文檔等級越高。

+0

謝謝您的回答。是的,我的第一個矩陣是查詢。什麼是差異。查詢和向量之間?它們不是幾乎一樣嗎?我使用一個文檔作爲查詢,第二個作爲目標。這就是我分別爲目標計算tf * idf和爲查詢計算tf * idf的原因。我不能使用transponse因爲我不知道確切的列和行數。這只是一個例子:)問題。你能解釋一下我該怎麼解決我的問題?我應該爲查詢和目標創建一個tf * idf嗎?如果是,那麼我將如何計算餘弦? – user238384 2010-02-23 04:12:18

+0

我會嘗試添加到我的答案 – tzenes 2010-02-23 04:49:56

+0

@agazerboy是否足夠或您需要更多的解釋? – tzenes 2010-02-27 21:31:41

3

簡單的java餘弦相似

static double cosine_similarity(Map<String, Double> v1, Map<String, Double> v2) { 
      Set<String> both = Sets.newHashSet(v1.keySet()); 
      both.removeAll(v2.keySet()); 
      double sclar = 0, norm1 = 0, norm2 = 0; 
      for (String k : both) sclar += v1.get(k) * v2.get(k); 
      for (String k : v1.keySet()) norm1 += v1.get(k) * v1.get(k); 
      for (String k : v2.keySet()) norm2 += v2.get(k) * v2.get(k); 
      return sclar/Math.sqrt(norm1 * norm2); 
    }