J'ai téléchargé en_core_web_lg
modèle et essayant de trouver la similitude entre deux phrases:
nlp = spacy.load('en_core_web_lg')
search_doc = nlp("This was very strange argument between american and british person")
main_doc = nlp("He was from Japan, but a true English gentleman in my eyes, and another one of the reasons as to why I liked going to school.")
print(main_doc.similarity(search_doc))
Ce qui renvoie une valeur très étrange:
0.9066019751888448
Ces deux phrases ne doivent pas être 90% similaires elles ont des significations très différentes.
Pourquoi cela se produit-il? Dois-je ajouter une sorte de vocabulaire supplémentaire afin de rendre le résultat de similarité plus raisonnable?
La documentation Spacy pour la similitude des vecteurs en explique l'idée de base:
Chaque mot a une représentation vectorielle, apprise par des intégrations contextuelles ( Word2Vec ), qui sont formées sur les corpus, comme expliqué dans la documentation.
Maintenant, l'incorporation de Word d'une phrase complète est simplement la moyenne de tous les mots différents. Si vous avez maintenant beaucoup de mots qui se trouvent sémantiquement dans la même région (comme par exemple des mots de remplissage comme "il", "était", "ceci", ...), et le vocabulaire supplémentaire "annule", alors vous pourrait se retrouver avec une similitude comme on le voit dans votre cas.
La question est à juste titre ce que vous pouvez faire à ce sujet: De mon point de vue, vous pourriez proposer une mesure de similitude plus complexe. Comme le search_doc
et main_doc
avoir des informations supplémentaires, comme la phrase d'origine, vous pouvez modifier les vecteurs par une pénalité de différence de longueur, ou bien essayer de comparer des morceaux plus courts de la phrase, et calculer des similitudes par paires (là encore, la question serait de savoir quelles parties comparer) .
Pour l'instant, il n'y a malheureusement pas de moyen propre de résoudre ce problème.
Spacy construit l'incorporation de phrases en faisant la moyenne des incorporations de Word. Puisque, dans une phrase ordinaire, il y a beaucoup de mots sans signification (appelés mots vides ), vous obtenez de mauvais résultats. Vous pouvez les supprimer comme ceci:
search_doc = nlp("This was very strange argument between american and british person")
main_doc = nlp("He was from Japan, but a true English gentleman in my eyes, and another one of the reasons as to why I liked going to school.")
search_doc_no_stop_words = nlp(' '.join([str(t) for t in search_doc if not t.is_stop]))
main_doc_no_stop_words = nlp(' '.join([str(t) for t in main_doc if not t.is_stop]))
print(search_doc_no_stop_words.similarity(main_doc_no_stop_words))
ou ne gardez que des noms, car ils ont le plus d'informations:
doc_nouns = nlp(' '.join([str(t) for t in doc if t.pos_ in ['NOUN', 'PROPN']))
Comme l'a souligné @dennlinger, les intégrations de phrases de Spacy ne sont que la moyenne de toutes les intégrations de vecteurs Word prises individuellement. Donc, si vous avez une phrase avec des mots négatifs comme "bon" et "mauvais", leurs vecteurs peuvent s'annuler mutuellement, ce qui entraîne des incorporations contextuelles moins bonnes. Si votre cas d'utilisation est spécifique pour obtenir des incorporations de phrases, vous devriez essayer les approches SOTA ci-dessous.
Encodeur universel de phrases de Google: https://tfhub.dev/google/universal-sentence-encoder/2
Encodeur infersent de Facebook: https://github.com/facebookresearch/InferSent
J'ai essayé ces deux intégrations et vous donne de bons résultats pour commencer la plupart du temps et utiliser des intégrations Word comme base pour construire des intégrations de phrases.
À votre santé!