Jak obliczyć cosinusowe podobieństwo dwóch wektorów?

Jak znaleźć cosinusowe podobieństwo między wektorami?

Muszę znaleźć podobieństwo, aby zmierzyć związek między dwoma linijkami tekstu.

Na przykład mam dwa zdania w stylu:

System dla interfejsu użytkownika

User interface machine

... i ich odpowiednie wektory po TF-idf, a następnie normalizacja za pomocą LSI, na przykład [1,0.5] i [0.5,1].

Jak zmierzyć uśmieszek między tymi wektorami?

Author: slhck, 2009-02-06

7 answers

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

Zrobiłem ostatnio kilka rzeczy TF-idf dla mojej jednostki wyszukiwania informacji na Uniwersytecie. Użyłem tej metody Cosinusowego podobieństwa, która wykorzystuje Jama: Java Matrix Package .

Pełny kod źródłowy znajduje się w IR Math with Java : Similarship Measures, naprawdę dobrym zasobie, który obejmuje kilka różnych pomiarów podobieństwa.

 20
Author: Mark Davidson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-02-06 13:42:24

Jeśli chcesz uniknąć polegania na bibliotekach innych firm dla tak prostego zadania, oto prosta implementacja Javy:

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

Zauważ, że funkcja zakłada, że dwa wektory mają tę samą długość. Może chcesz to dokładnie sprawdzić pod kątem bezpieczeństwa.

 44
Author: Alphaaa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-04-07 13:13:28

Spójrz na: http://en.wikipedia.org/wiki/Cosine_similarity .

Jeśli masz wektory A I B.

Podobieństwo jest zdefiniowane jako:

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)

Przykład:

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

cosine(theta) = (0.5 + 0.5) / sqrt(5/4) sqrt(5/4) = 4/5
 30
Author: Toon Krijthe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-28 15:42:01

Dla kodu macierzy w Javie polecam użycie bibliotekiColt . Jeśli masz to, kod wygląda tak (nie testowany ani nawet skompilowany):

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

Powyższy kod można również zmienić, aby użyć jednej z metod Blas.dnrm2() lub Algebra.DEFAULT.norm2() do obliczenia normy. Dokładnie ten sam wynik, który jest bardziej czytelny zależy od smaku.

 5
Author: Nick Fortescue,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-27 02:48:39

Kiedy jakiś czas temu pracowałem z eksploracją tekstu, korzystałem z biblioteki SimMetrics , która zapewnia szeroki zakres różnych metryk w Javie. Jeśli zdarzyło się, że potrzebujesz więcej, to zawsze jest R i CRAN do obejrzenia.

Ale kodowanie go z opisu w Wikipedii jest raczej banalnym zadaniem i może być miłym ćwiczeniem.

 2
Author: Anonymous,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-12 09:35:24

Dla nielicznej reprezentacji wektorów za pomocą Map(dimension -> magnitude) Poniżej znajduje się wersja scala (możesz robić podobne rzeczy w Javie 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
Author: Thamme Gowda,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
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))
}

Wersja Scala

 0
Author: 裴帅帅,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-30 15:31:46