¿Puede alguien dar un ejemplo de similitud de coseno, de una manera muy simple y gráfica?


Coseno Similitud artículo en Wikipedia

Puede mostrar los vectores aquí (en una lista o algo) y luego hacer las matemáticas,y vamos a ver cómo funciona?

Soy un principiante.
Author: slaphappy, 2009-11-17

10 answers

Aquí hay dos textos muy cortos para comparar:

  1. Julie loves me more than Linda loves me

  2. Jane likes me more than Julie loves me

Queremos saber cuán similares son estos textos, puramente en términos de conteo de palabras (e ignorando el orden de las palabras). Comenzamos haciendo una lista de las palabras de ambos textos:

me Julie loves Linda than more likes Jane

Ahora contamos el número de veces que cada una de estas palabras aparece en cada texto:

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

Sin embargo, no estamos interesados en las palabras mismas. Estamos interesados solo en esos dos verticales vectores de conteos. Por ejemplo, hay dos casos de "yo" en cada texto. Vamos a decidir qué tan cerca están estos dos textos de cada uno otros mediante el cálculo de una función de esos dos vectores, a saber, el coseno de el ángulo entre ellos.

Los dos vectores son, de nuevo:

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

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

El coseno del ángulo entre ellos es aproximadamente 0.822.

Estos vectores son de 8 dimensiones. Una virtud de usar similitud de coseno es claramente que convierte una pregunta que está más allá de lo humano capacidad de visualizar a uno eso puede ser. En este caso se puede pensar en esto como el ángulo de aproximadamente 35 grados que es una cierta 'distancia' de cero o acuerdo perfecto.

 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-09 19:45:46

Supongo que está más interesado en obtener una idea de " por qué" funciona la similitud de coseno (por qué proporciona una buena indicación de similitud), en lugar de " cómo" se calcula (las operaciones específicas utilizadas para el cálculo). Si su interés está con este último, vea la referencia indicada por Daniel en este post, así como una pregunta relacionada con SO.

Para explicar tanto el cómo como aún más el por qué, es útil, al principio, simplificar el problema y trabajar solo en dos dimensiones. Una vez que obtienes esto en 2D, es más fácil pensar en ello en 3 dimensiones, y por supuesto más difícil de imaginar en muchas más dimensiones, pero para entonces podemos usar álgebra lineal para hacer los cálculos numéricos y también para ayudarnos a pensar en términos de líneas/vectores / "planos" / "esferas" en n dimensiones a pesar de que no podemos dibujar estos.

So... en dos dimensiones: con respecto a la similitud del texto, esto significa que nos centraríamos en dos términos, decir las palabras "Londres" y "París", y contaríamos cuántas veces cada una de estas palabras se encuentra en cada uno de los dos documentos que queremos comparar. Esto nos da, para cada documento un punto en el plano x-y, por ejemplo, si Doc1 tenía París una vez, y Londres cuatro veces, un punto en (1,4) presentaría este documento (con respecto a esta evaluación diminuta de documentos). O, hablando en términos de vectores, este documento Doc1 sería una flecha que va desde el origen hasta el punto (1,4). Con esto imagen en mente, vamos a pensar en lo que significa ser similar para dos documentos y cómo esto se relaciona con los vectores.

Documentos MUY similares (de nuevo con respecto a este conjunto limitado de dimensiones) tendrían el mismo número de referencias a París, Y el mismo número de referencias a Londres, o tal vez, podrían tener la misma proporción de estas referencias (digamos un Documento Doc2, con 2 referencias a París y 8 Referencias a Londres, también sería muy similar, solo que tal vez un texto más largo o de alguna manera más repetitivo de los nombres de las ciudades, pero en la misma proporción: Tal vez ambos documentos son guías sobre Londres, solo haciendo referencias pasajeras a París (y lo poco cool que es esa ciudad; -) ¡Es broma!!!). Ahora documentos menos similares, también pueden incluir referencias a ambas ciudades, pero en proporciones diferentes, Tal vez Doc2 solo citaría París Una Vez y Londres 7 veces.

De vuelta a nuestro plano x-y, si dibujamos estos documentos hipotéticos, vemos que cuando son MUY similares sus vectores se superponen (aunque algunos vectores pueden ser más largos), y a medida que comienzan a tener menos en común, estos vectores comienzan a divergir, para tener un ángulo más grande entre ellos.

Bam! midiendo el ángulo entre los vectores, podemos tener una buena idea de su similitud , y, para hacer las cosas aún más fáciles, tomando el Coseno de este ángulo, tenemos un buen valor de 0 a 1 (o -1 a 1, dependiendo de qué y cómo representemos) que es indicativo de esta similitud. El más pequeño el ángulo, cuanto más grande (más cerca de 1) el valor del coseno, y también mayor es la similitud.

En el extremo, si el Doc1 solo cita París y el Doc2 solo cita Londres, los documentos no tienen absolutamente nada en común. Doc1 tendría su vector en el eje x, Doc2 en el eje y, el ángulo 90 grados, Coseno 0. (BTW eso es lo que queremos decir cuando decimos que dos cosas son ortogonales entre sí )

Añadiendo dimensiones :
Con esta sensación intuitiva de similitud expresado como un pequeño ángulo (o coseno grande), ahora podemos imaginar las cosas en 3 dimensiones, por ejemplo, trayendo la palabra "Amsterdam" en la mezcla. Y visualizamos, bastante bien, cómo un documento con dos referencias de cada uno tendría un vector que va en una dirección particular y podemos ver cómo esta dirección se compararía con un documento que cita París y Londres 3 veces cada uno, pero no Amsterdam, etc.. Como hemos dicho podemos intentar imaginar este espacio de lujo para 10 o 100 ciudades, difícil de dibujar, pero fácil de conceptualizar.

Terminaré diciendo unas palabras sobre la fórmula misma. Como se ha dicho, otras referencias proporcionan buena información sobre los cálculos.

Nuevamente primero en 2 dimensiones. La fórmula para el Coseno del ángulo entre dos vectores se deriva de la diferencia trigonométrica (entre el ángulo a y el ángulo b)

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

Esta fórmula se ve muy similar a la fórmula del producto escalar:

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

Donde cos (a) coincide con el valor x y sin(a) el y valor, para el primer vector. sucesivamente. El único problema, es que x, y etc. no son exactamente los valores cos y sin, para estos valores deben leerse en el círculo unitario. Ahí es donde el denominador de la fórmula entra en acción: dividiendo por el producto de la longitud de estos vectores, las coordenadas x e y se normalizan.

 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 11:55:09

Aquí está mi implementación 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
Author: tranmq,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-10-06 11:15:13

Para simplificar estoy reduciendo el vector a y b:

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

Luego similitud de coseno (Theta):

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

Entonces la inversa de cos 0.5 es 60 grados.

 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-10-31 04:51:30

Este código Python es mi intento rápido y sucio de implementar el algoritmo:

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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-10-06 10:41:46

Usando @Bill Bell ejemplo, dos maneras de hacer esto 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)))

O aprovechando el rendimiento del método 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-10-06 10:41:30

Este es un código simple Python que implementa la similitud de coseno.

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/ajaxhispano.com/template/agent.layouts/content.php on line 61
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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-10-06 10:42:19

Código JAVA simple para calcular la similitud del coseno

/**
   * 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-10-21 13:12:24

Dos vectores A y B existen en un espacio 2D o 3D, el ángulo entre esos vectores es similitud cos.

Si el ángulo es más (puede alcanzar un máximo de 180 grados) que es Cos 180=-1 y el ángulo mínimo es 0 grados. cos 0 = 1 implica que los vectores están alineados entre sí y por lo tanto los vectores son similares.

Cos 90=0 (que es suficiente para concluir que los vectores A y B no son similares en absoluto y puesto que la distancia no puede ser negativa, los valores del coseno se encuentran de 0 a 1. Por lo tanto, más ángulo implica implica reducir la similitud (visualizar también tiene sentido)

 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-09-22 00:54:25