In diesem Artikel lernen wir word2vec in Colaboratory und visualisieren es mit Tensorboard.
word2vecの学習には、著作権が切れたためにフリーで公開されている青空文庫にある夏目漱石作の「吾輩は猫である」を使用します。
Indem wir die Wörter im Roman mit word2vec lernen, überprüfen wir, ob der Computer korrekt ** "I" als "Katze" ** erkennen kann. (Wenn es richtig erkannt wird, sind mein Wortvektor und der Wortvektor der Katze nahe beieinander.)
Von hier aus implementieren wir es mit Google Colaboratory.
Installieren Sie die erforderlichen Bibliotheken im Labor. Verwenden Sie die folgenden zwei.
--MeCab (+ mecab-ipadic-neologd Wörterbuch)
MeCab(+mecab-ipadic-neologd)Installation von
!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
Installieren Sie Tensorboard X.
!pip install tensorboardX
%load_ext tensorboard
Importieren Sie die installierten und Standardbibliotheken.
Bibliotheksimport
import re
import MeCab
import torch
from gensim.models import word2vec
from tensorboardX import SummaryWriter
from itertools import chain
青空文庫のサイトから、「吾輩は猫である」のzipファイルをColaboratory上でダウンロードし、解凍します。
Laden Sie die Zip-Datei von "Ich bin eine Katze" herunter und entpacken Sie sie.
!wget https://www.aozora.gr.jp/cards/000148/files/789_ruby_5639.zip
!unzip 789_ruby_5639.zip
Dann erscheint "wagahaiwa_nekodearu.txt", lesen Sie also die Datei.
Daten lesen
f = open('./wagahaiwa_nekodearu.txt', 'r', encoding='shift-jis')
texts = [t.strip() for t in f.readlines()]
f.close()
Lassen Sie uns die Datei ausgeben.
Ausgabedaten
texts
['ich bin eine Katze',
'Natsume Soseki',
'',
'-------------------------------------------------------',
'[Über die Symbole, die im Text erscheinen]',
'',
'"":Rubin',
'(Beispiel) Ich "Mein Ja"',
'',
'|: Symbol, das den Anfang einer Zeichenkette mit Ruby kennzeichnet',
'(Beispiel) Ichiban | Evil << Doaku >>',
'',
'[#]: Personennotiz eingeben\u3000 Hauptsächlich Erklärung externer Zeichen und Bezeichnung der Position der Seitenpunkte',
'(Die Nummern sind JIS X 0213 Area Area Number oder Unicode, Originalseite und Anzahl der Zeilen.)',
'(Beispiel) * [# "Word + Making a Mound", Level 4 2-88-74]',
'',
'[]: Fügen Sie die akzentzersetzte europäische Sprache hinzu',
'(Beispiel) [Quid aliud est mulier nisi amicitiae& inimica〕',
'Weitere Informationen zur Akzentzerlegung finden Sie unter der folgenden URL',
'http://www.aozora.gr.jp/accent_separation.html',
'-------------------------------------------------------',
'',
'[# 8 Zeichen nach unten] 1 [# "1" ist eine mittlere Überschrift]',
'',
'Ich bin eine Katze. Es gibt noch keinen Namen.',
'Ich habe keine Ahnung, wo ich geboren wurde. Ich erinnere mich, wie ich an einem dunklen und feuchten Ort geweint habe. Ich habe hier zum ersten Mal Menschen gesehen. Außerdem hörte ich später, dass es die böseste Rasse aller Menschen war, die Shosei genannt wurde. Dieser Student erzählt manchmal, wie er uns fängt, kocht und isst. Allerdings habe ich damals nichts gedacht, also fand ich es nicht besonders beängstigend. Als es jedoch auf seine Handfläche gelegt und angehoben wurde, fühlte es sich einfach flauschig an. Es ist wahrscheinlich der Beginn eines sogenannten Menschen, der sich auf der Handfläche ein wenig beruhigt und das Gesicht des Schülers sieht. Das Gefühl, das ich zu dieser Zeit für seltsam hielt, bleibt bestehen. Das Gesicht, das mit den ersten Haaren verziert werden sollte, ist rutschig und sieht aus wie eine Medikamentendose. Danach habe ich viele Katzen getroffen, aber ich habe noch nie eine so einrädrige Katze getroffen. Nicht nur das, die Mitte des Gesichts ragt zu hervor. Dann blase ich manchmal Rauch aus dem Inneren des Lochs. Anscheinend war mein Hals so schwach, dass ich wirklich schwach war. Ungefähr zu dieser Zeit erfuhr ich schließlich, dass dies eine Zigarette war, die Menschen trinken.',
'Ich saß eine Weile gut gelaunt hinter der Handfläche dieses Schülers, aber nach einer Weile fing ich an, mit sehr hoher Geschwindigkeit zu fahren. Ich weiß nicht, ob sich der Schüler bewegen wird oder nur ich, aber meine Augen richten sich auf die Dunkelheit. Mir ist schlecht. Als ich dachte, dass es überhaupt nicht helfen würde, hörte ich ein lautes Geräusch und ein Feuer brach aus meinen Augen aus. Ich erinnere mich bis dahin, aber ich weiß nicht, was ich tun soll oder wie viel ich mir einfallen lassen will.',
'Als ich plötzlich bemerkte, war kein Schüler da. Es gibt viele Brüder und ich kann Piki nicht einmal sehen. Sogar die wesentliche Mutter von Kanjin ist verschwunden. Darüber hinaus ist es hell und dunkel, im Gegensatz zu den Orten, an denen ich bisher war. Ich kann nicht einmal meine Augen öffnen. Wenn etwas mit Yoko nicht stimmt, tut es sehr weh, wenn ich es herausnehme. Ich wurde plötzlich von oben auf Sasahara verlassen.',
・ ・ ・]
Wenn wir uns die Ausgabeergebnisse ansehen, sehen wir Folgendes.
Wir werden diese Vorverarbeitung im nächsten Schritt durchführen.
Hier bereiten wir eine Funktion zur Vorverarbeitung von Sätzen vor.
Funktion zur Satzvorverarbeitung
def preprocessTexts(texts):
# 1.Die Beschreibung des Romans vor und nach dem Satz wurde gelöscht
texts = texts[23:-17]
# 2.Gelöschter Rubin, Begrenzer, Inputter-Notiz, akzentzerlegte europäische Sprache
signs = re.compile(r'(《.*?》)|(|)|([#.*?])|(〔.*?〕)|(\u3000)')
texts = [signs.sub('',t) for t in texts]
# 3.Teilen Sie den Satz mit "."
texts = [t.split('。') for t in texts]
texts = list(chain.from_iterable(texts))
#Löschen Sie Sätze mit einem Zeichen oder weniger (da es sich nicht um einen Satz handelt).
texts = [t for t in texts if len(t) > 1]
return texts
Vorverarbeitung
texts = preprocessTexts(texts)
print('Anzahl der Sätze:', len(texts))
Anzahl der Sätze: 9058
Die Vorverarbeitung hat zu einer Liste von Sätzen geführt, die word2vec lernen kann.
Es lernt endlich word2vec. Bevor Sie lernen können, müssen Sie den Satz teilen (in Wörter unterteilt). Verwenden Sie das installierte MeCab, um jeden Satz zu trennen.
Definieren Sie eine Funktion zum Schreiben.
Funktion zum Teilen
def getWords(sentence, tokenizer, obj_pos=['all'], symbol=False):
"""
Teile Sätze in Wörter (getrenntes Schreiben)
Parameters
----------
sentence : str
Sätze zu teilen
tokenizer : class
MeCab Tokenizer
obj_pos : list of str, default ['all']
Ein Teil der Wörter zu bekommen
symbol : bool, default False
Gibt an, ob das Symbol eingefügt werden soll
Returns
--------
words : list of str
Sätze durch Worte geteilt
"""
node = tokenizer.parseToNode(sentence)
words = []
while node:
results = node.feature.split(",")
pos = results[0] #Teil
word = results[6] #Grundform des Wortes
if pos != "BOS/EOS" and (pos in obj_pos or 'all' in obj_pos) and (pos!='Symbol' or symbol):
if word == '*':
word = node.surface
words.append(word)
node = node.next
return words
Verwenden Sie die Funktion, um die Wörter zu trennen. Bereiten Sie zu diesem Zeitpunkt zwei Muster von Teilungsergebnissen vor.
Trennung von Sätzen
#Tokenizer einstellen
path = "-d /usr/lib/x86_64-linux-gnu/mecab/dic/mecab-ipadic-neologd"
tokenizer = MeCab.Tagger(path)
#Teilen Sie den Text
words = [getWords(t, tokenizer, symbol=True) for t in texts]
#Holen Sie sich Nomenklatur
nouns = [getWords(t, tokenizer, obj_pos=['Substantiv']) for t in texts]
nouns = set(chain.from_iterable(nouns)) #Eine angezeigte Nomenklatur
Von hier aus lernt man word2vec. Stellen Sie die Parameter wie folgt ein.
Parameter | Wert | Erläuterung |
---|---|---|
size | 300 | Anzahl der Dimensionen des Wortvektors |
sg | 1 | Zu verwendender Algorithmus(skip-gram:1, C-BOW:0) |
min_count | 2 | Die Anzahl der Auftritte beträgt min_Ignorieren Sie Wörter, die weniger als zählen |
seed | 0 | Zufälliger Samen |
Im Allgemeinen wird ein Sprunggramm verwendet, das als sehr genau bezeichnet wird, und der Startwert wird eingestellt, um die Reproduzierbarkeit sicherzustellen. size und min_count sind empirische Regeln ~~ (passender Name) ~~. Andere Parameter bleiben auf ihren Standardeinstellungen.
Parametereinstellung
size = 300
sg = 1
min_count = 2
seed = 0
Als nächstes kommt das Modelltraining. Um die Visualisierung verständlich zu machen, wird der Vektor des Trainingsergebnisses auf die L2-Norm gesetzt.
Word2vec lernen
model = word2vec.Word2Vec(words, size=size, min_count=min_count, sg=sg, seed=seed)
model.init_sims(replace=True)
Damit ist das Erlernen von word2vec abgeschlossen. Dieses Mal werden wir zur Vereinfachung der Visualisierung auf die 500 wichtigsten Wörter mit der höchsten Häufigkeit des Auftretens von Nomenklaturen eingrenzen.
Speicherung von Lernergebnissen
#Holen Sie sich eine Liste der verteilten Ausdrücke und Wörter
word_vectors = model.wv.vectors
index2word = model.wv.index2word
#Nomenklaturindex abrufen
nouns_id = [i for i, n in enumerate(index2word) if n in nouns]
#Extrahieren Sie die obersten 500 Wörter, deren Teilwörter Nomenklatur sind
word_vectors = word_vectors[nouns_id][:500]
index2word = [index2word[i] for i in nouns_id][:500]
Schließlich wird das gelernte Wort2vec von Tensorbord visualisiert. Gibt eine Datei zur Visualisierung aus. Sie können einfach mit der Bibliothek TensorbordX ausgeben.
Ausgabedatei zum Ausführen von Tensorboard
writer = SummaryWriter('./runs')
writer.add_embedding(torch.FloatTensor(word_vectors), metadata=index2word)
writer.close()
Führen Sie die Ausgabedatei aus. Sie können Tensorboard in Colaboratory mit ngrok ausführen.
Führen Sie TensorBoard aus
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'])"
Wenn Sie den obigen Code ausführen, wird eine URL wie "http://XXXXXXXX.ngrok.io" ausgegeben, sodass Sie TensorBoard sehen können, wenn Sie darauf zugreifen! Das ist es!
Wenn Sie darauf zugreifen, sieht es wie folgt aus. Bitte warten Sie eine Weile oder ändern Sie "** IN ACTIVE " oben rechts in " PROJECTOR **".
Dann erscheint das von PCA in 3 Dimensionen zusammengefasste Ergebnis.
Bitte wechseln Sie von PCA links zu T-SNE. Es wird weiter aggregiert und ähnliche Wörter werden zusammengestellt. Dies ist ein Sukusho, aber es ist sehr interessant, weil Sie tatsächlich sehen können, wie sich der Lernprozess bewegt.
Wenn das Lernen konvergiert hat, schauen wir uns die Ähnlichkeit (Distanz) zwischen "Ich" und "Katze" an, die das Hauptthema ist. Geben Sie "I" in die Suche rechts ein und suchen Sie den "I" -Punkt.
Unten links befindet sich "I" und oben rechts "Cat". Der Abstand ist nicht sehr ähnlich zu 0,317, aber es stellt sich heraus, dass er ziemlich ähnlich ist. Es wird angenommen, dass dies passiert ist, weil "Ich" und "Katze" selten im selben Kontext erscheinen.
Betrachtet man die Wörter mit hoher Ähnlichkeit jedes Wortes, Wörter, die nahe an "Ich" liegen, werden höher eingestuft als "er" und "sie", und Wörter, die "Katze" am nächsten kommen, sind "Menschen" und werden von Tieren gruppiert. Wenn man ähnliche Wörter betrachtet, scheint es, dass sie gut lernen.
Dieses Mal haben wir word2vec in Colaboratory gelernt und es mit TensorBoard visualisiert. Es ist sehr praktisch, es einfach implementieren zu können, ohne eine Umgebung aufzubauen. Noch bequemer wäre es, wenn PROJECTOR auf Colaboratoy visualisiert werden könnte, ohne es im Internet zu veröffentlichen! Wir erwarten Unterstützung für die Visualisierung von PROJECTOR.
Ich habe die ausführliche Erklärung weggelassen. Überprüfen Sie daher den Referenzartikel auf detaillierte Erklärungen wie Begriffe und Bibliotheken.
[Datenvisualisierung] TensorBoard Projector unter Keras und Colaboratory ausführen [Bis zur Verwendung von Mecab-ipadic-Neologd mit 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 der Gemsim word2vec-Optionen ngrok ist zu bequem
Recommended Posts