Frage

Wie kann ich die Cosinus Ähnlichkeit zwischen Vektoren finden?

Ich brauche die Ähnlichkeit zu finden, die Verwandtschaft zwischen zwei Textzeilen zu messen.

Zum Beispiel, ich habe zwei Sätze wie:

  

System zur Benutzeroberfläche

     

Benutzeroberfläche Maschine

... und ihre jeweiligen Vektoren nach TF-IDF, gefolgt von Normalisierung LSI unter Verwendung beispiel [1,0.5] und [0.5,1].

Wie kann ich die smiliarity zwischen diesen Vektoren messen?

War es hilfreich?

Lösung

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

Ich habe einige tf-idf Sachen vor kurzem für meine Information Retrieval Einheit an der Universität. Ich verwenden, um diese Kosinusähnlichkeit Methode, die verwendet Jama. Java Matrix Package

Für den vollständigen Quellcode finden Sie unter IR Math mit Java: Ähnlichkeitsmaß , wirklich gute Ressource, die eine gute paar verschiedene Ähnlichkeitsmessungen abdeckt.

Andere Tipps

Wenn Sie sich auf für eine solche einfache Aufgabe Bibliotheken von Drittanbietern vermeiden wollen, hier ist eine einfache Java-Implementierung:

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

beachten, dass die Funktion geht davon aus, dass die beiden Vektoren die gleiche Länge haben. Vielleicht möchten Sie es explizit für die Sicherheit überprüfen.

Hier finden Sie: http://en.wikipedia.org/wiki/Cosine_similarity .

Wenn Sie Vektoren A und B.

Die Ähnlichkeit ist wie folgt definiert:

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)

Beispiel:

A = (1, 0.5), B = (0.5, 1)

cosine(theta) = (0.5 + 0.5) / sqrt(5/4) sqrt(5/4) = 4/5

Für Matrix-Code in Java würde ich empfehlen die Verwendung von Colt Bibliothek. Wenn Sie diese haben, sieht der Code wie (nicht getestet oder sogar kompiliert):

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

Der obige Code könnte auch eine der Blas.dnrm2() Methoden oder Algebra.DEFAULT.norm2() für die Norm-Berechnung zu verwenden, geändert werden. Genau das gleiche Ergebnis, das besser lesbar ist abhängig von Geschmack ist.

Als ich vor einiger Zeit mit Text Mining arbeitete, wurde ich mit dem SimMetrics Bibliothek, die liefert ein umfangreiches Angebot an verschiedenen Metriken in Java. Wenn es passiert, dass Sie mehr brauchen, dann gibt es immer R und CRAN zu betrachten.

Aber Codierung aus der Beschreibung in der Wikipedia ist eher triviale Aufgabe, und kann eine nette Übung sein.

Für die dünn besetzte Darstellung von Vektoren Map(dimension -> magnitude) Hier ist eine scala-Version (Sie können in Java 8 ähnliche Dinge tun)

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

scala Version

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top