web-dev-qa-db-fra.com

Comment calculer la similarité cosinus de deux vecteurs?

Comment trouver la similarité cosinus entre les vecteurs? 

Je dois trouver la similarité pour mesurer la relation entre deux lignes de texte.

Par exemple, j'ai deux phrases comme:

système d'interface utilisateur 

machine d'interface utilisateur

… Et leurs vecteurs respectifs après tF-idf, suivis d'une normalisation à l'aide de LSI, par exemple [1,0.5] et [0.5,1].

Comment puis-je mesurer la similarité entre ces vecteurs?

29
shiva
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 récemment effectué quelques tâches tf-idf pour mon unité de recherche d'informations à l'université .J'ai utilisé cette méthode de similarité Cosinus qui utilise Jama: Java Matrix Package .

Pour le code source complet, voir Math IR avec Java: Mesures de similarité , une très bonne ressource qui couvre un bon nombre de mesures de similarité différentes. 

20
Mark Davidson

Si vous souhaitez éviter de vous fier à 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 voudrez peut-être vérifier explicitement pour des raisons de sécurité.

46
Alphaaa

Consultez: http://fr.wikipedia.org/wiki/Cosine_similarity .

Si vous avez les vecteurs A et B.

La similitude est définie comme suit:

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
31
Toon Krijthe

Pour le code de matrice en Java, je vous recommande d'utiliser la bibliothèque Colt . Si vous avez cela, le code ressemble à (non testé ni 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 peut également être modifié pour utiliser l'une des méthodes Blas.dnrm2() ou Algebra.DEFAULT.norm2() pour le calcul de la norme. Le même résultat, qui est plus lisible, dépend du goût.

5
Nick Fortescue

Lorsque je travaillais avec l'exploration de texte il y a quelque temps, j'utilisais la bibliothèque SimMetrics qui fournit une vaste gamme de métriques différentes en Java. Si vous aviez besoin de plus, il y a 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 de Nice.

2
Anonymous
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
裴帅帅

Pour la représentation fragmentaire 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
Thamme Gowda