[Python] [Verarbeitung natürlicher Sprache] Ich habe Deep Learning ausprobiert (auf Japanisch von Grund auf neu erstellt)

Einführung

Ist es für Anfänger (insbesondere Selbststudenten) nicht am schwierigsten, Korpus (eine große Anzahl von Sätzen) zu sammeln, wenn sie eine Verarbeitung natürlicher Sprache mit maschinellen Lernalgorithmen auf Japanisch durchführen?

In dem Thema "Deep Learning from Grundle ❷ ~ Natural Language Processing ~" und anderen Büchern steht im Grunde der Umgang mit dem englischen Korpus im Mittelpunkt, und der japanische Korpus hat eine andere Angewohnheit als Englisch. Die aktuelle Situation ist, dass es schwierig ist, die Verarbeitung von zu erleben. (Zumindest hatte ich große Probleme, weil ich überhaupt keine japanischen Korpora sammeln konnte.)

Also habe ich dieses Mal den Artikel "Livedoor News" (deutsche Mitteilung) verwendet und ihn wahrscheinlich einmal für diejenigen bekommen, die maschinelles Lernen betreiben. Ich möchte ein gutes Buch "Deep Learning von Grund auf ❷ ~ Verarbeitung natürlicher Sprache ~" auf Japanisch implementieren.

Zählbasierte Verarbeitung natürlicher Sprache

Dieses Mal werde ich den Korpus durch Japanisch ersetzen und ihn für die folgende Reihe von "Deep Learning" von Grund auf neu implementieren. Im Fall von Japanisch ist die Vorverarbeitung im Gegensatz zu Englisch problematisch. Konzentrieren Sie sich daher bitte auf diesen Bereich.
Ziel
Betreff: "Deep Learning von Grund auf neu ❷" Umfang dieser Zeit: Kapitel 2 Verteilte Darstellung von natürlicher Sprache und Wörtern 2.3 Zählbasierte Methode ~ 2.4.5 Auswertung mit PTB-Datensatz

Umgebung

Mac OS(Mojave) Python3(Python 3.7.4) jupiter Notebook

0. Vorbereitungen

Bei den Originaldaten handelt es sich um eine Textdatei, die für jeden Artikelliefertermin erstellt wird. Dies ist zwar umständlich (wahrscheinlich mehr als 100 Dateien). Kombinieren Sie daher zunächst alle Textdateien zu einer neuen Textdatei .. Sie können mehrere Textdateien mit dem folgenden Befehl (für Mac) kombinieren.

Terminal


$ cat ~/Verzeichnisname/*.txt >Neuer Name der Textdatei.txt


Referenz
https://ultrabem-branch3.com/informatics/commands_mac/cat_mac [Beiseite] Es ist wirklich nur eine Seite, aber ich persönlich hatte mit dem oben genannten Prozess zu kämpfen. .. Zuerst bin ich in die Datei gegangen und habe den Befehl " cat * .txt> new text file name.txt`` "ausgeführt, aber der Vorgang wurde wahrscheinlich vollständig abgeschlossen, wahrscheinlich weil der Verzeichnisname nicht angegeben wurde. (Vielleicht hat der Platzhalter versucht, alle Textdateien auf meinem PC zu lesen?) Und am Ende erhielt ich eine Bang-Bang-Warnung mit der Aufschrift "Nicht genug Speicherplatz!" .. .. Bitte seien Sie vorsichtig.

1. 1. Datenvorverarbeitung

** ⑴ Trennung von Sätzen **

python


import sys
sys.path.append('..')
import re
import pickle
from janome.tokenizer import Tokenizer
import numpy as np
import collections

with open("corpus/dokujo-tsushin/dokujo-tsushin-half.txt", mode="r",encoding="utf-8") as f: #Anmerkung 1)
    original_corpus = f.read()
    
text = re.sub("http://news.livedoor.com/article/detail/[0-9]{7}/","", original_corpus) #Anmerkung 2)
text = re.sub("[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}\+[0-9]{4}","", text) #Notiz 3)
text = re.sub("[\f\n\r\t\v]","", text)
text = re.sub(" ","", text)
text = re.sub("[「」]","", text)
text = [re.sub("[()]","", text)]

#<Punkt>
t = Tokenizer()

words_list = []
for word in text:
    words_list.append(t.tokenize(word, wakati=True))
    
with open("words_list.pickle",mode='wb') as f:
    pickle.dump(words_list, f)

Anmerkung 1) Dieses Mal bereiten wir im Gegensatz zu "Deep Learning ❷ von Grund auf neu" den Korpus selbst vor, damit wir den Zielkorpus lesen können. Auch dieses Mal wird "dokujo-tsushin-half.txt" gelesen, aber obwohl ich ursprünglich versucht habe, "dokujo-tsushin-all.txt" zu lesen, wurde eine Warnung ausgegeben, dass es aufgrund von Überkapazität nicht gelesen werden konnte. Daher habe ich "alle" aufgegeben und "die Hälfte" verwendet (⓪ die Kombination von vorbereiteten Textdateien führte nur die Hälfte aller Dateien aus).

** ** Da diesmal die Verarbeitung der japanischen natürlichen Sprache durchgeführt wird, können Sätze nicht mit der im Buch beschriebenen Methode in Wörter zerlegt werden (durch Leerzeichen in Wörter aufgeteilt). Also installierte ich dieses Mal janome, eine Bibliothek von Drittanbietern, und zerlegte (getrennte) japanische Sätze in Wörter. Da die Anzahl der Sätze groß und die Anzahl der Wörter daher groß ist, habe ich mich entschieden, das Ausführungsergebnis mit pickle zu speichern, damit ich es nicht an der Stelle ausführen muss, an der ich jede Minute schreibe. Die Pickle-Datei kann wie folgt aufgerufen werden und kann um ein Vielfaches schneller geladen werden als das Aufteilen von Grund auf.


with open('words_list.pickle', mode='rb') as f:
    words_list = pickle.load(f)

print(words_list) #Wenn Sie das Ladeergebnis nicht anzeigen müssen, ist diese Beschreibung nicht erforderlich

# =>Ausgabe
#[['Freund', 'Vertreter', 'von', 'Rede', '、', 'Deutschland', 'Frau', 'Ist', 'Wie', 'Machen', 'Hand', 'Ist', '?', 'demnächst', 'Juni', '・', 'Braut', 'Wann', 'Anruf', 'Sein', 'Juni', '。', 'Deutschland', 'Frau', 'von', 'Während ~', 'Zu', 'Ist', 'mich selber', 'von', 'Formel', 'Ist', 'noch', 'Nana', 'vonZu', 'Anruf', 'Re', 'Hand', 'Gerade', '…', '…', 'WannichU.', 'Feier', 'Armut', 'Status', 'von', 'Mann', 'Ebenfalls', 'Viele', 'von', 'damit', 'Ist', 'Nanaich', 'Ich wundere mich', 'U.', 'Oder', '?', 'SaらZu', 'Teilnahme', 'Anzahl', 'Zu', 'Stapel', 'Hand', 'Gehen', 'Wann', '、', 'こHmmNana', 'Bitte', 'ごWann', 'Zu', 'Sa', 'Sein', 'こWann', 'Ebenfalls', '少Nanaく', 'Nanaich', '。', 'Bitte', 'Aber', 'Gibt es', 'Hmm', 'Ist', 'aber', '…', '…', 'Freund', 'Vertreter', 'von', 'Rede', '、', 'Schließlich', 'Hand', 'くRe', 'Nanaich', 'Oder', 'Nana', '?', 'SaHand', 'そHmmNana', 'Wannき', '、', 'Deutschland', 'Frau', 'Ist', 'Wie', 'Korrespondenz', 'Shi', 'Tara', 'Gut', 'Oder', '?', 'Vor kurzem', 'Ist', 'Wann', 'das Internet', 'etc', 'damit', 'Suche', 'すRe', 'Wenn', 'Freund', 'Vertreter', 'Rede', 'zum', 'von', 'Beispielsatz', 'Seite? ˅', 'Aber', 'TaくSaHmm', 'aus', 'Hand', 'Kommen Sie', 'vondamit', '、', 'そReら', 'Zu', 'Referenz', 'Zu', 'すRe', 'Wenn', '、', 'Sicher', 'Nana', 'Ebenfallsvon', 'Ist', 'Wer', 'damitEbenfalls', 'Erstellen', 'damitきる', '。', 'ShiOderShi', 'Yuri', 'SaHmm', '33', 'Alter', 'Ist', 'Netz', 'Zu', 'Referenz', 'Zu', 'Shi', 'Hand', 'Erstellen', 'Shi', 'Ta', 'Ebenfallsvonvon', 'こRe', 'damit', '本当Zu', 'Gut', 'von', 'Oder', 'Angst', 'damitShi', 'Ta', '。', '一Mann暮らShi', 'Nana', 'vondamit', '聞Oder', 'einstellen', 'Hand', 'Impressionen', 'Zu', 'Ichi', 'Hand', 'くSein', 'Mann', 'Ebenfalls', 'ich', 'Nanaich', 'Shi', '、', 'Oder', 'Wann', 'Ichi', 'Hand', 'andere', 'von', 'Freund', 'Zu', 'Nimm dir die Mühe', '聞Oder', 'einstellenる', 'von', 'Ebenfalls', 'Wie', 'Oder', 'Wann',・ ・ ・ Unten weggelassen

** ⑵ Erstellen Sie eine Liste mit IDs für Wörter **

def preprocess(text):
    word_to_id = {}
    id_to_word = {}
    
    #<Punkt>
    for words in words_list:
        for word in words:
            if word not in word_to_id:
                new_id = len(word_to_id)
                word_to_id[word] = new_id
                id_to_word[new_id] = word
                
    corpus = [word_to_id[w] for w in words for words in words_list]
    
    return corpus, word_to_id, id_to_word

corpus, word_to_id, id_to_word = preprocess(text)

print('corpus size:', len(corpus))
print('corpus[:30]:', corpus[:30])
print()
print('id_to_word[0]:', id_to_word[0])
print('id_to_word[1]:', id_to_word[1])
print('id_to_word[2]:', id_to_word[2])
print()
print("word_to_id['Frau']:", word_to_id['Frau'])
print("word_to_id['Ehe']:", word_to_id['Ehe'])
print("word_to_id['Mann']:", word_to_id['Mann'])

# =>Ausgabe
# corpus size: 328831
# corpus[:30]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 5, 6, 2, 22, 23, 7, 24, 2]

# id_to_word[0]:Freund
# id_to_word[1]:Vertreter
# id_to_word[2]:von

# word_to_id['Frau']: 6
# word_to_id['Ehe']: 456
# word_to_id['Mann']: 1453


Punkt
-Die Vorverarbeitungsfunktion ist im Grunde die gleiche wie in diesem Buch, aber dieses Mal wurde die Wortteilung des Satzes bereits vorgenommen, sodass dieser Teil gelöscht wurde, und im Gegensatz zu diesem Buch wird der for-Satz zweimal gedreht. Der Punkt ist, eine ID zu geben. Der Grund, warum der for-Satz zweimal gedreht wird, ist, dass das Wort in der Doppelliste enthalten ist, da das Wort durch die Teilung geteilt wird, die sich von diesem Buch unterscheidet.

2. Auswertung

Ich werde die Details des Folgenden weglassen, da es viele Teile gibt, die sich mit dem Inhalt des Buches überschneiden, aber ich würde es begrüßen, wenn Sie darauf verweisen könnten, da es an einigen Stellen Kommentare enthält.

#Erstellen einer Matrix für das gleichzeitige Auftreten
def create_co_matrix(corpus, vocab_size, window_size=1):
    corpus_size = len(corpus)
    co_matrix = np.zeros((vocab_size, vocab_size), dtype=np.int32)
    
    for idx, word_id in enumerate(corpus):
        for i in range(1, window_size + 1):
            left_idx = idx - i
            right_idx = idx + i
            
            if left_idx >= 0:
                left_word_id = corpus[left_idx]
                co_matrix[word_id, left_word_id] += 1
                
            if right_idx < corpus_size:
                right_word_id = corpus[right_idx]
                co_matrix[word_id, right_word_id] += 1
            
    return co_matrix

#Beurteilung der Ähnlichkeit zwischen Vektoren (cos Ähnlichkeit)
def cos_similarity(x, y, eps=1e-8):
    nx = x / (np.sqrt(np.sum(x ** 2)) + eps)
    ny = y / (np.sqrt(np.sum(y ** 2)) + eps)
    return np.dot(nx, ny)

#Rangfolge der Ähnlichkeit zwischen Vektoren
def most_similar(query, word_to_id, id_to_word, word_matrix, top=5):
    if query not in word_to_id:
        print('%s is not found' % query)
        return

    print('\n[query] ' + query)
    query_id = word_to_id[query]
    query_vec = word_matrix[query_id]

    vocab_size = len(id_to_word)

    similarity = np.zeros(vocab_size)
    for i in range(vocab_size):
        similarity[i] = cos_similarity(word_matrix[i], query_vec)

    count = 0
    for i in (-1 * similarity).argsort():
        if id_to_word[i] == query:
            continue
        print(' %s: %s' % (id_to_word[i], similarity[i]))

        count += 1
        if count >= top:
            return

#Verbesserung der Wortrelevanzindikatoren durch positive gegenseitige Information (PPMI)
def ppmi(C, verbose=False, eps = 1e-8):
    M = np.zeros_like(C, dtype=np.float32)
    N = np.sum(C)
    S = np.sum(C, axis=0)
    total = C.shape[0] * C.shape[1]
    cnt = 0

    for i in range(C.shape[0]):
        for j in range(C.shape[1]):
            pmi = np.log2(C[i, j] * N / (S[j]*S[i]) + eps)
            M[i, j] = max(0, pmi)

            if verbose:
                cnt += 1
                if cnt % (total//100) == 0:
                    print('%.1f%% done' % (100*cnt/total))
    return M

window_size = 2
wordvec_size = 100

corpus, word_to_id, id_to_word = preprocess(text)
vocab_size = len(word_to_id)
print('counting  co-occurrence ...')
C = create_co_matrix(corpus, vocab_size, window_size)
print('calculating PPMI ...')
W = ppmi(C, verbose=True)

print('calculating SVD ...')
try:
    #Dimensionsreduktion durch SVD mit sklearn
    from sklearn.utils.extmath import randomized_svd
    U, S, V = randomized_svd(W, n_components=wordvec_size, n_iter=5,
                             random_state=None)
except ImportError:
    U, S, V = np.linalg.svd(W)

word_vecs = U[:, :wordvec_size]

querys = ['Weiblich', 'Ehe', 'er', 'Mote']
for query in querys:
    most_similar(query, word_to_id, id_to_word, word_vecs, top=5)

# =>Unten das Ausgabeergebnis
"""
[query]Weiblich
männlich: 0.6902421712875366
Etc.: 0.6339510679244995
Modell-: 0.5287646055221558
Generation: 0.5057054758071899
Schicht: 0.47833186388015747

[query]Ehe
Liebe: 0.5706729888916016
Dating: 0.5485040545463562
Gegner: 0.5481910705566406
 ?。: 0.5300850868225098
Zehn: 0.4711574614048004

[query]er
Freundin: 0.7679144740104675
Freund: 0.67448890209198
Mann: 0.6713247895240784
Elternteil: 0.6373711824417114
Ehemalige: 0.6159241199493408

[query]Mote
Ru: 0.6267833709716797
Erwägung: 0.5327887535095215
Twink: 0.5280393362045288
Mädchen: 0.5190156698226929
Fahrrad: 0.5139431953430176
"""
​

Recommended Posts

[Python] [Verarbeitung natürlicher Sprache] Ich habe Deep Learning ausprobiert (auf Japanisch von Grund auf neu erstellt)
Python: Tiefes Lernen in der Verarbeitung natürlicher Sprache: Grundlagen
Deep Learning 2 von Grund auf 1.3 Verarbeitung natürlicher Sprache 1.3 Zusammenfassung
Ich habe versucht, Dropout zu erklären
Python: Deep Learning in der Verarbeitung natürlicher Sprache: Implementierung eines Antwortsatzauswahlsystems
Deep Learning Memo von Grund auf neu gemacht
Ich habe versucht, Perceptron Teil 1 [Deep Learning von Grund auf neu] zu implementieren.
[Lernnotiz] Deep Learning von Grund auf neu gemacht [Kapitel 7]
Deep Learning / Deep Learning von Grund auf neu Kapitel 6 Memo
[Lernnotiz] Deep Learning von Grund auf neu gemacht [Kapitel 5]
[Deep Learning von Grund auf neu] Ich habe versucht, die Gradientenbestätigung auf leicht verständliche Weise zu erklären.
[Lernnotiz] Deep Learning von Grund auf neu gemacht [Kapitel 6]
"Deep Learning von Grund auf neu" mit Haskell (unvollendet)
Deep Learning / Deep Learning von Grund auf neu Kapitel 7 Memo
Ich habe versucht, natürliche Sprache mit Transformatoren zu verarbeiten.
[Lernnotiz] Deep Learning von Grund auf neu gemacht [~ Kapitel 4]
[Deep Learning von Grund auf neu] Ich habe versucht, Sigmoid Layer und Relu Layer zu implementieren
[Python] Ich habe mit der Verarbeitung natürlicher Sprache ~ Transformatoren ~ gespielt
Python vs Ruby "Deep Learning von Grund auf neu" Zusammenfassung
Python: Verarbeitung natürlicher Sprache
Deep Learning von Grund auf neu
Ich habe versucht, tief zu lernen
[Deep Learning von Grund auf neu] Beschleunigen des neuronalen Netzwerks Ich erklärte die Verarbeitung der Rückausbreitung
[Für Anfänger] Was ist in Deep Learning von Grund auf neu geschrieben?
[Deep Learning von Grund auf neu] Ich habe die Affine-Ebene implementiert
Anwendung von Deep Learning 2 von Grund auf neu Spam-Filter
Deep Learning von Grund auf 1-3 Kapitel
Ich habe Python auf Japanisch geschrieben
"Deep Learning from Grund" Memo zum Selbststudium (Nr. 16) Ich habe versucht, SimpleConvNet mit Keras zu erstellen
"Deep Learning from Grund" Memo zum Selbststudium (Nr. 17) Ich habe versucht, DeepConvNet mit Keras zu erstellen
Ich habe versucht, 100 Sprachverarbeitung klopfen 2020
Ich verstehe Python auf Japanisch!
Ein Amateur stolperte in Deep Learning von Grund auf neu Hinweis: Kapitel 1
Ein Amateur stolperte in Deep Learning von Grund auf neu Hinweis: Kapitel 3
Ein Amateur stolperte in Deep Learning von Grund auf neu. Hinweis: Kapitel 7
Ein Amateur stolperte in Deep Learning von Grund auf neu Hinweis: Kapitel 5
Ein Amateur stolperte in Deep Learning von Grund auf neu Hinweis: Kapitel 4
Ein Amateur stolperte in Deep Learning von Grund auf neu Hinweis: Kapitel 2
Ich habe versucht, in einem tief erlernten Sprachmodell zu schreiben
[Verarbeitung natürlicher Sprache] Ich habe diese Woche versucht, die aktuellen Themen in der Slack-Community zu visualisieren
Verwenden Sie die Swagger-Benutzeroberfläche. Wenn Sie einen Swagger-UI-ähnlichen Stil wünschen, kopieren Sie einfach die gesamte Datei unter / dist unter https://github.com/swagger-api/swagger-ui. Danach schreiben Sie einfach hier in index.html die URL der yml-Datei um. Wenn Sie der Meinung sind, dass Sie @ApiModel oder @ApiModelProperty nicht finden können, wurden übrigens anscheinend alle Anmerkungen zur Schemadefinition in @Schema integriert. Emotionsanalyse mit Java, Swagger, OpenAPI, Micronaut Natural Language Processing! Ich habe versucht, die Bewertung anhand des Überprüfungstextes vorherzusagen
"Deep Learning from Grund" Memo zum Selbststudium (Teil 8) Ich habe die Grafik in Kapitel 6 mit matplotlib gezeichnet
[Deep Learning von Grund auf neu] Implementieren Sie die Backpropagation-Verarbeitung in einem neuronalen Netzwerk mithilfe der Fehler-Back-Propagation-Methode
[Verarbeitung natürlicher Sprache] Ich habe versucht, die Bemerkungen jedes Mitglieds in der Slack-Community zu visualisieren
[Verarbeitung natürlicher Sprache] Vorverarbeitung mit Japanisch
Tiefes Lernen von Grund auf neu (Kostenberechnung)
Ich habe versucht, 100 Sprachverarbeitung klopfen 2020: Kapitel 3
Python-Anfänger versucht 100 Sprachverarbeitung klopfen 2015 (05 ~ 09)
Ich habe versucht, 100 Sprachverarbeitung klopfen 2020: Kapitel 1
Ich habe versucht, mit Theano tief zu lernen
Ich habe Line Benachrichtigung in Python versucht
Ich habe versucht, 100 Sprachverarbeitung zu klopfen 2020: Kapitel 2
Ich habe versucht, 100 Sprachverarbeitung zu klopfen 2020: Kapitel 4
Python-Anfänger versucht 100 Sprachverarbeitung klopfen 2015 (00 ~ 04)
Japanische Verarbeitung natürlicher Sprache mit Python3 (4) Emotionsanalyse durch logistische Regression
Dockerfile mit den notwendigen Bibliotheken für die Verarbeitung natürlicher Sprache mit Python
Warum ModuleNotFoundError: In "Deep Learning from Grund" wird kein Modul mit dem Namen "didaset.mnist" angezeigt.
Schreiben Sie Ihre Eindrücke von der Deep Learning 3 Framework Edition, die von Grund auf neu erstellt wurde
[Deep Learning von Grund auf neu] Informationen zu den Ebenen, die für die Implementierung der Backpropagation-Verarbeitung in einem neuronalen Netzwerk erforderlich sind
Kapitel 1 Einführung in Python Schneiden Sie nur die guten Punkte des Deeplearning aus, die von Grund auf neu erstellt wurden