Czy ktoś może podać przykład cosinusowego podobieństwa, w bardzo prosty, graficzny sposób?

Cosinus podobieństwa artykuł na Wikipedii

Możesz tu pokazać wektory (na liście czy coś) a potem policz i zobaczmy, jak to działa?

Jestem początkujący.

Author: slaphappy, 2009-11-17

10 answers

Oto dwa bardzo krótkie teksty do porównania:

  1. Julie loves me more than Linda loves me

  2. Jane likes me more than Julie loves me

Chcemy wiedzieć, jak podobne są te teksty, wyłącznie pod względem liczby słów (i ignorowania kolejności słów). Zaczynamy od sporządzenia listy słów z obu tekstów:

me Julie loves Linda than more likes Jane

Teraz policzymy, ile razy każde z tych słów pojawia się w każdym tekście:

   me   2   2
 Jane   0   1
Julie   1   1
Linda   1   0
likes   0   1
loves   2   1
 more   1   1
 than   1   1
Nie interesują nas jednak same słowa. Jesteśmy zainteresowani tylko te dwa pionowe wektory liczeń. Na przykład, istnieją dwa przypadki "ja" w każdym tekście. Zdecydujemy, jak blisko są te dwa teksty do każdego innych przez obliczenie jednej funkcji tych dwóch wektorów, a mianowicie cosinusa kąt między nimi.

Dwa wektory to:

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

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

Cosinus kąta między nimi wynosi około 0,822.

Te wektory są 8-wymiarowe. Zaletą stosowania podobieństwa cosinusowego jest wyraźnie że zamienia pytanie, które jest poza ludzkim możliwość wizualizacji do jednego możliwe. W tym przypadku można myśleć o tym jako o kącie około 35 stopni, co jest pewną "odległością" od zera lub idealnego porozumienia.

 382
Author: Bill Bell,
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-02-09 19:45:46

Zgaduję, że jesteś bardziej zainteresowany uzyskaniem wglądu w " Dlaczego " podobieństwo cosinusów działa (dlaczego zapewnia dobre wskazanie podobieństwa), a nie "Jak" jest obliczane (konkretne operacje używane do obliczania). Jeśli interesuje cię ten ostatni, zobacz odniesienie wskazane przez Daniela w tym poście, a także powiązane pytanie so.

Aby wyjaśnić zarówno jak i jeszcze bardziej dlaczego, warto najpierw uprościć problem i działać tylko w dwóch wymiarach. Po uzyskaniu tego w 2D, łatwiej jest myśleć o tym w 3 wymiarach, i oczywiście trudniej wyobrazić sobie w wielu innych wymiarach, ale wtedy możemy użyć algebry liniowej do obliczeń numerycznych, a także pomóc nam myśleć w kategoriach linii/wektorów / "płaszczyzn" / "sfer" w n wymiarach, mimo że nie możemy ich narysować.

Więc... w dwóch wymiarach : w odniesieniu do podobieństwa tekstu oznacza to, że skupimy się na dwóch różnych terminy, powiedzmy słowa "Londyn" i "Paryż", a policzymy, ile razy każde z tych słów znajduje się w każdym z dwóch dokumentów, które chcemy porównać. To daje nam, dla każdego dokumentu punkt w płaszczyźnie x-y, na przykład gdyby Doc1 miał Paryż raz, a Londyn cztery razy, punkt w (1,4) przedstawiłby ten dokument (w odniesieniu do tej drobnej oceny dokumentów). Mówiąc o wektorach, dokument Doc1 byłby strzałką przechodzącą od punktu początkowego do punktu (1,4). Z tym wyobraźmy sobie, co to znaczy być podobnym dla dwóch dokumentów i jak to się odnosi do wektorów.

Bardzo podobne dokumenty (znowu w odniesieniu do tego ograniczonego zestawu wymiarów) miałyby taką samą liczbę odniesień do Paryża i taką samą liczbę odniesień do Londynu, a może mogłyby mieć taki sam stosunek tych odniesień (powiedzmy dokument Doc2, z 2 refami do Paryża i 8 Refami do Londynu, również byłby bardzo podobny, tylko może dłuższy tekst lub więcej). jakoś bardziej powtarzalne nazwy miast, ale w tej samej proporcji: może oba dokumenty to przewodniki po Londynie, tylko nawiązujące do Paryża (a jakie to niefajne Miasto; -) tylko żartowałem!!!). Obecnie mniej podobnych dokumentów może zawierać odniesienia do obu miast, ale w różnych proporcjach może Doc2 cytuje Paryż tylko raz, a Londyn 7 razy.

Wracając do naszej płaszczyzny x - y, Jeśli narysujemy te hipotetyczne dokumenty, widzimy, że gdy są bardzo podobne ich wektory nakładają się na siebie (choć niektóre wektory mogą być dłuższe), a gdy zaczynają mieć mniej wspólnego, wektory te zaczynają się różnić, aby mieć większy kąt między nimi.

Bam! mierząc kąt między wektorami, możemy uzyskać dobre wyobrażenie o ich podobieństwie , a dla ułatwienia, Biorąc Cosinus tego kąta, mamy ładne 0 do 1 (lub -1 do 1, w zależności od tego, co i jak rozliczamy) wartość, która wskazuje na to podobieństwo. Mniejsze kąt, im większa (bliżej 1) wartość cosinusa, a także większe podobieństwo. Jeśli Doc1 cytuje tylko Paryż, a Doc2 tylko Londyn, dokumenty nie mają ze sobą absolutnie nic wspólnego. Doc1 miałby swój wektor na osi x, Doc2 na osi y, kąt 90 stopni, Cosinus 0. (BTW to mamy na myśli, gdy mówimy, że dwie rzeczy są ortogonalne względem siebie)

Dodawanie wymiarów :
Z tym intuicyjnym wyczuciem podobieństwa wyrażony jako mały kąt (lub duży cosinus), możemy teraz wyobrazić sobie rzeczy w 3 wymiarach, powiedzmy wprowadzając słowo "Amsterdam" w miksie. I wyobraź sobie, całkiem dobrze, jak dokument z dwoma odniesieniami do każdego miałby wektor idący w określonym kierunku i możemy zobaczyć, jak ten kierunek byłby porównywany do dokumentu cytującego Paryż i Londyn 3 razy każdy, ale nie Amsterdam itp.. Jak już wspomniano, możemy spróbować wyobrazić sobie tę fantazyjną przestrzeń dla 10 lub 100 miast, trudną do narysowania, ale łatwą do konceptualizuj.

Zakończę mówiąc kilka słów o samej formule . Jak wspomniano, inne odniesienia dostarczają dobrych informacji na temat obliczeń.

Ponownie pierwszy w 2 wymiarach. Wzór na cosinus kąta między dwoma wektorami pochodzi z różnicy trygonometrycznej (między kątem a i kątem b)

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

Wzór ten wygląda bardzo podobnie do wzoru produktu kropkowego:

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

Gdzie cos(a) odpowiada wartości x i sin (a) wartość y dla pierwszego wektora. itd. Jedynym problemem jest to, że x, y itp. nie są dokładnie wartości cos i sin, dla tych wartości muszą być odczytywane na okręgu jednostkowym. Tam zaczyna się mianownik wzoru: dzieląc przez iloczyn długości tych wektorów, współrzędne x i y stają się znormalizowane.

 103
Author: mjv,
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
2017-05-23 11:55:09

Oto moja implementacja w 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
Author: tranmq,
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-10-06 11:15:13

Dla uproszczenia redukuję wektor a i b:

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

Wtedy cosinus podobieństwa (Theta):

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

Wtedy odwrotność cos 0,5 wynosi 60 stopni.

 15
Author: userPS,
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-10-31 04:51:30

Ten kod Pythona jest moją szybką i brudną próbą implementacji algorytmu:

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))
 11
Author: Victor Yan,
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-10-06 10:41:46

Używając przykładu @ Bill Bell, dwa sposoby, aby to zrobić w [R]

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

Lub wykorzystując wydajność metody crossprod ()...

e = crossprod(a, b) / (sqrt(crossprod(a, a)) * sqrt(crossprod(b, b)))
 8
Author: Andrew U,
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-10-06 10:41:30

Jest to prosty Python kod implementujący podobieństwo cosinusów.

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
Author: Nilani Algiriyage,
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-10-06 10:42:50
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
Author: user1472571,
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-10-06 10:42:19

Prosty kod Javy do obliczania podobieństwa cosinusów

/**
   * 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));
  }
 0
Author: nikoo28,
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-10-21 13:12:24

Dwa wektory A i B istnieją w przestrzeni 2D lub 3D, kąt między tymi wektorami jest cos.

Jeśli kąt jest większy (może osiągnąć max 180 stopni), co jest Cos 180=-1, a minimalny kąt wynosi 0 stopni. cos 0 = 1 oznacza, że wektory są wyrównane do siebie, a zatem wektory są podobne.

Cos 90=0 (co wystarczy, aby stwierdzić, że wektory A i B nie są do siebie podobne, a ponieważ odległość nie może być ujemna, wartości cosinusa będą wynosić od 0 do 1. Stąd większy kąt implikuje redukcję podobieństwa (wizualizacja również ma sens)

 0
Author: Anik,
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-22 00:54:25