it-swarm.com.de

Kann jemand auf eine sehr einfache, grafische Weise ein Beispiel für Cosinus-Ähnlichkeit geben?

Cosine-Ähnlichkeitsartikel auf Wikipedia

Können Sie die Vektoren hier (in einer Liste oder in etwas) anzeigen, und dann die Berechnungen durchführen und uns zeigen lassen, wie es funktioniert?

Ich bin ein Anfänger.

173
TIMEX

Hier sind zwei sehr kurze Texte zum Vergleich:

  1. Julie loves me more than Linda loves me

  2. Jane likes me more than Julie loves me

Wir möchten wissen, wie ähnlich diese Texte sind, rein in Bezug auf die Anzahl der Wörter (und die Reihenfolge der Wörter ignorieren). Wir beginnen mit einer Liste der Wörter aus beiden Texten:

me Julie loves Linda than more likes Jane

Jetzt zählen wir, wie oft jedes dieser Wörter in jedem Text vorkommt:

   me   2   2
 Jane   0   1
Julie   1   1
Linda   1   0
likes   0   1
loves   2   1
 more   1   1
 than   1   1

Wir sind jedoch nicht an den Wörtern selbst interessiert. Wir sind nur an diesen beiden vertikalen Vektoren der Zählungen interessiert. Zum Beispiel gibt es zwei Instanzen von 'Me' in jedem Text. Wir werden entscheiden, wie nahe diese beiden Texte aneinander liegen, indem wir eine Funktion dieser beiden Vektoren berechnen, nämlich den Cosinus von _ dem Winkel zwischen ihnen. 

Die zwei Vektoren sind wiederum:

a: [2, 0, 1, 1, 0, 2, 1, 1]

b: [2, 1, 1, 0, 1, 1, 1, 1]

Der Cosinus des Winkels zwischen ihnen beträgt etwa 0,822.

Diese Vektoren sind 8-dimensional. Die Verwendung der Cosinus-Ähnlichkeit hat eindeutig den Vorteil, dass sie eine Frage, die über die menschliche Fähigkeit zur Visualisierung hinausgeht, in eine mögliche Frage umwandelt. In diesem Fall können Sie sich dies als einen Winkel von etwa 35 Grad vorstellen, der eine gewisse Entfernung von Null oder perfekte Übereinstimmung ist.

409
Bill Bell

Ich nehme an, Sie sind mehr daran interessiert, einen Einblick in ", warum " die Cosinus-Ähnlichkeit funktioniert (warum sie einen guten Hinweis auf Ähnlichkeit liefert), als " wie "es berechnet wird (die spezifischen Operationen, die für die Berechnung verwendet werden). Wenn Sie an letzterem interessiert sind, lesen Sie die von Daniel in diesem Beitrag angegebene Referenz sowie eine verwandte SO Frage .

Um sowohl das Wie als auch das Warum zu erklären, ist es zunächst sinnvoll, das Problem zu vereinfachen und nur in zwei Dimensionen zu arbeiten. Sobald Sie dies in 2D erhalten haben, ist es einfacher, es in drei Dimensionen zu denken, und es ist natürlich schwieriger, es sich in vielen weiteren Dimensionen vorzustellen. Bis dahin können wir jedoch die lineare Algebra verwenden, um die numerischen Berechnungen durchzuführen und uns dabei zu helfen, in Begriffen zu denken von Linien/Vektoren/"Ebenen"/"Kugeln" in n Dimensionen, obwohl wir diese nicht zeichnen können.

Also, in zwei Dimensionen: In Bezug auf die Ähnlichkeit des Textes bedeutet dies, dass wir uns auf zwei verschiedene Begriffe konzentrieren, die Wörter "London" und "Paris" sagen, und wir würden jedes Mal zählen, wie oft Diese Wörter befinden sich in jedem der beiden Dokumente, die wir vergleichen möchten. Dies gibt uns für jedes Dokument einen Punkt in der x-y-Ebene. Wenn beispielsweise Doc1 einmal Paris und viermal London hatte, würde ein Punkt bei (1,4) dieses Dokument darstellen (im Hinblick auf diese winzige Bewertung von Dokumenten). In Vektoren ausgedrückt wäre dieses Dokument Doc1 ein Pfeil, der vom Ursprung zum Punkt (1,4) führt. Überlegen wir uns vor diesem Hintergrund, was es bedeutet, wenn zwei Dokumente ähnlich sind und in welcher Beziehung sie zu den Vektoren stehen.

SEHR ähnliche Dokumente (wiederum in Bezug auf diesen begrenzten Satz von Dimensionen) hätten die gleiche Anzahl von Verweisen auf Paris UND die gleiche Anzahl von Verweisen auf London, oder vielleicht könnten sie das gleiche Verhältnis dieser Verweise haben. Ein Dokument, Doc2, mit 2 Verweisen auf Paris und 8 Verweisen auf London, wäre ebenfalls sehr ähnlich, nur mit einem möglicherweise längeren Text oder einer irgendwie sich wiederholenden Bezeichnung der Städte, aber in demselben Verhältnis. Vielleicht sind beide Dokumente Reiseführer über London und beziehen sich nur auf Paris (und wie unsinnig diese Stadt ist ;-) Ich mache nur Spaß !!!.

Weniger ähnliche Dokumente können nun auch Verweise auf beide Städte enthalten, jedoch in unterschiedlichen Anteilen. Vielleicht würde Doc2 Paris nur einmal und London siebenmal zitieren.

Zurück zu unserer xy-Ebene Wenn wir diese hypothetischen Dokumente zeichnen, sehen wir, dass, wenn sie SEHR ähnlich sind, sich ihre Vektoren überlappen (obwohl einige Vektoren länger sein können) und wenn sie anfangen, weniger gemeinsam zu haben divergieren diese Vektoren, um einen größeren Winkel zwischen ihnen zu haben.

Indem wir den Winkel zwischen den Vektoren, können wir eine gute Vorstellung von ihrer Ähnlichkeit bekommen und die Dinge noch einfacher machen, indem wir den Cosinus davon nehmen Winkel, wir haben einen Nice 0 zu 1 oder -1 zu 1 Wert, der diese Ähnlichkeit anzeigt, je nachdem, was und wie wir erklären. Je kleiner der Winkel, desto größer (näher an 1) der Kosinuswert und desto höher die Ähnlichkeit.

Im Extremfall haben die Dokumente absolut nichts gemeinsam, wenn Doc1 nur Paris und Doc2 nur London zitiert. Doc1 hat seinen Vektor auf der x-Achse, Doc2 auf der y-Achse, den Winkel 90 Grad, Cosinus 0. In diesem Fall würden wir sagen, dass diese Dokumente orthogonal zueinander sind.

Hinzufügen von Dimensionen:
Mit diesem intuitiven Gefühl für Ähnlichkeit, ausgedrückt als kleiner Winkel (oder großer Kosinus), können wir uns jetzt Dinge in drei Dimensionen vorstellen, indem wir beispielsweise das Wort "Amsterdam" in die Mischung einbinden und gut visualisieren, wie ein Dokument aussieht mit jeweils zwei Verweisen würde ein Vektor in eine bestimmte Richtung verlaufen, und wir können sehen, wie diese Richtung mit einem Dokument verglichen würde, das jeweils drei Mal Paris und London, aber nicht Amsterdam usw. zitiert. Wie gesagt, wir können versuchen, uns das vorzustellen Dieser schicke Raum für 10 oder 100 Städte. Es ist schwer zu zeichnen, aber einfach zu konzipieren.

Ich fasse zusammen, indem ich ein paar Worte über die Formel selbst ​​sage. Wie ich bereits sagte, bieten andere Referenzen gute Informationen zu den Berechnungen.

Zuerst in zwei Dimensionen. Die Formel für den Kosinus des Winkels zwischen zwei Vektoren ergibt sich aus der trigonometrischen Differenz (zwischen Winkel a und Winkel b):

cos(a - b) = (cos(a) * cos(b)) + (sin (a) * sin(b))

Diese Formel sieht der Formel für das Skalarprodukt sehr ähnlich:

Vect1 . Vect2 =  (x1 * x2) + (y1 * y2)

wobei cos(a) dem x -Wert und sin(a) dem y -Wert für den ersten Vektor usw. entspricht. Das einzige Problem ist, dass x, y usw. sind nicht genau die Werte cos und sin, da diese Werte auf dem Einheitskreis abgelesen werden müssen. Hier setzt der Nenner der Formel an: Durch Division durch das Produkt der Länge dieser Vektoren werden die Koordinaten x und y normalisiert.

112
mjv

Hier ist meine Implementierung in C #.

using System;

namespace CosineSimilarity
{
    class Program
    {
        static void Main()
        {
            int[] vecA = {1, 2, 3, 4, 5};
            int[] vecB = {6, 7, 7, 9, 10};

            var cosSimilarity = CalculateCosineSimilarity(vecA, vecB);

            Console.WriteLine(cosSimilarity);
            Console.Read();
        }

        private static double CalculateCosineSimilarity(int[] vecA, int[] vecB)
        {
            var dotProduct = DotProduct(vecA, vecB);
            var magnitudeOfA = Magnitude(vecA);
            var magnitudeOfB = Magnitude(vecB);

            return dotProduct/(magnitudeOfA*magnitudeOfB);
        }

        private static double DotProduct(int[] vecA, int[] vecB)
        {
            // I'm not validating inputs here for simplicity.            
            double dotProduct = 0;
            for (var i = 0; i < vecA.Length; i++)
            {
                dotProduct += (vecA[i] * vecB[i]);
            }

            return dotProduct;
        }

        // Magnitude of the vector is the square root of the dot product of the vector with itself.
        private static double Magnitude(int[] vector)
        {
            return Math.Sqrt(DotProduct(vector, vector));
        }
    }
}
20
tranmq

Zur Vereinfachung reduziere ich die Vektoren a und b:

Let :
    a : [1, 1, 0]
    b : [1, 0, 1]

Dann Cosinusähnlichkeit (Theta):

 (Theta) = (1*1 + 1*0 + 0*1)/sqrt((1^2 + 1^2))* sqrt((1^2 + 1^2)) = 1/2 = 0.5

dann ist die Inverse von cos 0,5 60 Grad.

17
userPS

Dieser Python-Code ist mein schneller und schmutziger Versuch, den Algorithmus zu implementieren:

import math
from collections import Counter

def build_vector(iterable1, iterable2):
    counter1 = Counter(iterable1)
    counter2 = Counter(iterable2)
    all_items = set(counter1.keys()).union(set(counter2.keys()))
    vector1 = [counter1[k] for k in all_items]
    vector2 = [counter2[k] for k in all_items]
    return vector1, vector2

def cosim(v1, v2):
    dot_product = sum(n1 * n2 for n1, n2 in Zip(v1, v2) )
    magnitude1 = math.sqrt(sum(n ** 2 for n in v1))
    magnitude2 = math.sqrt(sum(n ** 2 for n in v2))
    return dot_product / (magnitude1 * magnitude2)


l1 = "Julie loves me more than Linda loves me".split()
l2 = "Jane likes me more than Julie loves me or".split()


v1, v2 = build_vector(l1, l2)
print(cosim(v1, v2))
13
Victor Yan

Verwenden Sie @Bill Bell, zwei Möglichkeiten, dies in [R] zu tun.

a = c(2,1,0,2,0,1,1,1)

b = c(2,1,1,1,1,0,1,1)

d = (a %*% b) / (sqrt(sum(a^2)) * sqrt(sum(b^2)))

oder die Leistung der crossprod () -Methode nutzen ...

e = crossprod(a, b) / (sqrt(crossprod(a, a)) * sqrt(crossprod(b, b)))
8
Andrew U

Dies ist ein einfacher Python-Code, der eine Cosinusähnlichkeit implementiert.

from scipy import linalg, mat, dot
import numpy as np

In [12]: matrix = mat( [[2, 1, 0, 2, 0, 1, 1, 1],[2, 1, 1, 1, 1, 0, 1, 1]] )

In [13]: matrix
Out[13]: 
matrix([[2, 1, 0, 2, 0, 1, 1, 1],
        [2, 1, 1, 1, 1, 0, 1, 1]])
In [14]: dot(matrix[0],matrix[1].T)/np.linalg.norm(matrix[0])/np.linalg.norm(matrix[1])
Out[14]: matrix([[ 0.82158384]])
4
import Java.util.HashMap;
import Java.util.HashSet;
import Java.util.Map;
import Java.util.Set;

/**
 * 
* @author Xiao Ma
* mail : [email protected]
*
*/
  public class SimilarityUtil {

public static double consineTextSimilarity(String[] left, String[] right) {
    Map<String, Integer> leftWordCountMap = new HashMap<String, Integer>();
    Map<String, Integer> rightWordCountMap = new HashMap<String, Integer>();
    Set<String> uniqueSet = new HashSet<String>();
    Integer temp = null;
    for (String leftWord : left) {
        temp = leftWordCountMap.get(leftWord);
        if (temp == null) {
            leftWordCountMap.put(leftWord, 1);
            uniqueSet.add(leftWord);
        } else {
            leftWordCountMap.put(leftWord, temp + 1);
        }
    }
    for (String rightWord : right) {
        temp = rightWordCountMap.get(rightWord);
        if (temp == null) {
            rightWordCountMap.put(rightWord, 1);
            uniqueSet.add(rightWord);
        } else {
            rightWordCountMap.put(rightWord, temp + 1);
        }
    }
    int[] leftVector = new int[uniqueSet.size()];
    int[] rightVector = new int[uniqueSet.size()];
    int index = 0;
    Integer tempCount = 0;
    for (String uniqueWord : uniqueSet) {
        tempCount = leftWordCountMap.get(uniqueWord);
        leftVector[index] = tempCount == null ? 0 : tempCount;
        tempCount = rightWordCountMap.get(uniqueWord);
        rightVector[index] = tempCount == null ? 0 : tempCount;
        index++;
    }
    return consineVectorSimilarity(leftVector, rightVector);
}

/**
 * The resulting similarity ranges from −1 meaning exactly opposite, to 1
 * meaning exactly the same, with 0 usually indicating independence, and
 * in-between values indicating intermediate similarity or dissimilarity.
 * 
 * For text matching, the attribute vectors A and B are usually the term
 * frequency vectors of the documents. The cosine similarity can be seen as
 * a method of normalizing document length during comparison.
 * 
 * In the case of information retrieval, the cosine similarity of two
 * documents will range from 0 to 1, since the term frequencies (tf-idf
 * weights) cannot be negative. The angle between two term frequency vectors
 * cannot be greater than 90°.
 * 
 * @param leftVector
 * @param rightVector
 * @return
 */
private static double consineVectorSimilarity(int[] leftVector,
        int[] rightVector) {
    if (leftVector.length != rightVector.length)
        return 1;
    double dotProduct = 0;
    double leftNorm = 0;
    double rightNorm = 0;
    for (int i = 0; i < leftVector.length; i++) {
        dotProduct += leftVector[i] * rightVector[i];
        leftNorm += leftVector[i] * leftVector[i];
        rightNorm += rightVector[i] * rightVector[i];
    }

    double result = dotProduct
            / (Math.sqrt(leftNorm) * Math.sqrt(rightNorm));
    return result;
}

public static void main(String[] args) {
    String left[] = { "Julie", "loves", "me", "more", "than", "Linda",
            "loves", "me" };
    String right[] = { "Jane", "likes", "me", "more", "than", "Julie",
            "loves", "me" };
    System.out.println(consineTextSimilarity(left,right));
}
}
3
user1472571

Einfacher Java-Code zur Berechnung der Cosinus-Ähnlichkeit

/**
   * Method to calculate cosine similarity of vectors
   * 1 - exactly similar (angle between them is 0)
   * 0 - orthogonal vectors (angle between them is 90)
   * @param vector1 - vector in the form [a1, a2, a3, ..... an]
   * @param vector2 - vector in the form [b1, b2, b3, ..... bn]
   * @return - the cosine similarity of vectors (ranges from 0 to 1)
   */
  private double cosineSimilarity(List<Double> vector1, List<Double> vector2) {

    double dotProduct = 0.0;
    double normA = 0.0;
    double normB = 0.0;
    for (int i = 0; i < vector1.size(); i++) {
      dotProduct += vector1.get(i) * vector2.get(i);
      normA += Math.pow(vector1.get(i), 2);
      normB += Math.pow(vector2.get(i), 2);
    }
    return dotProduct / (Math.sqrt(normA) * Math.sqrt(normB));
  }
1
nikoo28

Zwei Vektoren A und B existieren in einem 2D-Raum oder 3D-Raum, der Winkel zwischen diesen Vektoren ist cos-Ähnlichkeit. 

Wenn der Winkel größer ist (max. 180 Grad erreichen kann), ist Cos 180 = -1 und der minimale Winkel ist 0 Grad. cos 0 = 1 bedeutet, dass die Vektoren zueinander ausgerichtet sind und daher die Vektoren ähnlich sind. 

cos 90 = 0 (was ausreicht, um zu schließen, dass die Vektoren A und B überhaupt nicht ähnlich sind, und da der Abstand nicht negativ sein kann, liegen die Cosinuswerte zwischen 0 und 1) macht Sinn)

0
Drool