¿Cómo puedo calcular la similitud del coseno de dos vectores?


¿Cómo encuentro la similitud del coseno entre vectores?

Necesito encontrar la similitud para medir la relación entre dos líneas de texto.

Por ejemplo, tengo dos oraciones como:

Sistema para interfaz de usuario

Máquina de interfaz de usuario

} y sus respectivos vectores después de tF-idf, seguido de la normalización utilizando LSI, por ejemplo [1,0.5] y [0.5,1].

¿Cómo mido la smiliaridad entre estos vectores?

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

Hice algunas cosas tf-idf recientemente para mi unidad de Recuperación de Información en la Universidad. He utilizado este método de Similitud Coseno que utiliza Jama: Java Matrix Package.

Para el código fuente completo ver IR Math with Java : Similarity Measures, un recurso realmente bueno que cubre unas cuantas mediciones de similitud diferentes.

 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-02-06 13:42:24

Si desea evitar depender de bibliotecas de terceros para una tarea tan simple, aquí hay una implementación de Java simple:

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

Tenga en cuenta que la función asume que los dos vectores tienen la misma longitud. Es posible que desee verificar explícitamente su seguridad.

 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-04-07 13:13:28

Echa un vistazo a: http://en.wikipedia.org/wiki/Cosine_similarity .

Si tienes vectores A y B.

La similitud se define como:

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)

Ejemplo:

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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-02-28 15:42:01

Para el código de matriz en Java recomendaría usar la biblioteca Colt. Si usted tiene esto, el código se ve como (no probado o incluso compilado):

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

El código anterior también podría modificarse para usar uno de los métodos Blas.dnrm2() o Algebra.DEFAULT.norm2() para el cálculo de la norma. Exactamente el mismo resultado, que es más legible depende del gusto.

 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-05-27 02:48:39

Cuando estaba trabajando con la minería de texto hace algún tiempo, estaba utilizando la biblioteca SimMetrics que proporciona una amplia gama de diferentes métricas en Java. Si sucede que necesita más, entonces siempre hay R y CRAN para mirar.

Pero codificarlo a partir de la descripción en Wikipedia es una tarea bastante trivial, y puede ser un buen ejercicio.

 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-11-12 09:35:24

Para la representación dispersa de vectores usando Map(dimension -> magnitude) Aquí hay una versión de scala (Puedes hacer cosas similares en Java 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
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))
}

Versión 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-09-30 15:31:46