[PYTHON] Introduction à Word2Vec que même les chats peuvent comprendre

motivation

Ravi de vous rencontrer, je m'appelle pyaNotty. Ceci est le premier message. Récemment, j'ai eu l'occasion d'entrer en contact avec MeCab et keras, alors j'ai voulu essayer quelque chose de traitement du langage naturel. J'ai entendu dire que les expressions distribuées utilisant Word2Vec sont souvent utilisées pour le traitement du langage naturel, en particulier pour la génération de phrases à l'aide de LSTM. Cette fois, je vais essayer de faire une expression distribuée de mots qui peut être alimentée au modèle LSTM avec Word2Vec.

Même l'auteur, qui n'a que l'intelligence d'un chat, est assez facile à gérer.

Qu'est-ce que Word2Vec

Un modèle pour convertir des mots en vecteurs.

Lorsque vous entraînez un modèle LSTM ou quelque chose avec du texte, vous ne pouvez pas alimenter le modèle avec des chaînes brutes. Par conséquent, il est nécessaire de convertir la phrase en une expression numérique. Par exemple, dans le cas de la phrase "Ceci est un stylo", après avoir décomposé les parties en parties telles que ["Ceci est", "Pen", "est"], chaque mot est converti en une expression numérique.

Le moyen le plus simple est de donner à chaque mot un identifiant unique. Si vous convertissez ['ceci est', 'stylo', 'est'] → [1, 2, 3] etc., vous pouvez entrer dans le modèle Ichiou. Cependant, dans cet état, l'apprentissage du modèle ne fonctionnera pas car les relations entre les mots ne peuvent pas être exprimées.

Par conséquent, Word2Vec est une méthode pour acquérir une expression numérique qui incorpore les relations entre les mots. Vous pouvez l'utiliser pour trouver la distance entre "poire" et "pomme", ou pour calculer "poire" + "pomme" = "ananas". L'auteur est confus, et quand je commencerai à écrire une histoire ici, l'article sera rempli par lui-même, donc pour plus de détails, voir Ce livre % 83% AD% E3% 81% 8B% E3% 82% 89% E4% BD% 9C% E3% 82% 8B Apprentissage en profondeur-% E2% 80% 95% E8% 87% AA% E7% 84% B6% E8% A8% 80% E8% AA% 9E% E5% 87% A6% E7% 90% 86% E7% B7% A8-% E6% 96% 8E% E8% 97% A4-% E5% BA% B7% Veuillez vous référer à E6% AF% 85 / dp / 4873118360).

Création de corpus

Pour créer un modèle Word2Vec, vous devez créer un corpus (en gros, une liste de mots). Une méthode courante consiste à créer un corpus à partir d'une grande quantité de texte collecté sur Wikipédia. En tant que modèle créé à partir du corpus Wikipedia, par exemple, Japanese entity vector est publié sur le Web. Je suis.

Cette fois, je veux être romancier, alors je voudrais gratter le texte et créer un corpus. Puisque l 'API dédiée est ouverte au public, il est facile de collecter des phrases. Implémentons-le tout de suite. Implémenté en python3.7.

import requests
import gzip
import pandas as pd
import datetime
import time

api_url="https://api.syosetu.com/novelapi/api/" 
df = pd.DataFrame()
endtime = int(datetime.datetime.now().timestamp())

interval = 3600*24
cnt = len(df)
while cnt < 100000:
  #Obtenez le titre et le synopsis du roman publiés dans la plage horaire
  time_range = str(endtime - interval) + '-' + str(endtime)
  payload = {'out': 'json','gzip': 5,'order': 'new','lim': 500,
             'lastup': time_range,
             'of': 't-ua-s'}
  res = requests.get(api_url, params=payload).content
  r =  gzip.decompress(res).decode("utf-8") 

  df_temp = pd.read_json(r).drop(0)
  df = pd.concat([df, df_temp])

  #time_Plage de décalage par intervalle
  endtime -= interval
  cnt = len(df['title'].unique())
  time.sleep(2)

En remontant à l'époque actuelle, j'ai obtenu le titre et le synopsis des 100 000 derniers romans. Parmi les données collectées, nous créerons un corpus à partir du synopsis. Tout d'abord, enregistrez le fichier txt.

import pandas as pd

df = pd.read_csv('./data/titles.csv')
txt = ''

#Connectez à peu près tous les synopsis
for i in range(len(df)):
    txt += df['story'][i]

with open('./data/story.txt', mode='w', encoding='utf-8') as f:
    f.write(txt)

Créez un corpus à partir du fichier txt enregistré. Après la division à l'aide de MeCab, supprimez les symboles inutiles et écrivez dans un fichier txt. Le code est basé sur cet article.

import MeCab
import re
import os
import sys

mecab = MeCab.Tagger('-Ochasen -d C:\mecab-ipadic-neologd')

class Corpus:
    def __init__(self, text):
        self.text = text
        self.formated = ""
        self.corpus = []

        self.format()
        self.split()

        
    def split(self):
        node = mecab.parseToNode(str(self.formated))
        while node:
            PoS = node.feature.split(",")[0]

            if PoS not in "BOS/EOS":#Celui qui sort avec les spécifications de mecab, dérangeant
                self.corpus.append(node.surface)

            node = node.next

    def format(self):
        ret= re.sub(r'https?://[\w/:%#\$&\?\(\)~\.=\+\-…]+', "", self.text)#URL
        ret = re.sub(r"[0-9]+", "0", ret)#Nombre à 0
        ret = re.sub(r"[!-/]", "", ret)#Symbole demi-largeur
        ret = re.sub(r"[:-@]", "", ret)#Symbole demi-largeur
        ret = re.sub(r"[[-`]", "", ret)#Symbole demi-largeur
        ret = re.sub(r"[{|}-]", "", ret)#Symbole demi-largeur
        ret = re.sub(r"["'() * [] ... [] << >> = ~" "" "+ *,. ・ _? !! / ◀ ▲:]", "", ret)#Symbole pleine largeur
        ret = re.sub("[\n]", "", ret)#Sauts de ligne, espaces
        ret = re.sub("[\u3000]", "", ret)

        self.formated = ret

    def rtn_corpus(self):
        ret = " ".join(self.corpus)
        return ret


input_file = "./data/story.txt"
output_file = "./data/corpus.txt"

with open(input_file, encoding='utf-8') as in_f:
    lines = in_f.readlines()
    with open(output_file, mode='w', encoding='utf-8') as out_f:
        for l in lines:
            text = Corpus(l).rtn_corpus()
            out_f.write(text + '')

Vous avez créé avec succès un corpus.

corpus.txt


La fiancée du prince, Dalia, a désespérément besoin d'entendre que le prince est en bons termes avec les gens du commun, car son père, qui envisage de diriger le pouvoir royal, lui dit que vous serez certainement une reine, mais Dalia se rend compte soudainement qu'il a grandi. Je me demande si c'est correct de se fiancer. Si nous n'étions pas là, ce pays serait plus heureux, et si ce n'était pas pour nous, il serait brillamment dispersé comme la fille méchante dégoûtante du roman. Veuillez noter qu'il y a des erreurs typographiques et des phrases peu claires qui ont été retravaillées et changées fréquemment. Bien que le titre soit Reverse Harlem, l'héroïne n'utilise pas Reverse Harlem, mais la fille méchante le comprend mal comme Reverse Harlem. De plus, j'ai écrit que non seulement la fille méchante, mais aussi les autres personnages se sont réincarnés dans un autre monde, mais j'ai changé le programme et la fille méchante a changé le décor de la personne réincarnée. Je suis désolé pour les changements fréquents.\Chinatsu, qui a été relégué d'une grande société immobilière pour travailler pour une société de gestion immobilière d'une filiale, a été déprimé et s'est mis au travail. C'était l'esprit flottant d'un ancien banquier Takamura Genki qui était assis à côté de moi. Chinatsu, qui était connue pour avoir une constitution dans laquelle les fantômes peuvent être vus en lui parlant, est malheureusement choisie comme responsable de la propriété fantôme.\Et le fantôme d'un ancien banquier qui était possédé comme un esprit flottant dans le bureau Genki et le beau patron cool Harutaka seront en charge de la propriété fantôme Chinatsu Et quand vous toucherez l'esprit avec esprit, le passé de l'esprit sera Peeping Special Ability Activated Utilisant ce pouvoir pour résoudre les regrets des fantômes, ils réalisent la véritable cause de leur mort. Un tel mystère d'amour occulte Lloyd, qui était un chevalier d'un pays, est le garde d'une princesse Un jour, ils sont montés tous les deux dans une calèche pour assister à une danse dans un pays voisin, mais le chevalier qui a fait tomber la calèche d'une falaise par les mains d'un pays ennemi a dit que Kaburagi Shigure se réveillerait ensuite. Shigure Kaburagi, qui est devenue une lycéenne qui s'était réincarnée en femme, a rencontré Rin Kiriyama, qui était un cran plus haut à Bunbu et à Rin, et le sort des deux a commencé à bouger. Dans le jardin, je passe la majeure partie de ma vie seule, mais j'ai perdu le sens de la vie. Un jour, j'ai rencontré une fille nommée Amatsuka Nagisa. J'étais attirée par la beauté et la gentillesse de Nagisa. J'ai été amoureux pour la première fois de Nagisa, et j'ai sollicité mes pensées Lotus a retrouvé le sens de la vie, mais Nagisa a avoué que je vais bientôt mourir, je suis désespérée. Un rayon de lumière qui brille dans le soleil, une lumière qui ressemble au soleil, c'était le soleil, Mahal-neechan, je veux être ta princesse, je suis l'aîné Maiharu et le plus jeune cousin, l'amour du soleil, et en attendant. Une histoire d'amour triste Une histoire d'une fille avec un pouvoir particulier que j'évacuerai car ma sécurité s'est détériorée.J'acquérirai des compétences dans un autre monde avec des pièces mystérieuses et ce sera calme. Shiro Sakamoto, un détective de la police de la préfecture d'Osaka, est condamné à une semaine de prison à vie par un médecin atteint d'un cancer, alors qu'il veut vivre au Japon.

Ainsi, l'énumération des mots divisés est enregistrée dans le fichier txt.

Formation sur le modèle Word2Vec

Enfin, nous créerons un modèle Word2Vec. La méthode utilisant word2vec de gensim est pratique et bonne. Cela se termine vraiment en un instant.

from gensim.models import word2vec

#Chargez le corpus que vous venez de créer
corpus = './data/corpus.txt'
sentences = word2vec.Text8Corpus(corpus)

#Former le modèle
model = word2vec.Word2Vec(sentences,#Corpus à utiliser
                          size=200,#Nombre de dimensions du vecteur à créer
                          sg=0#skip-Utiliser ou non gramme,Cette fois, allez avec cbow
                          )

#Enregistrer le modèle
model.wv.save('./narou.model')

Je n'expliquerai brièvement que les paramètres de création du modèle. Le paramètre sg spécifie la méthode à utiliser lors de la création du modèle. Créez un modèle en utilisant CBOW avec sg = 0 et skip-gramme avec sg = 1. CBOW est une méthode pour déduire des mots entre les mots environnants. S'il y a une phrase "Ceci est un stylo", c'est une image de saisie "ceci est" et "est" et de sortie "plume". skip-gram est l'opposé de CBOW, inférant les mots environnants à partir d'un seul mot. Par conséquent, dans CBOW et skip-gram, la couche d'entrée et la couche de sortie sont interchangées telles quelles. 機械学習殴り書き-20.jpg Désolé pour le chiffre approximatif, veuillez me pardonner car je ferai n'importe quoi.

C'est la fin de la création du modèle. Je vous remercie pour votre travail acharné.

Essayez de jouer

Maintenant que vous avez fait un modèle, jouons un peu avec.

model.wv['Monde différent']
array([-2.11708   ,  0.48667097,  1.4323529 ,  1.2636857 ,  3.7746162 ,
        1.3120568 ,  2.2951639 , -0.8711858 ,  1.1539211 , -0.54808956,
        0.6777047 ,  0.21446693, -1.3346114 ,  3.0864553 ,  2.8941932 ,
        0.78770447,  1.4938581 , -1.7187694 , -0.58673733,  1.3345109 ,
       -0.5837457 ,  1.1400971 , -1.3413094 , -1.1784658 ,  0.5038208 ,
        0.2184668 ,  0.7903634 ,  0.99530613,  1.1820349 , -0.39339375,
        1.1770552 ,  1.1574073 ,  0.8442716 , -1.5331408 , -1.3503907 ,
       -0.22193083, -1.2109485 ,  3.1873496 ,  1.5198792 , -0.3475026 ,
        1.1639794 ,  2.1614919 ,  1.44486   ,  1.4375949 , -0.12329875,
        0.76681995,  1.0177598 ,  0.15669581,  1.1294595 ,  0.6686    ,
       -2.159141  ,  2.169207  , -0.00955578,  0.3961775 ,  0.839961  ,
        0.05453613, -0.4493284 ,  2.4686203 ,  0.35897058,  0.6430457 ,
       -0.7321106 , -0.06844574,  1.1651453 ,  1.440661  , -1.9773052 ,
       -1.0753456 , -1.3506272 ,  0.90463066, -1.5573175 ,  3.1350327 ,
        2.821969  ,  1.6074497 , -0.03897483,  0.84363884,  2.4653218 ,
        0.65267706,  0.22048295,  2.229037  ,  0.8114238 , -2.0834744 ,
        0.47891453, -1.1666266 , -0.5350998 ,  0.25257212,  2.3054895 ,
       -1.2035478 ,  2.7664409 , -2.121225  ,  1.3237966 , -0.40595815,
       -0.69292945, -0.39868835,  0.22690924,  0.3353806 , -1.3963023 ,
        0.48296794,  1.5792748 , -1.4290403 , -0.7156262 ,  2.1010907 ,
        0.4076586 , -0.47208166,  1.3889042 ,  0.9942379 , -0.3618385 ,
        0.10046659, -2.8085515 , -0.12091257,  1.33154   ,  1.196143  ,
       -1.3222407 , -2.2687335 , -0.74325466, -0.6354738 ,  1.2630842 ,
       -0.98507017, -1.5422399 ,  2.0910058 , -0.71927756,  0.3105838 ,
        1.4744896 , -0.84034425,  1.3462327 ,  0.08759955,  0.29124606,
       -1.9146007 ,  1.361217  ,  2.059756  , -0.73954767, -0.8559703 ,
        1.9385318 ,  0.44165856,  0.76255304,  0.26668853,  2.135404  ,
        0.37146965,  0.17825744,  0.73358685, -0.40393773, -0.58863884,
        2.9904902 ,  0.5401901 , -0.90699816, -0.03270415,  1.4531562 ,
       -2.6180272 ,  0.03460709, -1.028743  , -1.1348175 ,  0.9340523 ,
       -1.8640583 , -0.68235844,  1.8670527 ,  0.6017655 , -1.0030158 ,
       -1.7779472 ,  0.5410166 , -0.54911584,  1.4723094 , -1.229491  ,
        1.768442  ,  0.41630363, -2.417083  , -0.46536174,  0.26779643,
        0.6326522 ,  1.2000504 ,  1.1760272 , -0.17639238,  1.1781607 ,
       -3.0334888 ,  0.93554455,  0.52397215, -0.4301726 ,  1.3797791 ,
       -3.2156737 , -0.9460046 , -0.32353514, -0.27070895, -0.01405313,
        0.78362066, -0.41299725, -1.148895  ,  1.810671  , -1.0644491 ,
       -1.2899619 , -1.2057134 , -0.43731746, -0.5561588 ,  0.18522681,
       -0.86407244,  0.6044319 ,  0.3605701 ,  1.167799  , -1.2906225 ,
       -0.41644478,  1.3338335 , -0.2976896 ,  0.56920403,  2.6792917 ],
      dtype=float32)

De cette manière, le vecteur de mot appris peut être récupéré sous la forme d'un tableau de numpy.

Puisqu'il s'agit d'une représentation vectorielle, il est bien entendu possible d'effectuer diverses opérations entre vecteurs. Trouvons un vecteur similaire au vecteur du «monde différent». Il semble que la similitude des vecteurs de mots soit généralement mesurée par la similarité cosinus. La similitude cosinus entre les deux vecteurs de mots $ \ boldsymbol {w} _1 $ et $ \ boldsymbol {w} _2 $ est donnée par:

\mathrm{similarity}(\boldsymbol{w}_1, \boldsymbol{w}_2) = \frac{\boldsymbol{w}_1.\boldsymbol{w}_2}{|\boldsymbol{w}_1||\boldsymbol{w}_2|}

Puisque cela représente $ cos \ theta $ dans l'espace euclidien, il semble intuitivement que la similitude cosinus est telle que deux vecteurs de mots pointent dans la même direction.

Avec la méthode la plus_similaire, vous pouvez récupérer les 10 premiers mots avec la similitude cosinus la plus élevée.

model.wv.most_similar('Monde différent')
[('Réincarné dans un autre monde', 0.6330794095993042),
 ('Un autre monde', 0.6327196359634399),
 ('Transfert dans un autre monde', 0.5990908145904541),
 ('monde réel', 0.5668200850486755),
 ('nouveau monde', 0.5559623837471008),
 ('Différent', 0.5458788871765137),
 ('monde', 0.5394454002380371),
 ('Japon moderne', 0.5360320210456848),
 ('Monde extraterrestre', 0.5353666543960571),
 ('Ce monde', 0.5082162618637085)]

Le résultat était généralement convaincant.

Les mots enregistrés dans le modèle peuvent être récupérés sous forme de liste avec index2word.

import copy
index2word = copy.copy(model.wv.index2word)
index2word
['de',
 'À',
 'À',
 'Est',
 'Ta',
 'main',
 'Mais',
 'Quand',
 'alors',
 'Shi',
 'Nana',
 'Aussi',
 'je',
 'Absent',
 'Ré',
 'Faire',
 'Masu',

Par défaut, les mots couramment utilisés viennent en premier dans la liste. Puisqu'il n'y a pas de mots en double dans la liste, la longueur est le nombre de vocabulaire que possède le modèle.

len(index2word)
41619

Il semble qu'environ 42 000 mots sont enregistrés.

Vous pouvez utiliser l'index de la liste comme ID de mot.

index2word.index('Monde différent')
31

Quand "un autre monde" arrive à la 32ème place, j'ai l'impression qu'il le sera.

Résumé

C'est tout pour créer un modèle avec Word2Vec. Une fois le corpus créé, je pouvais facilement créer un modèle, donc j'ai pensé que c'était vraiment pratique. Dans le prochain post (le cas échéant), j'aimerais pouvoir générer des phrases en utilisant le modèle vectoriel (provisoire) que j'ai réalisé cette fois. Alors retrouvons-nous.

Recommended Posts

Introduction à Word2Vec que même les chats peuvent comprendre
Introduction à Python que même les singes peuvent comprendre (partie 1)
Introduction à Python que même les singes peuvent comprendre (partie 2)
[Pour les débutants] Super introduction aux réseaux de neurones que même les chats peuvent comprendre
Une introduction aux Pandas pour apprendre tout en souffrant [Partie 1]
Introduction à Cython sans approfondir -2-
[Python] Comprendre comment utiliser les fonctions récursives
Comprendre comment utiliser django-filter
[Pour les débutants] Super introduction aux réseaux de neurones que même les chats peuvent comprendre
Introduction à Private TensorFlow
Une introduction à la programmation Python
Introduction à l'optimisation bayésienne
Modèle SIR que même les élèves du premier cycle du secondaire peuvent comprendre
Filtre de Kalman que vous pouvez comprendre
Une introduction à Mercurial pour les non-ingénieurs
Premiers pas avec Python pour les non-ingénieurs
[Tutoriel Python] Une introduction facile à Python
Une introduction à OpenCV pour l'apprentissage automatique
Réseau neuronal récursif: une introduction à RNN
Une introduction à Python pour l'apprentissage automatique
Une introduction à l'orientation des objets - Donnez à un objet un enfant.
Une introduction à Python pour les programmeurs en langage C
Comprendre Word2Vec
Qu'est-ce qu'un algorithme? Introduction à l'algorithme de recherche] ~ Python ~
Une introduction à l'apprentissage automatique pour les développeurs de robots
Une introduction à la programmation orientée objet pour les débutants par les débutants
Introduction à la modélisation statistique pour l'analyse des données
Même un singe peut comprendre! À propos des intentions dans discord.py!
Introduction à Python "Re" 1 Construction d'un environnement d'exécution
Une introduction à l'analyse vocale pour les applications musicales
Fonctionnement automatique du navigateur que même les débutants peuvent faire
Comprendre le développement de Python pour Pepper. -Introduction à Python Box-
[Python] Introduction au scraping WEB | Résumé des méthodes pouvant être utilisées avec webdriver