web-dev-qa-db-fra.com

Modèle d'espace vectoriel: similarité cosinus vs distance euclidienne

J'ai des corpus de texte classifié. À partir de cela, je crée des vecteurs. Chaque vecteur correspond à un document. Les composants vectoriels sont des pondérations de mots dans ce document calculées en tant que valeurs TFIDF. Ensuite, je construis un modèle dans lequel chaque classe est présentée par un seul vecteur. Le modèle a autant de vecteurs que de classes dans les corpus. La composante d'un vecteur de modèle est calculée en tant que moyenne de toutes les valeurs de composante extraites des vecteurs de cette classe. Pour les vecteurs non classés, je détermine la similarité avec un vecteur modèle en calculant le cosinus entre ces vecteurs.

Des questions: 

1) Puis-je utiliser la distance euclidienne entre non classifié et vecteur de modèle pour calculer leur similarité? 

2) Pourquoi la distance euclidienne ne peut-elle pas être utilisée comme mesure de similarité au lieu de cosinus d'angle entre deux vecteurs et inversement?

Merci!

31
Anton Ashanin

Une façon informelle mais plutôt intuitive d’y réfléchir consiste à considérer les 2 composantes d’un vecteur: direction et magnitude .

Direction est la "préférence"/"style"/"sentiment"/"variable latente" du vecteur, tandis que la magnitude indique sa force dans cette direction.

Lors de la classification des documents, nous souhaitons les classer selon leur sentiment général. Nous utilisons donc la distance angulaire.

La distance euclidienne est susceptible de regrouper les documents en fonction de leur norme L2 (magnitude, dans le cas bidimensionnel) au lieu de leur direction. C'est à dire. les vecteurs ayant des directions très différentes seraient regroupés car leurs distances par rapport à Origin sont similaires.

35
kizzx2

Je répondrai aux questions dans l'ordre inverse. Pour votre deuxième question, la similarité des cosinus et la distance euclidienne sont deux manières différentes de mesurer la similarité des vecteurs. Le premier mesure la similarité des vecteurs par rapport à l'origine, tandis que le second mesure la distance entre des points d'intérêt particuliers le long du vecteur. Vous pouvez les utiliser isolément, les combiner et utiliser les deux, ou rechercher l'une des nombreuses façons de déterminer la similarité. Voir ces diapositives d'une conférence de Michael Collins pour plus d'informations.

Votre première question n’est pas très claire, mais vous devriez pouvoir utiliser l’une ou l’autre des mesures pour trouver une distance entre deux vecteurs, que vous compariez des documents ou vos "modèles" (ce qui serait plus traditionnellement décrit comme des clusters, où les modèle est la somme de tous les groupes). 

22
Tyson

Temps de calcul sage (en python):

import time
import numpy as np

for i in range(10):
    start = time.time() 
    for i in range(10000):
        a, b = np.random.Rand(100), np.random.Rand(100) 
        np.dot(a, b) / ( np.linalg.norm(a) * np.linalg.norm(b))
    print 'Cosine similarity took', time.time() - start

    start = time.time() 
    for i in range(10000):
        a, b = np.random.Rand(100), np.random.Rand(100) 
        2 * (1 - np.dot(a, b) / ( np.linalg.norm(a) * np.linalg.norm(b)))
    print 'Euclidean from 2*(1 - cosine_similarity) took', time.time() - start


    start = time.time() 
    for i in range(10000):
        a, b = np.random.Rand(100), np.random.Rand(100) 
        np.linalg.norm(a-b)
    print 'Euclidean Distance using np.linalg.norm() took', time.time() - start


    start = time.time() 
    for i in range(10000):
        a, b = np.random.Rand(100), np.random.Rand(100) 
        np.sqrt(np.sum((a-b)**2))
    print 'Euclidean Distance using np.sqrt(np.sum((a-b)**2)) took', time.time() - start
    print '--------------------------------------------------------'

[en dehors]:

Cosine similarity took 0.15826010704
Euclidean from 2*(1 - cosine_similarity) took 0.179041862488
Euclidean Distance using np.linalg.norm() took 0.10684299469
Euclidean Distance using np.sqrt(np.sum((a-b)**2)) took 0.113723039627
--------------------------------------------------------
Cosine similarity took 0.161732912064
Euclidean from 2*(1 - cosine_similarity) took 0.178358793259
Euclidean Distance using np.linalg.norm() took 0.107393980026
Euclidean Distance using np.sqrt(np.sum((a-b)**2)) took 0.111194849014
--------------------------------------------------------
Cosine similarity took 0.16274189949
Euclidean from 2*(1 - cosine_similarity) took 0.178978919983
Euclidean Distance using np.linalg.norm() took 0.106336116791
Euclidean Distance using np.sqrt(np.sum((a-b)**2)) took 0.111373186111
--------------------------------------------------------
Cosine similarity took 0.161939144135
Euclidean from 2*(1 - cosine_similarity) took 0.177414178848
Euclidean Distance using np.linalg.norm() took 0.106301784515
Euclidean Distance using np.sqrt(np.sum((a-b)**2)) took 0.11181807518
--------------------------------------------------------
Cosine similarity took 0.162333965302
Euclidean from 2*(1 - cosine_similarity) took 0.177582979202
Euclidean Distance using np.linalg.norm() took 0.105742931366
Euclidean Distance using np.sqrt(np.sum((a-b)**2)) took 0.111120939255
--------------------------------------------------------
Cosine similarity took 0.16153883934
Euclidean from 2*(1 - cosine_similarity) took 0.176836967468
Euclidean Distance using np.linalg.norm() took 0.106392860413
Euclidean Distance using np.sqrt(np.sum((a-b)**2)) took 0.110891103745
--------------------------------------------------------
Cosine similarity took 0.16018986702
Euclidean from 2*(1 - cosine_similarity) took 0.177738189697
Euclidean Distance using np.linalg.norm() took 0.105060100555
Euclidean Distance using np.sqrt(np.sum((a-b)**2)) took 0.110497951508
--------------------------------------------------------
Cosine similarity took 0.159607887268
Euclidean from 2*(1 - cosine_similarity) took 0.178565979004
Euclidean Distance using np.linalg.norm() took 0.106383085251
Euclidean Distance using np.sqrt(np.sum((a-b)**2)) took 0.11084485054
--------------------------------------------------------
Cosine similarity took 0.161075115204
Euclidean from 2*(1 - cosine_similarity) took 0.177822828293
Euclidean Distance using np.linalg.norm() took 0.106630086899
Euclidean Distance using np.sqrt(np.sum((a-b)**2)) took 0.110257148743
--------------------------------------------------------
Cosine similarity took 0.161051988602
Euclidean from 2*(1 - cosine_similarity) took 0.181928873062
Euclidean Distance using np.linalg.norm() took 0.106360197067
Euclidean Distance using np.sqrt(np.sum((a-b)**2)) took 0.111301898956
--------------------------------------------------------
5
alvas

Je suggère que le seul moyen sûr de déterminer quelle mesure de distance est la meilleure dans une application donnée est d'essayer les deux et de voir laquelle vous donne les résultats les plus satisfaisants. J'imagine que dans la plupart des cas, la différence d'efficacité ne serait pas grande, mais cela pourrait ne pas être vrai dans votre application particulière.

0
Ralph Dratman