2016-07-11 45 views
2

我使用了一個使用armadillo C++線性庫的餘弦相似函數。我的代碼是下一個:使用Armadillo C++的餘弦相似性給我帶來負面結果

double cosine_similarity(rowvec A, rowvec B) 
{ 
    double dot = as_scalar(A*B.t()); 
    double denomA = as_scalar(A*A.t()); 
    double denomB = as_scalar(B*B.t()); 
    return dot/(sqrt(denomA) * sqrt(denomB)) ; 
} 

我有此矩陣作爲一個例子:

-0.0261 -0.6780 -0.7338 0.0345

-0.0230 0.0082 -0.0400 -0.7056

-0.2590 -0.7052 0.6590 -0.0371

-0.9650 0.2072 -0.1551 0.0426

-0.0230 0.0082 -0.0400 -0.7056

當我計算第二行之間的餘弦相似性VS所有的i行得到的結果如下:

相似度[1,0]:-1.07944e-16

相似度[1,1]:1

相似度[1,2]:-1.96262e-17

相似度[1,3]:-1.71729e-16

相似度[1,2 4 ]:1

這是正確的嗎?即使他們的意思是零,我也擔心負面結果。我想知道如果我做錯了什麼。 cosine_similarity用於這種方式:

for (unsigned int row = 0; row < redV.n_rows ; row++) 
{ 
    double ans = cosine_similarity(redV.row(indicate), redV.row(row)); 
    cout << "Similarity [" << indicate << "," << row << "]: " << ans << endl; 
    cout << "Similarity [" << indicate << "," << row << "]: " << norm_dot(redV.row(indicate), redV.row(row)) << endl; 
} 
+0

爲什麼不只是使用[norm_dot()](http://arma.sourceforge.net/docs。 html#dot)函數呢? – hbrerkere

+0

謝謝你的建議。我想到了同樣的結果。當sm在matlab上做同樣的計算時,我得到的數字略有不同.. –

+1

您還沒有顯示完整的代碼。計算'相似性[1,0]'的代碼是什麼?顯示如何使用'cosine_similarity()'的具體示例。 – hbrerkere

回答

1

你的代碼似乎是正確的,你只是遇到機器精度問題。 A*B.t()A第三行和B第二行(反之亦然)應該爲零但不是,但在機器精度內。 Scipy’s cosine有同樣的問題:

In [10]: from scipy.spatial.distance import cosine 

In [11]: 1 - cosine([-0.2590, -0.7052, 0.6590, -0.0371], [-0.0230, 0.0082, -0.0400, -0.7056]) 
Out[11]: -1.114299639159988e-05 # <=============== should not be negative! 

(我用1減去的只是因爲SciPy的是如何定義cosine因爲你發佈的只有四個小數這個答案不匹配你點,但點睛之筆,它是消極的。 )

如果你想檢查浮點數x是否是另一個y機器精度內,比較其與std::numeric_limits::epsilon差異。請參閱almost_equal here的定義。您可能想要cosine_similarity檢查結果是否爲almost_equal爲0或1,在這種情況下返回0或1.