Comment calculer la similitude cosinus de deux vecteurs?
Comment trouver la similitude de cosinus entre les vecteurs?
je dois trouver la similitude pour mesurer la parenté entre deux lignes de texte.
Par exemple, j'ai deux phrases comme:
système d'interface utilisateur
machine à interface utilisateur
... et leurs vecteurs respectifs après TF-idf, suivie d'une normalisation par LSI, pour exemple
[1,0.5]
et [0.5,1]
.
Comment mesurer la smiliarité entre ces vecteurs?
7 réponses
public class CosineSimilarity extends AbstractSimilarity {
@Override
protected double computeSimilarity(Matrix sourceDoc, Matrix targetDoc) {
double dotProduct = sourceDoc.arrayTimes(targetDoc).norm1();
double eucledianDist = sourceDoc.normF() * targetDoc.normF();
return dotProduct / eucledianDist;
}
}
j'ai fait des trucs TF-idf récemment pour mon Unité de recherche D'Information à L'Université. J'ai utilisé cette méthode de similitude cosinus qui utilise Jama: Java Matrix Package .
Pour le code source complet voir IR Mathématiques avec Java : Mesures de Similarité , vraiment bonne ressource qui couvre un bon nombre de différentes mesures de similarité.
si vous voulez éviter de compter sur des bibliothèques tierces pour une tâche aussi simple, voici une implémentation Java simple:
public static double cosineSimilarity(double[] vectorA, double[] vectorB) {
double dotProduct = 0.0;
double normA = 0.0;
double normB = 0.0;
for (int i = 0; i < vectorA.length; i++) {
dotProduct += vectorA[i] * vectorB[i];
normA += Math.pow(vectorA[i], 2);
normB += Math.pow(vectorB[i], 2);
}
return dotProduct / (Math.sqrt(normA) * Math.sqrt(normB));
}
Notez que la fonction suppose que les deux vecteurs ont la même longueur. Vous pouvez explicitement en vérifier la sécurité.
regardez: http://en.wikipedia.org/wiki/Cosine_similarity .
si vous avez des vecteurs A et B.
la similitude est définie comme:
cosine(theta) = A . B / ||A|| ||B||
For a vector A = (a1, a2), ||A|| is defined as sqrt(a1^2 + a2^2)
For vector A = (a1, a2) and B = (b1, b2), A . B is defined as a1 b1 + a2 b2;
So for vector A = (a1, a2) and B = (b1, b2), the cosine similarity is given as:
(a1 b1 + a2 b2) / sqrt(a1^2 + a2^2) sqrt(b1^2 + b2^2)
exemple:
A = (1, 0.5), B = (0.5, 1)
cosine(theta) = (0.5 + 0.5) / sqrt(5/4) sqrt(5/4) = 4/5
pour le code matriciel en Java, je recommande d'utiliser la bibliothèque Colt . Si vous avez ceci, le code ressemble à (pas testé ou même compilé):
DoubleMatrix1D a = new DenseDoubleMatrix1D(new double[]{1,0.5}});
DoubleMatrix1D b = new DenseDoubleMatrix1D(new double[]{0.5,1}});
double cosineDistance = a.zDotProduct(b)/Math.sqrt(a.zDotProduct(a)*b.zDotProduct(b))
le code ci-dessus pourrait également être modifié pour utiliser l'une des méthodes Blas.dnrm2()
ou Algebra.DEFAULT.norm2()
pour le calcul de la norme. Exactement le même résultat, qui est plus lisible dépend de goût.
quand je travaillais avec l'exploration de texte il y a quelque temps, j'utilisais la bibliothèque SimMetrics qui fournit une vaste gamme de mesures différentes en Java. S'il s'est passé que vous avez besoin de plus, alors il ya toujours R et CRAN à regarder.
mais le coder à partir de la description dans Wikipedia est une tâche plutôt triviale, et peut être un exercice agréable.
pour la représentation clairsemée des vecteurs utilisant Map(dimension -> magnitude)
Voici une version scala (vous pouvez faire des choses similaires en Java 8)
def cosineSim(vec1:Map[Int,Int],
vec2:Map[Int,Int]): Double ={
val dotProduct:Double = vec1.keySet.intersect(vec2.keySet).toList
.map(dim => vec1(dim) * vec2(dim)).sum
val norm1:Double = vec1.values.map(mag => mag * mag).sum
val norm2:Double = vec2.values.map(mag => mag * mag).sum
return dotProduct / (Math.sqrt(norm1) * Math.sqrt(norm2))
}
def cosineSimilarity(vectorA: Vector[Double], vectorB: Vector[Double]):Double={
var dotProduct = 0.0
var normA = 0.0
var normB = 0.0
var i = 0
for(i <- vectorA.indices){
dotProduct += vectorA(i) * vectorB(i)
normA += Math.pow(vectorA(i), 2)
normB += Math.pow(vectorB(i), 2)
}
dotProduct / (Math.sqrt(normA) * Math.sqrt(normB))
}
def main(args: Array[String]): Unit = {
val vectorA = Array(1.0,2.0,3.0).toVector
val vectorB = Array(4.0,5.0,6.0).toVector
println(cosineSimilarity(vectorA, vectorA))
println(cosineSimilarity(vectorA, vectorB))
}
version scala