2016-07-11 11 views
2

Ich habe eine Cosinus-Ähnlichkeitsfunktion implemented, die Armadillo C++ lineare Bibliothek verwendet. Mein Code ist der nächste:Cosinusähnlichkeit mit Armadillo C++ gibt mir negative Ergebnisse

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)) ; 
} 

Ich habe diese Matrix als Beispiel:

-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

Wenn I berechnen die Cosinus Ähnlichkeit zwischen der zweiten Reihe vs alle Zeilen i erhalten die folgenden Ergebnisse:

Similarity [1,0]: -1.07944e-16

Similarity [1,1]: 1

Similarity [1,2]: -1.96262e-17

Similarity [1,3]: -1.71729e-16

Ähnlichkeit [1, 4 ]: 1

Ist das korrekt? Mache mir Sorgen um die negativen Ergebnisse, auch wenn sie meinen, dass sie null sind. Ich frage mich, ob ich etwas falsch mache. cosine_similarity wird auf diese Weise verwendet:

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

warum nicht einfach die [norm_dot()] (http://arma.sourceforge.net/docs. html # dot) Funktion stattdessen? – hbrerkere

+0

Vielen Dank für den Hinweis. Ich bekomme die gleichen Ergebnisse. Wenn ich die gleichen Berechnungen auf Matlab mache, bekomme ich etwas andere Zahlen. –

+1

Sie haben Ihren gesamten Code nicht angezeigt. Wie lautet der Code für die Berechnung von "Similarity [1,0]"? Zeigen Sie ein konkretes Beispiel dafür, wie 'cosine_similarity()' verwendet wird. – hbrerkere

Antwort

1

Ihr Code scheint richtig zu sein, Sie stoßen gerade auf Maschinenpräzisionsprobleme. A*B.t() für A die dritte Zeile und B für die zweite Zeile (oder umgekehrt) sollte Null sein, ist aber nicht, aber ist innerhalb der Maschinengenauigkeit. Scipy’s cosine hat das gleiche Problem.

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! 

(I um 1 nur abziehen, weil, wie Scipy definiert cosine Und diese Antwort ist Ihnen nicht überein, weil Sie nur vier Dezimalstellen geschrieben Punkte, aber die Pointe ist, ist es negativ.)

Wenn Sie überprüfen möchten, ob eine Fließkommazahl x innerhalb der Maschinengenauigkeit eines anderen y liegt, vergleichen Sie deren Unterschied mit std::numeric_limits::epsilon. Siehe die Definition von almost_equal here. Vielleicht möchten Sie cosine_similarity überprüfen, ob das Ergebnis almost_equal auf 0 oder 1 ist, in diesem Fall geben Sie 0 oder 1 zurück.

Verwandte Themen