Calculer la similarité cosinus à l'aide de 2 chaînes de phrases
à Partir de Python: tf-idf-cosinus: trouver de la ressemblance du document , il est possible de calculer la ressemblance de document à l'aide de tf-idf cosinus. Sans importer de bibliothèques externes, est-ce une façon de calculer la similarité cosinus entre 2 chaînes?
s1 = "This is a foo bar sentence ."
s2 = "This sentence is similar to a foo bar sentence ."
s3 = "What is this string ? Totally not related to the other two lines ."
cosine_sim(s1, s2) # Should give high cosine similarity
cosine_sim(s1, s3) # Shouldn't give high cosine similarity value
cosine_sim(s2, s3) # Shouldn't give high cosine similarity value
4 réponses
une simple implémentation pure-Python serait:
import re, math
from collections import Counter
WORD = re.compile(r'\w+')
def get_cosine(vec1, vec2):
intersection = set(vec1.keys()) & set(vec2.keys())
numerator = sum([vec1[x] * vec2[x] for x in intersection])
sum1 = sum([vec1[x]**2 for x in vec1.keys()])
sum2 = sum([vec2[x]**2 for x in vec2.keys()])
denominator = math.sqrt(sum1) * math.sqrt(sum2)
if not denominator:
return 0.0
else:
return float(numerator) / denominator
def text_to_vector(text):
words = WORD.findall(text)
return Counter(words)
text1 = 'This is a foo bar sentence .'
text2 = 'This sentence is similar to a foo bar sentence .'
vector1 = text_to_vector(text1)
vector2 = text_to_vector(text2)
cosine = get_cosine(vector1, vector2)
print 'Cosine:', cosine
Imprime:
Cosine: 0.861640436855
la formule cosine utilisée ici est décrite ici .
cela ne comprend pas la pondération des mots par TF-idf, mais pour utiliser tf-idf, vous devez avoir un corpus assez grand à partir de laquelle estimer les poids tfidf.
vous pouvez également le développer davantage, en utilisant un plus une façon sophistiquée d'extraire des mots d'un morceau de texte, de le faire glisser ou de le lemmatiser, etc.
La réponse est "non, il n'est pas possible de le faire dans un moyen de principes qui fonctionne même à distance". Il s'agit d'un problème non résolu dans la recherche sur le traitement du langage naturel et qui fait aussi l'objet de mes travaux de doctorat. Je vais très brièvement résumer où nous en sommes et vous montrer quelques publications:
sens des mots
l'hypothèse La plus importante ici est qu'il est possible d'obtenir un vecteur cela représente chaque mot dans la phrase en question. Ce vecteur est généralement choisi pour capturer les contextes, le mot peut apparaître dans de. Par exemple, si nous considérons seulement les trois contextes "manger"," rouge " et "peluche", le mot "chat" pourrait être représenté comme [98, 1, 87], parce que si vous deviez lire un très très long morceau de texte (quelques milliards de mots n'est pas rare dans la norme d'aujourd'hui), le mot "chat" apparaîtrait très souvent dans le contexte de "peluche" et "manger", mais pas que souvent dans le contexte de "rouge". De la même manière, "chien" peut être représenté comme [87,2,34] et "parapluie" peut-être [1,13,0]. En imaginant ces vecteurs comme des points dans L'espace 3D, " cat "est clairement plus proche de" dog "que de" umbrella", donc" cat "signifie aussi quelque chose de plus similaire à" dog "qu'à un"umbrella".
cette ligne de travail a été étudiée depuis le début des années 90 (par exemple ce travail par Greffenstette) et a donné des résultats étonnamment bons résultat. Par exemple, voici quelques entrées aléatoires dans un thésaurus que j'ai construit récemment en ayant mon ordinateur lire wikipedia:
theory -> analysis, concept, approach, idea, method
voice -> vocal, tone, sound, melody, singing
james -> william, john, thomas, robert, george, charles
ces listes de mots similaires ont été obtenues entièrement sans intervention humaine - vous nourrissez du texte et revenez quelques heures plus tard.
le problème avec les phrases
vous pourriez vous demander pourquoi nous ne faisons pas la même chose pour des phrases plus longues, comme " les renards roux aiment fruits." C'est parce que nous n'avons pas assez de texte. Pour que nous puissions de façon fiable établir à quoi ressemble X, nous devons voir de nombreux exemples D'X utilisé dans le contexte. Lorsque X est un seul mot comme "voix", ce n'est pas trop dur. Cependant, à mesure que X s'allonge, les chances de trouver des occurrences naturelles de X sont exponentiellement plus lentes. Pour comparaison, Google a environ 1B pages contenant le mot "renard" et pas une seule page contenant "les renards gingembre fruit de l'amour", malgré le fait que c'est une phrase parfaitement valide en anglais et que nous comprenons tous ce qu'elle signifie.
Composition
pour s'attaquer au problème de la rareté des données, nous voulons effectuer la composition, c'est-à-dire prendre des vecteurs pour les mots, qui sont faciles à obtenir à partir de texte réel, et de mettre ensemble d'une manière qui capture leur sens. La mauvaise nouvelle, c'est que personne n'a été capable de faire ça bien pour l'instant.
Le plus simple et le plus la façon évidente est d'ajouter ou de multiplier les vecteurs de mots individuels ensemble. Cela conduit à des effets secondaires indésirables que "les chats pourchassent les chiens" et "les chiens pourchassent les chats" signifierait la même chose pour votre système. En outre, si vous vous multipliez, vous devez être très prudent ou chaque phrase finira représenté par [0,0,...,0], ce qui est contraire au point.
"pour plus d'information
je ne vais pas discuter des méthodes plus sophistiquées pour la composition qui ont été proposées jusqu'à présent. Je vous suggère de lire Katrin Erk "espace Vectoriel des modèles de la signification du mot et de la phrase signifiant: une enquête" . C'est un très bon haut niveau de l'enquête pour obtenir vous avez commencé. Malheureusement, n'est pas librement disponible sur le site de l'éditeur, courriel à l'auteur directement pour en obtenir une copie. Dans ce document, vous trouverez des références à beaucoup plus de méthodes concrètes. Les plus compréhensibles sont par Mitchel et Lapata (2008) et Baroni et Zamparelli (2010) .
: L'essentiel de cette réponse est de souligner le fait que bien qu'il existe des méthodes naïves (par exemple, addition, multiplication, similarité de surface, etc.), celles-ci sont fondamentalement défectueuses et, en général, on ne devrait pas s'attendre à de grandes performances de leur part.
Merci @vpekar pour votre mise en œuvre. Il a beaucoup aidé. Je viens de découvrir qu'il manque le poids TF-idf tout en calculant la similitude cosinus. Le compteur (mot) retourne un dictionnaire qui a la liste des mots avec leur occurrence.
cos(q, d) = sim(q, d) = (q · d)/(|t||d|) = (somme(qi, di)/(sqrt(sum(qi2)))*(sqrt(sum(vi2))) où i = 1 à v)
- le qi est le tf-idf poids du terme i dans la requête.
- di est le tf-idf
- poids du terme i dans le document. |q| et |d| sont les longueurs de q et D.
- c'est la similitude cosinus de q et D. . . . . . ou, de même, le cosinus de l'angle entre q et D.
s'il vous Plaît n'hésitez pas à consulter mon code ici . Mais d'abord, vous devrez télécharger l'anaconda paquet. Il vous définira automatiquement le chemin python dans Windows. Ajouter cette interprète python dans Eclipse.
si vous connaissez word embeddings comme Glove / Word2Vec / Numberbatch, votre travail est à moitié terminé. Si non laissez-moi vous expliquer comment il est possible d'agir. Convertissez chaque phrase en jetons de mots, et représentez chacun de ces jetons comme des vecteurs de haute dimension (en utilisant le mot pré-formé embeddings, ou vous pourriez train eux vous-même même!). Donc, maintenant vous ne capturez pas leur similarité de surface mais plutôt extraire le sens de chaque mot qui composent la phrase dans son ensemble. Après cela calculez leur similitude cosinus et vous êtes mis.