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.
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).
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.
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. 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é.
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.
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