[PYTHON] Vectoriser les phrases et rechercher des phrases similaires

J'ai recherché des phrases similaires avec Doc2Vec, je vais donc vous présenter l'implémentation.

Qu'est-ce que Doc2Vec?

Pour qu'un ordinateur traite un langage naturel, il doit d'abord avoir une valeur que le langage humain peut gérer. [Word2Vec] existe comme méthode de vectorisation du sens des mots. Pour plus de détails, la destination du lien est très facile à comprendre, mais grosso modo, ce mot est exprimé par une liste de n mots avant et après. En faisant cela, par exemple, «chien» et «chat» sont utilisés dans des contextes similaires et peuvent être considérés comme ayant une «signification» similaire. Doc2Vec est une application de Word2Vec pour vectoriser des phrases.

Exemple d'implémentation

Les deux fonctions suivantes seront réalisées à l'aide de Doc2Vec cette fois.

Comme exemple, j'ai utilisé le texte d'Aozora Bunko. Le code utilisé dans cet article est [Publié sur GitHub] [GitHub]. (Le texte utilisé pour l'apprentissage a également été compressé, mais veuillez noter qu'il est de grande taille)

environnement

Veuillez pouvoir utiliser.

Apprentissage

  1. Obtenez le fichier texte
  2. Récupérer le texte d'un fichier
  3. Supprimez les parties inutiles du texte
  4. Décomposer en mots
  5. Apprenez avec Doc2Vec
  6. Sortie des données de formation

Processus selon le flux de.

1. Obtenez le fichier texte

import os
import sys
import MeCab
import collections
from gensim import models
from gensim.models.doc2vec import LabeledSentence

Tout d'abord, importez les bibliothèques requises.

def get_all_files(directory):
    for root, dirs, files in os.walk(directory):
        for file in files:
            yield os.path.join(root, file)

Obtient tous les fichiers dans le répertoire donné.

2. Récupérer le texte d'un fichier

def read_document(path):
    with open(path, 'r', encoding='sjis', errors='ignore') as f:
        return f.read()

3. Supprimez les parties inutiles du texte

def trim_doc(doc):
    lines = doc.splitlines()
    valid_lines = []
    is_valid = False
    horizontal_rule_cnt = 0
    break_cnt = 0
    for line in lines:
        if horizontal_rule_cnt < 2 and '-----' in line:
            horizontal_rule_cnt += 1
            is_valid = horizontal_rule_cnt == 2
            continue
        if not(is_valid):
            continue
        if line == '':
            break_cnt += 1
            is_valid = break_cnt != 3
            continue
        break_cnt = 0
        valid_lines.append(line)
    return ''.join(valid_lines)

Je pense que le traitement ici changera en fonction de la phrase cible. Cette fois, j'ai ignoré la partie explication du texte avant et après le texte. On ne sait pas dans quelle mesure cela affecte la précision en premier lieu.

4. Décomposer en mots

def split_into_words(doc, name=''):
    mecab = MeCab.Tagger("-Ochasen")
    valid_doc = trim_doc(doc)
    lines = mecab.parse(doc).splitlines()
    words = []
    for line in lines:
        chunks = line.split('\t')
        if len(chunks) > 3 and (chunks[3].startswith('verbe') or chunks[3].startswith('adjectif') or (chunks[3].startswith('nom') and not chunks[3].startswith('nom-nombre'))):
            words.append(chunks[0])
    return LabeledSentence(words=words, tags=[name])

def corpus_to_sentences(corpus):
    docs = [read_document(x) for x in corpus]
    for idx, (doc, name) in enumerate(zip(docs, corpus)):
        sys.stdout.write('\r Prétraitement{} / {}'.format(idx, len(corpus)))
        yield split_into_words(doc, name)

Prend une phrase d'un fichier et la décompose en mots. Afin d'améliorer la précision, il semble que les mots utilisés pour l'apprentissage ne soient parfois que de la nomenclature. Cette fois, j'ai utilisé des verbes, des adjectifs et une nomenclature (autres que des nombres).

5. Apprenez avec Doc2Vec

def train(sentences):
    model = models.Doc2Vec(size=400, alpha=0.0015, sample=1e-4, min_count=1, workers=4)
    model.build_vocab(sentences)
    for x in range(30):
        print(x)
        model.train(sentences)
        ranks = []
        for doc_id in range(100):
            inferred_vector = model.infer_vector(sentences[doc_id].words)
            sims = model.docvecs.most_similar([inferred_vector], topn=len(model.docvecs))
            rank = [docid for docid, sim in sims].index(sentences[doc_id].tags[0])
            ranks.append(rank)
        print(collections.Counter(ranks))
        if collections.Counter(ranks)[0] >= PASSING_PRECISION:
            break
    return model

Les paramètres d'apprentissage sont définis dans la partie models.Doc2Vec.

alpha Plus il est haut, plus il converge vite, mais s'il est trop haut, il diverge. Plus la valeur est basse, plus la précision est élevée, mais plus la convergence est lente.

sample Les mots qui apparaissent trop souvent sont probablement des mots dénués de sens et peuvent être ignorés. Définissez ce seuil.

min_count Contrairement à l'échantillon, les mots trop rares peuvent ne pas être appropriés pour décrire la phrase et peuvent être ignorés. Cependant, cette fois, j'ai ciblé tous les mots.

for x in range(30):
        print(x)
        model.train(sentences)
        ranks = []
        for doc_id in range(100):
            inferred_vector = model.infer_vector(sentences[doc_id].words)
            sims = model.docvecs.most_similar([inferred_vector], topn=len(model.docvecs))
            rank = [docid for docid, sim in sims].index(sentences[doc_id].tags[0])
            ranks.append(rank)
        print(collections.Counter(ranks))
        if collections.Counter(ranks)[0] >= PASSING_PRECISION:
            break
    return model

Nous apprenons et évaluons dans cette partie. L'évaluation est effectuée en recherchant des phrases similaires dans 100 des phrases apprises et en comptant le nombre de fois où la phrase la plus similaire était vous-même. Cette fois, l'apprentissage est terminé lorsque 94 fois ou plus. (Parce que j'ai essayé de le tourner plusieurs fois et que la précision ne s'améliorait plus)

6. Sortie des données de formation

model.save(OUTPUT_MODEL)

OUTPUT_MODEL contient le chemin de sortie.

Rechercher des phrases par mot

model = models.Doc2Vec.load('doc2vec.model')

def search_similar_texts(words):
    x = model.infer_vector(words)
    most_similar_texts = model.docvecs.most_similar([x])
    for similar_text in most_similar_texts:
        print(similar_text[0])

Comme Doc2Vec vectorise également les mots (Word2Vec) en même temps, j'ai essayé de rechercher des mots similaires.

def search_similar_words(words):
    for word in words:
        print()
        print(word + ':')
        for result in model.most_similar(positive=word, topn=10):
            print(result[0])

Exemple de recherche de "chat"

猫.PNG

Exemple de recherche de "neige"

雪.PNG

Rechercher des phrases similaires

model = models.Doc2Vec.load('doc2vec.model')

def search_similar_texts(path):
    most_similar_texts = model.docvecs.most_similar(path)
    for similar_text in most_similar_texts:
        print(similar_text[0])

Un exemple de recherche de "Je suis un chat" par Soseki Natsume

夏目漱石.PNG

Un exemple de recherche de "disqualification humaine" par Osamu Tadashi

太宰治.PNG

Résumé

J'ai essayé de mettre en œuvre une recherche de phrases similaires dans Doc2Vec. J'espère que cela vous aidera.

Si une erreur survient

Seule l'erreur qui s'est produite dans mon environnement, mais je posterai la solution.

référence

[Word2Vec: puissance incroyable du vecteur de mots qui surprend l'inventeur] [Word2Vec] [Document tutoriel de calcul de similarité utilisant le mécanisme Doc2Vec et le gensim] [Tutoriel] [Que se passe-t-il si vous effectuez un apprentissage automatique avec un roman pixiv [les données du modèle entraîné sont distribuées]] [pixiv] [Utilisez TensorFlow pour vérifier la différence de mouvement en fonction du taux d'apprentissage] [Taux d'apprentissage] [models.doc2vec – Deep learning with paragraph2vec][doc2vec]

<! - Lien-> [Word2Vec]:https://deepage.net/bigdata/machine_learning/2016/09/02/word2vec_power_of_word_vector.html [GitHub]:https://github.com/Foo-x/doc2vec-sample [Tutoriel]: https://deepage.net/machine_learning/2017/01/08/doc2vec.html [pixiv]:http://inside.pixiv.net/entry/2016/09/13/161454 [Taux d'apprentissage]: http://qiita.com/isaac-otao/items/6d44fdc0cfc8fed53657 [doc2vec]:https://radimrehurek.com/gensim/models/doc2vec.html

Recommended Posts

Vectoriser les phrases et rechercher des phrases similaires
Raisonnement causal et recherche causale par Python (pour les débutants)
Recherche approximative du voisin le plus proche pour une analyse d'image similaire (pour les débutants) (1)
Recherche récursive de fichiers et de répertoires en Python et sortie
Application console interactive pour la recherche d'adresses et de codes postaux
Essayez une recherche similaire de recherche d'images à l'aide du SDK Python [Recherche]
Recherchez le pandas.DataFrame avec une variable et obtenez la ligne correspondante.
Liste de recherche des éléments en double
Rechercher le nom de la fonction OpenCV
Rechercher des chaînes dans les fichiers
Structure WordNet et recherche de synonymes
Pièges et solutions de contournement pour pandas.DataFrame.to_sql
Rechercher numpy.array pour Vrai consécutif
[Python] Recherche de priorité de profondeur et recherche de priorité de largeur
Rechercher des chaînes de caractères dans les fichiers [Comparaison entre Bash et PowerShell]
Vider, restaurer et rechercher des requêtes d'instances de classe Python à l'aide de mongodb