Domanda

Come faccio a trovare la somiglianza del coseno tra i vettori?

Ho bisogno di trovare la somiglianza di misurare la parentela tra due righe di testo.

Per esempio, ho due frasi come:

  

Sistema per l'interfaccia utente

     

macchina interfaccia utente

... ei loro rispettivi vettori dopo TF-IDF, seguita dalla normalizzazione utilizzando LSI, per esempio [1,0.5] e [0.5,1].

Come faccio a misurare la smiliarity tra questi vettori?

È stato utile?

Soluzione

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

Ho fatto alcune cose TF-IDF recentemente per la mia unità Information Retrieval presso l'Università. Ho usato questo metodo Cosine somiglianza che utilizza Jama:. Java Matrix Pacchetto

Per il codice sorgente completo vedi IR Math con Java: misure di similarità , davvero buona risorsa che copre un buon paio di misure di similarità differenti.

Altri suggerimenti

Se si vuole evitare di fare affidamento su librerie di terze parti per un compito così semplice, ecco un'implementazione Java semplice:

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

Si noti che la funzione presuppone che i due vettori hanno la stessa lunghezza. Si consiglia di verificare esplicitamente per la sicurezza.

Date un'occhiata a: http://en.wikipedia.org/wiki/Cosine_similarity .

Se si dispone di vettori A e B.

La somiglianza è definito come:

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)

Esempio:

A = (1, 0.5), B = (0.5, 1)

cosine(theta) = (0.5 + 0.5) / sqrt(5/4) sqrt(5/4) = 4/5

Per il codice a matrice in Java mi consiglia di utilizzare la Colt biblioteca. Se si dispone di questo, il codice è simile (non testato o addirittura compilato):

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

Il codice sopra potrebbe anche essere modificato per utilizzare uno dei metodi Blas.dnrm2() o Algebra.DEFAULT.norm2() per il calcolo norma. Esattamente lo stesso risultato, che è più leggibile dipende dal gusto.

Quando lavoravo con il text mining qualche tempo fa, stavo usando il SimMetrics biblioteca che fornisce una vasta gamma di diversi parametri in Java. Se è successo che avete bisogno di più, poi c'è sempre R e CRAN da guardare.

Ma codifica dalla descrizione nella Wikipedia è compito piuttosto banale, e può essere un buon esercizio.

Per la rappresentazione sparsa di vettori utilizzando Map(dimension -> magnitude) Ecco una versione Scala (Si può fare cose simili in 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))
}

Versione Scala

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top