Vraag Hoe bereken ik de cosinusovereenkomst van twee vectoren?


Hoe vind ik de cosinusovereenkomst tussen vectoren?

Ik moet de gelijkenis vinden om de verwantschap tussen twee regels tekst te meten.

Ik heb bijvoorbeeld twee zinnen zoals:

systeem voor gebruikersinterface

gebruikersinterfacemachine

... en hun respectievelijke vectoren na tF-idf, gevolgd door bijvoorbeeld normalisatie met LSI [1,0.5] en [0.5,1].

Hoe meet ik de smiliariteit tussen deze vectoren?


28
2018-02-06 13:15


oorsprong


antwoorden:


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

Ik heb onlangs een aantal tf-idf-dingen gedaan voor mijn eenheid voor informatie-ophalen aan de universiteit. Ik heb deze Cosine Similarity-methode gebruikt Jama: Java Matrix-pakket.

Zie voor de volledige broncode IR Math with Java: similarity Measures, echt een goede bron die een aantal verschillende similariteitsmetingen dekt.


20
2018-02-06 13:42



Als u wilt voorkomen dat u voor zo'n eenvoudige taak vertrouwt op bibliotheken van derden, volgt hier een eenvoudige Java-implementatie:

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

Merk op dat de functie aanneemt dat de twee vectoren dezelfde lengte hebben. Misschien wilt u het op een veilige manier controleren op veiligheid.


42
2018-04-07 13:13



Kijk even naar: http://en.wikipedia.org/wiki/Cosine_similarity.

Als u vector A en B hebt

De gelijkenis wordt gedefinieerd als:

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)

Voorbeeld:

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

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

30
2018-02-06 13:34



Voor matrixcode in Java raad ik aan de Colt bibliotheek. Als je dit hebt, ziet de code eruit (niet getest of zelfs gecompileerd):

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

De bovenstaande code kan ook worden gewijzigd om een ​​van de te gebruiken Blas.dnrm2() methoden of Algebra.DEFAULT.norm2() voor de normberekening. Precies hetzelfde resultaat, dat beter leesbaar is, is afhankelijk van de smaak.


5
2018-02-06 13:28



Toen ik enige tijd geleden met text mining aan het werken was, gebruikte ik de SimMetrics bibliotheek die een uitgebreid scala aan verschillende metrieken in Java biedt. Als het gebeurt dat je meer nodig hebt, dan is er altijd wel R en CRAN kijken naar.

Maar het coderen van de beschrijving in de Wikipedia is een nogal triviale klus en kan een leuke oefening zijn.


2
2017-11-18 22:25



Voor de schaarse weergave van vectoren met Map(dimension -> magnitude) Hier is een scala-versie (je kunt soortgelijke dingen doen in 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