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?

28
demandé sur slhck 2009-02-06 16:15:35

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é.

20
répondu Mark Davidson 2009-02-06 13:42:24

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é.

44
répondu Alphaaa 2014-04-07 13:13:28

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
30
répondu Toon Krijthe 2016-02-28 15:42:01

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.

5
répondu Nick Fortescue 2013-05-27 02:48:39

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.

2
répondu Anonymous 2015-11-12 09:35:24

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))
}
0
répondu Thamme Gowda 2016-11-18 22:49:42
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

0
répondu 裴帅帅 2018-09-30 15:31:46