Pregunta

¿Cómo puedo encontrar la similitud del coseno entre los vectores?

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

Por ejemplo, tengo dos frases como:

sistema para la interfaz de usuario

la interfaz de usuario de la máquina

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

¿Cómo puedo medir la smiliarity entre estos vectores?

¿Fue útil?

Solución

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 coseno similitud que utiliza Jama:. Java Matrix Paquete

Para el código fuente completo Ver IR Math con Java: medidas de similitud , muy buen recurso que cubre unas cuantas mediciones de similitud diferentes.

Otros consejos

Si desea evitar depender de bibliotecas de terceros para una tarea tan sencilla, aquí es una aplicación Java sencilla:

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 comprobar que explicitamente para la seguridad.

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

Si usted tiene 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

Para el código de matriz en Java le recomiendo usar el Colt biblioteca. Si usted tiene esto, el código es el siguiente (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 ser alterado para utilizar uno de los métodos Blas.dnrm2() o Algebra.DEFAULT.norm2() para el cálculo norma. Exactamente el mismo resultado, que es más fácil de leer depende del gusto.

Cuando estaba trabajando con la minería de texto hace algún tiempo, yo estaba usando el SimMetrics biblioteca que ofrece una amplia gama de diferentes métricas en Java. Si sucedió que necesita más, entonces siempre hay R y CRAN a la vista.

Sin embargo, la codificación que de la descripción en la Wikipedia es tarea bastante trivial, y puede ser un buen ejercicio.

Para la representación escasa de vectores usando Map(dimension -> magnitude) He aquí una versión Scala (Usted puede 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))
}
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

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top