Dans cet article, nous allons apprendre word2vec dans Colaboratory et le visualiser avec Tensorboard.
word2vecの学習には、著作権が切れたためにフリーで公開されている青空文庫にある夏目漱石作の「吾輩は猫である」を使用します。
En apprenant les mots du roman avec word2vec, nous vérifierons si l'ordinateur peut correctement ** "I" peut être reconnu comme un "chat" **. (S'il est reconnu correctement, mon vecteur de mots et le vecteur de mots de chat seront proches)
À partir de là, nous mettrons en œuvre en utilisant Google Colaboratory.
Installez les bibliothèques nécessaires sur le Colaboratoire. Utilisez les deux suivants.
--MeCab (+ dictionnaire mecab-ipadic-neologd)
MeCab(+mecab-ipadic-neologd)Installation de
!apt-get -q -y install sudo file mecab libmecab-dev mecab-ipadic-utf8 git curl python-mecab > /dev/null
!git clone --depth 1 https://github.com/neologd/mecab-ipadic-neologd.git > /dev/null
!echo yes | mecab-ipadic-neologd/bin/install-mecab-ipadic-neologd -n > /dev/null 2>&1
!pip install mecab-python3 > /dev/null
Installez Tensorboard X
!pip install tensorboardX
%load_ext tensorboard
Importez les bibliothèques installées et standard.
Import de bibliothèque
import re
import MeCab
import torch
from gensim.models import word2vec
from tensorboardX import SummaryWriter
from itertools import chain
青空文庫のサイトから、「吾輩は猫である」のzipファイルをColaboratory上でダウンロードし、解凍します。
Téléchargez et décompressez le fichier zip "Je suis un chat"
!wget https://www.aozora.gr.jp/cards/000148/files/789_ruby_5639.zip
!unzip 789_ruby_5639.zip
Ensuite, "wagahaiwa_nekodearu.txt" apparaîtra, alors lisez le fichier.
Lire les données
f = open('./wagahaiwa_nekodearu.txt', 'r', encoding='shift-jis')
texts = [t.strip() for t in f.readlines()]
f.close()
Sortons le fichier.
Des données de sortie
texts
['je suis un chat',
'Natsume Soseki',
'',
'-------------------------------------------------------',
'[À propos des symboles qui apparaissent dans le texte]',
'',
'"":rubis',
'(Exemple) I "Mon Oui"',
'',
'|: Symbole qui identifie le début d'une chaîne de caractères avec ruby',
'(Exemple) Ichiban | Evil << Doaku >>',
'',
'[#]: Saisissez la note de la personne\u3000 Principalement explication des caractères externes et désignation de la position des points latéraux',
'(Les nombres sont le numéro de zone JIS X 0213 ou Unicode, la page d'origine et le nombre de lignes)',
'(Exemple) * [# "Word + Making a mound", Niveau 4 2-88-74]',
'',
'[]: Joindre la langue européenne décomposée par l'accent',
'(Exemple) [Quid aliud est mulier nisi amicitiae& inimica〕',
'Veuillez vous référer à l'URL suivante pour plus de détails sur la décomposition d'accent',
'http://www.aozora.gr.jp/accent_separation.html',
'-------------------------------------------------------',
'',
'[# 8 caractères vers le bas] 1 [# "1" est le titre du milieu]',
'',
'Je suis un chat. Il n'y a pas encore de nom.',
'Je n'ai aucune idée d'où je suis né. Je me souviens avoir pleuré dans un endroit sombre et humide. J'ai vu des êtres humains pour la première fois ici. De plus, j'ai entendu plus tard que c'était la race la plus perverse de tous les êtres humains appelée Shosei. Cet étudiant est une histoire qui nous surprend parfois, bouilli et mange. Cependant, je ne pensais rien à ce moment-là, donc je ne pensais pas que c'était particulièrement effrayant. Cependant, quand il a été placé sur sa paume et soulevé, il était juste duveteux. C'est probablement le début de ce qu'on appelle un être humain qui se calme un peu sur la paume et voit le visage de l'élève. Le sentiment que je trouvais étrange à cette époque demeure toujours. Le visage, qui doit être décoré avec les premiers cheveux, est glissant et ressemble à un médicament. Après cela, j'ai rencontré beaucoup de chats, mais je n'ai jamais rencontré un tel chat à une roue. Non seulement cela, le centre du visage est trop saillant. Puis, de l'intérieur du trou, je souffle parfois de la fumée. Apparemment, ma gorge était si faible que j'étais vraiment faible. C'est à cette époque que j'ai finalement appris qu'il s'agissait d'une cigarette que les humains boivent.',
'Je me suis assis de bonne humeur pendant un moment derrière la paume de cet étudiant, mais au bout d'un moment, j'ai commencé à rouler à très grande vitesse. Je ne sais pas si l'élève bougera ou seulement je bougerai, mais mes yeux se tournent vers l'obscurité. Je me sens malade. Quand je pensais que cela n'aiderait pas du tout, j'ai entendu un bruit fort et un feu a éclaté de mes yeux. Je me souviens jusque-là, mais je ne sais pas quoi faire ni à quel point j'essaye de trouver.',
'Quand j'ai soudainement remarqué, il n'y avait pas d'élève. Il y a beaucoup de frères et je ne peux même pas voir Piki. Même la mère essentielle de Kanjin a disparu. En plus de cela, il fait clair et sombre, contrairement aux endroits où je suis allé jusqu'à présent. Je ne peux même pas ouvrir les yeux. Si quelque chose ne va pas avec Yoko, ça fait très mal quand je le retire. J'ai été soudainement abandonné à Sasahara du haut de la paille.',
・ ・ ・]
En regardant les résultats de sortie, nous pouvons voir ce qui suit.
Nous effectuerons ces prétraitements à l'étape suivante.
Ici, nous allons préparer une fonction pour le prétraitement des phrases.
Fonction de prétraitement des phrases
def preprocessTexts(texts):
# 1.Suppression de la description du roman avant et après la phrase
texts = texts[23:-17]
# 2.Rubis supprimé, délimiteur, note d'entrée, langue européenne décomposée par l'accent
signs = re.compile(r'(《.*?》)|(|)|([#.*?])|(〔.*?〕)|(\u3000)')
texts = [signs.sub('',t) for t in texts]
# 3.Divisez la phrase par "."
texts = [t.split('。') for t in texts]
texts = list(chain.from_iterable(texts))
#Supprimer les phrases d'un caractère ou moins (car ce n'est pas une phrase)
texts = [t for t in texts if len(t) > 1]
return texts
Prétraitement
texts = preprocessTexts(texts)
print('Nombre de phrases:', len(texts))
Nombre de phrases: 9058
Le prétraitement a abouti à une liste de phrases que word2vec peut apprendre.
Il apprend enfin word2vec. Avant de pouvoir apprendre, vous devez diviser la phrase (divisée en mots). Utilisez le MeCab installé pour séparer chaque phrase.
Définissez une fonction dans laquelle écrire.
Fonction de partage
def getWords(sentence, tokenizer, obj_pos=['all'], symbol=False):
"""
Divisez les phrases en mots (écriture séparée)
Parameters
----------
sentence : str
Phrases à partager
tokenizer : class
Tokenizer MeCab
obj_pos : list of str, default ['all']
Une partie des mots à obtenir
symbol : bool, default False
S'il faut inclure le symbole
Returns
--------
words : list of str
Phrases divisées par mot
"""
node = tokenizer.parseToNode(sentence)
words = []
while node:
results = node.feature.split(",")
pos = results[0] #Partie
word = results[6] #Forme de base du mot
if pos != "BOS/EOS" and (pos in obj_pos or 'all' in obj_pos) and (pos!='symbole' or symbol):
if word == '*':
word = node.surface
words.append(word)
node = node.next
return words
Utilisez la fonction pour séparer les mots. À ce stade, préparez deux modèles de résultats de division.
Séparation des phrases
#Définir Tokenizer
path = "-d /usr/lib/x86_64-linux-gnu/mecab/dic/mecab-ipadic-neologd"
tokenizer = MeCab.Tagger(path)
#Divisez le texte
words = [getWords(t, tokenizer, symbol=True) for t in texts]
#Obtenir la nomenclature
nouns = [getWords(t, tokenizer, obj_pos=['nom']) for t in texts]
nouns = set(chain.from_iterable(nouns)) #Un ensemble de nomenclature qui apparaît
De là, c'est l'apprentissage de word2vec. Réglez les paramètres comme suit.
Paramètres | valeur | La description |
---|---|---|
size | 300 | Nombre de dimensions du vecteur de mot |
sg | 1 | Algorithme à utiliser(skip-gram:1, C-BOW:0) |
min_count | 2 | Le nombre d'apparitions est de min_Ignorer les mots moins que compter |
seed | 0 | Graine aléatoire |
Généralement, skip-gram, qui est dit très précis, est utilisé, et la valeur de départ est définie pour assurer la reproductibilité. size et min_count sont des règles empiriques ~~ (nom approprié) ~~. Les autres paramètres conservent leurs valeurs par défaut.
Paramètres des paramètres
size = 300
sg = 1
min_count = 2
seed = 0
Vient ensuite la formation des modèles. Afin de rendre la visualisation facile à comprendre, le vecteur du résultat de la formation est défini sur la norme L2.
Apprentissage de word2vec
model = word2vec.Word2Vec(words, size=size, min_count=min_count, sg=sg, seed=seed)
model.init_sims(replace=True)
Ceci termine l'apprentissage de word2vec. Cette fois, afin de simplifier la visualisation, nous nous limiterons aux 500 premiers mots avec la fréquence d'occurrence la plus élevée de la nomenclature.
Stockage des résultats d'apprentissage
#Obtenez une liste d'expressions et de mots distribués
word_vectors = model.wv.vectors
index2word = model.wv.index2word
#Obtenir l'index de la nomenclature
nouns_id = [i for i, n in enumerate(index2word) if n in nouns]
#Extraire les 500 premiers mots dont les mots de partie sont la nomenclature
word_vectors = word_vectors[nouns_id][:500]
index2word = [index2word[i] for i in nouns_id][:500]
Enfin, le mot2vec appris est visualisé par Tensorbord. Produit un fichier pour la visualisation. Vous pouvez facilement sortir en utilisant la bibliothèque TensorbordX.
Fichier de sortie pour exécuter Tensorboard
writer = SummaryWriter('./runs')
writer.add_embedding(torch.FloatTensor(word_vectors), metadata=index2word)
writer.close()
Exécutez le fichier de sortie. Vous pouvez exécuter Tensorboard dans Colaboratory en utilisant ngrok.
Exécuter TensorBoard
LOG_DIR = './runs'
get_ipython().system_raw(
'tensorboard --logdir={} --host 0.0.0.0 --port 6006 &'
.format(LOG_DIR)
)
!wget https://bin.equinox.io/c/4VmDzA7iaHb/ngrok-stable-linux-amd64.zip
!unzip ngrok-stable-linux-amd64.zip
get_ipython().system_raw('./ngrok http 6006 &')
!curl -s http://localhost:4040/api/tunnels | python3 -c \
"import sys, json; print(json.load(sys.stdin)['tunnels'][0]['public_url'])"
Lorsque vous exécutez le code ci-dessus, une URL comme "http://XXXXXXXX.ngrok.io" sera affichée, vous pouvez donc voir TensorBoard lorsque vous y accédez! C'est tout!
Lorsque vous y accédez, il ressemble à ce qui suit. Veuillez patienter quelques instants ou remplacez "** IN ACTIVE " en haut à droite par " PROJECTOR **".
Ensuite, le résultat résumé en 3 dimensions par PCA apparaîtra.
Veuillez changer de PCA sur la gauche à T-SNE. Il est ensuite agrégé et des mots similaires sont rassemblés. C'est un sukusho, mais c'est très intéressant car vous pouvez réellement voir le processus d'apprentissage se déplacer.
Lorsque l'apprentissage a convergé, regardons la similitude (distance) entre «je» et «chat», qui est le sujet principal. Entrez «I» dans la recherche sur la droite et trouvez le point «I».
Il y a "I" en bas à gauche et "Cat" en haut à droite. La distance n'est pas très similaire à 0,317, mais elle s'avère être raisonnablement similaire. On pense que cela s'est produit parce que «je» et «chat» apparaissent rarement dans le même contexte.
En regardant les mots avec une grande similitude de chaque mot, Les mots qui sont proches de «je» sont classés plus haut comme «il» et «ils», et les mots qui sont les plus proches de «chat» sont «humains» et sont regroupés par animaux. En regardant des mots similaires, il semble qu'ils apprennent bien.
Cette fois, nous avons appris word2vec sur Colaboratory et l'avons visualisé avec TensorBoard. Il est très pratique de pouvoir l'implémenter facilement sans créer d'environnement. Ce serait encore plus pratique si PROJECTEUR pouvait être visualisé sur Colaboratoy sans le publier sur Internet! Nous attendons un support pour la visualisation du PROJECTEUR.
J'ai omis l'explication détaillée, veuillez donc consulter l'article de référence pour des explications détaillées telles que les termes et les bibliothèques.
[Visualisation des données] Exécutez le projecteur TensorBoard sur Keras et Colaboratory [Jusqu'à l'utilisation de Mecab-ipadic-Neologd avec Google Colaboratory](https://shunyaueta.com/posts/2018-04-23_google-colaboratory-%E3%81%A7-mecabipadicneologd-%E3%82%92%E4% BD% BF% E3% 81% 86% E3% 81% BE% E3% 81% A7 /) Liste des options de Gemsim word2vec ngrok est trop pratique
Recommended Posts