web-dev-qa-db-fra.com

Quelqu'un peut-il donner un exemple de similarité de cosinus, de manière très simple et graphique?

Article de similitude Cosine sur Wikipedia

Pouvez-vous montrer les vecteurs ici (dans une liste ou quelque chose) Et ensuite faire le calcul, et laissez-nous voir comment cela fonctionne?

Je suis un débutant.

173
TIMEX

Voici deux textes très courts à comparer:

  1. Julie loves me more than Linda loves me

  2. Jane likes me more than Julie loves me

Nous voulons savoir dans quelle mesure ces textes sont similaires, uniquement en termes de nombre de mots (et en ignorant l'ordre des mots). Nous commençons par dresser une liste des mots des deux textes:

me Julie loves Linda than more likes Jane

Maintenant, nous comptons le nombre de fois où chacun de ces mots apparaît dans chaque texte:

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

Nous ne sommes cependant pas intéressés par les mots eux-mêmes. Nous ne nous intéressons qu’à , Ces deux vecteurs verticaux des comptes. Par exemple, il y a deux instances de «Moi» dans chaque texte. Nous allons déterminer à quel point ces deux textes sont proches l'un de l'autre en calculant une fonction de ces deux vecteurs, à savoir le cosinus de them l'angle entre eux. 

Les deux vecteurs sont, encore une fois:

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

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

Le cosinus de l'angle entre eux est d'environ 0,822.

Ces vecteurs sont en 8 dimensions. L'utilisation de la similarité en cosinus est un avantage, clairement, de convertir une question qui dépasse la capacité de visualisation de l'homme à une question possible. Dans ce cas, vous pouvez considérer cela comme un angle d'environ 35 degrés, ce qui correspond à une "distance" par rapport à zéro ou à un accord parfait.

409
Bill Bell

Je suppose que vous êtes plus intéressé par un aperçu de "pourquoi" la similarité de cosinus fonctionne (pourquoi elle fournit une bonne indication de similitude), plutôt que de "comment", elle est calculée (la opérations utilisées pour le calcul). Si votre intérêt concerne ce dernier point, voir la référence indiquée par Daniel dans ce message, ainsi que une question connexe SO .

Pour expliquer à la fois le comment et plus encore le pourquoi, il est utile, dans un premier temps, de simplifier le problème et de ne travailler que dans deux dimensions. Une fois que vous obtenez ceci en 2D, il est plus facile de le penser en 3 dimensions, et bien sûr plus difficile de l'imaginer dans beaucoup d'autres dimensions, mais nous pouvons alors utiliser l'algèbre linéaire pour faire les calculs numériques et aussi pour nous aider à penser en termes de lignes/vecteurs/"plans"/"sphères" en n dimensions même si nous ne pouvons pas les dessiner.

Donc ... en deux dimensions _: en ce qui concerne la similarité des textes, cela signifie que nous nous concentrerions sur deux termes distincts, prononcer les mots "Londres" et "Paris", et compter le nombre de fois. de ces mots se trouve dans chacun des deux documents que nous souhaitons comparer. Cela nous donne, pour chaque document un point dans le plan xy, par exemple si Doc1 avait une fois Paris et quatre fois Londres, un point en (1,4) présenterait ce document (en ce qui concerne cette évaluation diminutive de documents) . Ou, en termes de vecteurs, ce document Doc1 serait une flèche allant de l’origine au point (1,4). En gardant à l’esprit cette image, réfléchissons à ce que cela signifie d’être similaire pour deux documents et en quoi cela se rapporte aux vecteurs.

Des documents TRES similaires (toujours en ce qui concerne cet ensemble limité de dimensions) porteraient le même nombre de références à Paris, ET le même nombre de références à Londres, ou peut-être pourraient-ils avoir le même rapport de ces références (disons Le document Doc2, avec 2 références à Paris et 8 références à Londres, serait également très similaire, ne serait-ce qu'un texte plus long ou plus répétitif des noms de villes, mais dans la même proportion: Les deux documents sont peut-être des guides sur Londres, ne faisant que en passant des références à Paris (et à quel point cette ville est peu cool ;-) Je plaisante !!!) . Maintenant, des documents moins similaires, peuvent également inclure des références aux deux villes, mais dans des proportions différentes, Doc2 ne citerait peut-être que Paris Once et Londres 7 fois.

Retour à notre plan xy,} si nous dessinons ces documents hypothétiques, nous voyons que lorsqu'ils sont TRES similaires, leurs vecteurs se chevauchent (bien que certains vecteurs puissent être plus longs), et lorsqu'ils commencent à avoir moins en commun, les vecteurs commencent à diverger, à avoir un angle plus grand entre eux.

Bam! en mesurant l'angle entre les vecteurs, nous pouvons avoir une bonne idée de leur similitude}, et, pour rendre les choses encore plus simples, en prenant le Cosinus de cet angle, nous avons un Nice 0 à 1 (ou -1 à 1, en fonction de quoi et comment nous comptabilisons) valeur qui indique cette similarité. Plus l'angle est petit, plus la valeur du cosinus est grande (plus proche de 1), et plus la similarité est grande.

À l'extrême, si Doc1 ne cite que Paris et que Doc2 ne cite que Londres, les documents n'ont absolument rien en commun. Doc1 aurait son vecteur sur l'axe des x, Doc2 sur l'axe des y, l'angle 90 degrés, Cosinus 0. (BTW c'est ce que nous voulons dire quand nous disons que deux choses sont orthogonales)

Ajout de dimensions:
Avec cette sensation intuitive de similitude exprimée sous forme de petit angle (ou grand cosinus), nous pouvons maintenant imaginer des choses en 3 dimensions, par exemple en intégrant le mot "Amsterdam" dans le mélange. Et visualisez, très bien, comment un document avec deux références de chacune aurait un vecteur allant dans une direction particulière et nous pouvons voir comment cette direction se comparerait à un document citant Paris et Londres trois fois, mais pas à Amsterdam, etc. Comme dit nous pouvons essayer et imaginer cet espace de fantaisie pour 10 ou 100 villes, difficile à dessiner, mais facile à conceptualiser.

Je vais terminer en disant simplement quelques mots sur la formule elle-même}. Comme dit d'autres références fournissent de bonnes informations sur les calculs. 

Encore une fois en 2 dimensions. La formule du cosinus de l'angle entre deux vecteurs est déduite de la différence trigonométrique (entre l'angle a et l'angle b) 

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

Cette formule ressemble beaucoup à la formule du produit scalaire:

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

Où cos (a) correspond à la valeur x et sin (a) à la valeur y, pour le premier vecteur. etc. Le seul problème, c'est que x, y, etc. ne sont pas exactement les valeurs cos et sin, car ces valeurs doivent être lues sur le cercle unitaire. C'est là que le dénominateur de la formule entre en jeu: en divisant par le produit de la longueur de ces vecteurs, les coordonnées x et y deviennent normalisées.

107
mjv

Voici mon implémentation en 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

Pour simplifier, je réduis le vecteur a et b:

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

Puis similitude cosinus (Thêta):

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

alors l'inverse de cos 0.5 est 60 degrés.

17
userPS

Ce code Python est ma tentative rapide et sale d’implémenter l’algorithme:

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

À l'aide de l'exemple @Bill Bell, deux façons de procéder en [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)))

ou en tirant parti des performances de la méthode crossprod () ...

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

Il s'agit d'un simple code Python qui implémente la similarité en cosinus.

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

Code Java simple pour calculer la similarité de cosinus

/**
   * 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

Deux vecteurs A et B existent dans un espace 2D ou un espace 3D, l'angle entre ces vecteurs est la même similarité. 

Si l'angle est plus grand (peut atteindre 180 degrés maxi), il s'agit de Cos 180 = -1 et l'angle minimal est de 0 degré. cos 0 = 1 implique que les vecteurs sont alignés les uns sur les autres et que, par conséquent, les vecteurs sont similaires. 

cos 90 = 0 (ce qui suffit à conclure que les vecteurs A et B ne sont pas du tout similaires et que la distance ne peut être négative, les valeurs du cosinus seront comprises entre 0 et 1. Par conséquent, un angle plus important implique de réduire la similarité (le visualiser également). logique)

0
Drool