Similitude entre deux documents textuels

j'envisage de travailler sur un projet NLP, dans n'importe quelle langue (bien que Python sera ma préférence).

je veux écrire un programme qui prendra deux documents et de déterminer comment ils sont similaires.

comme je suis assez nouveau à cela et une recherche rapide de google ne me pointe pas trop. Connaissez-vous des références (sites Web, manuels, articles de journaux) qui couvrent ce sujet et qui pourraient m'aider?

Merci

143
nlp
demandé sur Reily Bourne 2012-01-17 19:51:09

7 réponses

la manière courante de faire ceci est de transformer les documents en vecteurs TF-idf, puis de calculer la similitude cosinus entre eux. Tout manuel sur la recherche d'informations (IR) couvre cette question. Voir les esp. Introduction à la recherche d'Information , qui est gratuit et disponible en ligne.

Tf-idf (et transformations de texte similaires) sont implémentés dans les paquets Python Gensim et scikit-learn . Dans ce dernier cas, le calcul des similitudes cosinus est aussi simple que

from sklearn.feature_extraction.text import TfidfVectorizer

documents = [open(f) for f in text_files]
tfidf = TfidfVectorizer().fit_transform(documents)
# no need to normalize, since Vectorizer will return normalized tf-idf
pairwise_similarity = tfidf * tfidf.T

ou, si les documents sont de simples chaînes de caractères,

>>> vect = TfidfVectorizer(min_df=1)
>>> tfidf = vect.fit_transform(["I'd like an apple",
...                             "An apple a day keeps the doctor away",
...                             "Never compare an apple to an orange",
...                             "I prefer scikit-learn to Orange"])
>>> (tfidf * tfidf.T).A
array([[ 1.        ,  0.25082859,  0.39482963,  0.        ],
       [ 0.25082859,  1.        ,  0.22057609,  0.        ],
       [ 0.39482963,  0.22057609,  1.        ,  0.26264139],
       [ 0.        ,  0.        ,  0.26264139,  1.        ]])

bien que Gensim puisse avoir plus d'options pour ce genre de tâche.

Voir aussi cette question .

[Avertissement: j'ai été impliqué dans la scikit-learn tf-idf de mise en œuvre.]

214
répondu Fred Foo 2017-05-23 12:34:48

identique à @larsman, mais avec quelques prétraitement

import nltk, string
from sklearn.feature_extraction.text import TfidfVectorizer

nltk.download('punkt') # if necessary...


stemmer = nltk.stem.porter.PorterStemmer()
remove_punctuation_map = dict((ord(char), None) for char in string.punctuation)

def stem_tokens(tokens):
    return [stemmer.stem(item) for item in tokens]

'''remove punctuation, lowercase, stem'''
def normalize(text):
    return stem_tokens(nltk.word_tokenize(text.lower().translate(remove_punctuation_map)))

vectorizer = TfidfVectorizer(tokenizer=normalize, stop_words='english')

def cosine_sim(text1, text2):
    tfidf = vectorizer.fit_transform([text1, text2])
    return ((tfidf * tfidf.T).A)[0,1]


print cosine_sim('a little bird', 'a little bird')
print cosine_sim('a little bird', 'a little bird chirps')
print cosine_sim('a little bird', 'a big dog barks')
70
répondu Renaud 2016-10-19 06:48:48

c'est une vieille question, mais j'ai trouvé que cela peut être fait facilement avec Spacy . Une fois que le document est lu, une simple api similarity peut être utilisée pour trouver la similitude cosinus entre les vecteurs du document.

import spacy
nlp = spacy.load('en')
doc1 = nlp(u'Hello hi there!')
doc2 = nlp(u'Hello hi there!')
doc3 = nlp(u'Hey whatsup?')

print doc1.similarity(doc2) # 0.999999954642
print doc2.similarity(doc3) # 0.699032527716
print doc1.similarity(doc3) # 0.699032527716
22
répondu Koustuv Sinha 2017-05-21 22:34:59

en général, une similitude cosinus entre deux documents est utilisée comme mesure de la similitude des documents. En Java, vous pouvez utiliser Lucene (si votre collection est assez grande) ou LingPipe pour ce faire. Le concept de base serait de compter les termes de chaque document et de calculer le produit scalaire de l'expression des vecteurs. Les bibliothèques apportent plusieurs améliorations par rapport à cette approche générale, par exemple en utilisant des fréquences de documents inverses et en calculant tf-idf des vecteurs. Si vous cherchez à faire quelque chose copmlex, LingPipe fournit également des méthodes pour calculer la similarité LSA entre les documents qui donne de meilleurs résultats que la similarité cosinus. Pour Python, vous pouvez utiliser NLTK .

17
répondu Pulkit Goyal 2012-01-17 15:59:17

Voici une petite application pour commencer...

import difflib as dl

a = file('file').read()
b = file('file1').read()

sim = dl.get_close_matches

s = 0
wa = a.split()
wb = b.split()

for i in wa:
    if sim(i, wb):
        s += 1

n = float(s) / float(len(wa))
print '%d%% similarity' % int(n * 100)
3
répondu Dr. KingSchultz 2012-06-30 22:17:49

vous pourriez vouloir essayer ce service en ligne pour cosine document similarité http://www.scurtu.it/documentSimilarity.html

import urllib,urllib2
import json
API_URL="http://www.scurtu.it/apis/documentSimilarity"
inputDict={}
inputDict['doc1']='Document with some text'
inputDict['doc2']='Other document with some text'
params = urllib.urlencode(inputDict)    
f = urllib2.urlopen(API_URL, params)
response= f.read()
responseObject=json.loads(response)  
print responseObject
2
répondu Ekaterina Gorchinsky 2013-02-12 12:03:16

si vous êtes plus intéressé à mesurer la similitude sémantique de deux morceaux de texte, je suggère de jeter un oeil à ce projet gitlab . Vous pouvez l'exécuter comme un serveur, il y a aussi un modèle pré-construit que vous pouvez utiliser facilement pour mesurer la similarité de deux morceaux de texte; bien qu'il soit principalement formé pour mesurer la similarité de deux phrases, vous pouvez encore l'utiliser dans votre cas.Il est écrit en java mais vous pouvez l'exécuter comme un service reposant.

une autre option est aussi Dkpro Similarity qui est une bibliothèque avec divers algorithmes pour mesurer la similitude des textes. Cependant, il est aussi écrit en java.

1
répondu Mohammad-Ali 2018-01-31 23:35:53