In den letzten Jahren gab es viele faszinierende Anwendungen des tiefen Lernens, von denen eine die automatische Satzgenerierung ist. Es ist aufregend, Sätze wie den des Autors aus dem Stil des Buches zu generieren oder die Texte zu lernen und neue Songs zu erstellen. Also wollte ich ein paar Sätze machen, aber da es so viele Bücher und Lieder gibt, habe ich mich gefragt, ob es irgendetwas gibt, aber ich dachte: "Lass mich Jojos Weltbild und Jojo World lernen. Wäre es nicht interessant, wenn wir es bauen könnten? " Nun, ich wusste, dass der Grund, warum ich beim Nachschlagen nicht viel getan habe, darin bestand, dass nicht genügend Trainingsdaten vorhanden waren und es nicht funktionierte, aber ich habe es in einem Test versucht, also werde ich es teilen.
** - Erinnerst du dich, wie viele Brote du jemals gegessen hast? ** **. ** - Aber ablehnen **
Sogar diejenigen, die sagen "Ich kenne Jojo nicht", haben die obigen Zeilen vielleicht einmal gehört. Jojo ist ein Jungen-Manga "Jojos bizarres Abenteuer", das seit 1986 von Professor Hirohiko Araki serialisiert wurde. Es handelt sich um eine Geschichte mit einer einzigartigen Weltanschauung zum Thema "Menschliche Hymne" (wiki). //ja.wikipedia.org/wiki/%E3%82%B8%E3%83%A7%E3%82%B8%E3%83%A7%E3%81%AE%E5%A5%87%E5% Von A6% 99% E3% 81% AA% E5% 86% 92% E9% 99% BA)). Aufgrund seiner einzigartigen Ausdrucksmethode halte ich es für einen Cartoon, in dem Linien und Soundeffekte (Zukuuun, Memeta usw.) im Internet am häufigsten zitiert werden.
LSTM Der diesmal verwendete Algorithmus ist LSTM (Long Short Term Memory). LSTM ist ein Typ von RNN (Recurrent Neural Network), einem neuronalen Netzwerk, das Zeitreiheninformationen verarbeiten kann. Durch die Einführung von drei Gattern, die als Eingangsgatter, Ausgangsgatter und Vergessengatter bezeichnet werden, waren Daten, die in der Vergangenheit nicht möglich waren Sie können sich lange Zeit merken und lange Zeitreiheninformationen wie Sätze verarbeiten. Um beispielsweise den Satz "Erinnerst du dich, wie viele Brote du gegessen hast?" Zu lernen, extrahiere das N-Zeichen und lerne das nächste Zeichen. Wenn N = 10 ist, ist "Sie haben bisher gegessen" das Trainingsmuster und das nächste "Pa" das Etikett. Verschieben Sie dann beispielsweise diesen Satz um 3 Zeichen, um neue Daten zu erstellen, und lernen Sie als "ist das Brot, das ich gegessen habe" → "Blatt". Wie Sie diesem Beispiel entnehmen können, wird eine große Anzahl von Sätzen als Trainingsdaten für die Satzgenerierung benötigt. Wenn ich diese Methode mit der Menge einer Sammlung von Zitaten verwenden würde, würde der Satz auf Japanisch gebrochen, also habe ich ihn Wort für Wort statt für Buchstaben gelernt. Mit anderen Worten: "Sie haben bis jetzt gegessen" → "Brot". Weitere Informationen zu LSTM finden Sie in diesem Artikel. LSTM wird in Frameworks wie Keras bereitgestellt, sodass Sie es problemlos erstellen können, ohne es selbst zu implementieren.
Lassen Sie es uns implementieren. Dieser Code basiert hauptsächlich auf lstm_text_generation.py, das vom Keras-Team veröffentlicht wurde. Die Ausführungsumgebung ist Google Colanoratory.
Importieren Sie zunächst die erforderlichen Bibliotheken.
Bibliotheksimport
import os
import re
import bs4
import requests
from __future__ import print_function
from keras.callbacks import LambdaCallback
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import LSTM
from keras.optimizers import Adam
from keras.utils.data_utils import get_file
import numpy as np
import random
import sys
import io
import matplotlib.pyplot as plt
!apt install aptitude
!aptitude install mecab libmecab-dev mecab-ipadic-utf8 git make curl xz-utils file -y
!pip install mecab-python3==0.7
import MeCab
Dieses Mal erhalten wir die Daten von der Website und analysieren die Morphologie. Daher haben wir die erforderlichen Elemente zusätzlich zur üblichen Bibliothek für maschinelles Lernen installiert. Die letzten vier Zeilen sind das morphologische Analysetool von OSS namens Mecab, das Sätze in Wörter zerlegt.
Dann erhalten Sie das Angebot durch Schaben. Dieses Mal habe ich es von dieser Website erhalten.
Angebote erhalten
'''Holen Sie sich Jojo Zitate'''
with open('jojo.txt', 'a') as f:
url = 'http://kajipon.sakura.ne.jp/art/jojo9.htm'
res = requests.get(url)
res.raise_for_status()
'''Analysieren Sie das erworbene HTML und erfassen Sie nur die Dialogzeile'''
soup = bs4.BeautifulSoup(res.content, 'html.parser')
soup = soup.find_all( text=re.compile("「.+?」+(.+?)+Nein.") )
for s in soup:
txt = s.__str__()
'''Entfernen Sie zusätzliche Teile'''
txt = re.sub('Nein..+?rollen', '', txt)
txt = re.sub('(.+?)', '', txt)
txt = re.sub('※.+', '', txt)
txt = txt.replace('「', '')
txt = txt.replace('」', '')
print(txt)
f.write(txt)
Das Ausführungsergebnis sieht so aus (nur die ersten 20 Zeilen).
Nein! Was machst du! Yuru-san!
Wie erwartet, Dio! Tu was wir nicht können! Es fühlt sich dort taub an! Ich sehne mich danach!
Dioooooooo! Sie sind! Bis du weinst! Ich werde nicht aufhören dich zu schlagen!
Dio! Wenn Ihr dummer Kuss darauf abzielte, wäre es effektiver gewesen als erwartet!
Das Motiv für den Kampf ist anders als bei euch!
Lass es nicht los! Reicher Ama-Chan!
Ich werde Menschen verlassen! Jojo! !!
Nein! Der Geist dieses Vaters ist ... sein Sohn Jonathan Joe Star hat ihn geerbt! Es wird sein starker Wille, Stolz und Zukunft sein! !!
Verdammt! Lassen Sie uns in das Verbrechen der Invasion verwickelt werden, und ich werde diesen Raum betreten und ihn in vollen Zügen feiern! !!
Der Schnellwagen fährt kühl
Ach je! Was! Ich mit einem gebrochenen Arm! Ich unterstütze dich immer
Ist es Schicksal ... Es kann sein, dass die Begegnung von Menschen vom Schicksal bestimmt wird ...
Uhohohohohoho!
Entfernen Sie die Gelenke und strecken Sie Ihre Arme! Der starke Schmerz wird durch Wellenenergie gemildert!
Papau! Pow Pow! Wellenschneider! !!
Erinnerst du dich, wie viele Brote du jemals gegessen hast?
"Wellen"? Was ist "Atemmethode"? Wenn du hoo hoo bläst ... Es passt zu mir, sogar Fanfare für mich zu blasen!
Überraschend! Das sind Haare!
Denken Sie anders herum. Ich denke, es ist okay, es zu geben
Herz schütteln! Hitze bis zum Ausbrennen! !! Oh oh, ich werde den Blutschlag hacken! Berggebrannter Wellen-Sprint! !!
Lesen Sie die oben erstellte Datei jojo.txt und erstellen Sie Trainingsdaten. Außerdem sind Zitate im Gegensatz zu Sätzen und Texten grundsätzlich unabhängig, sodass es keine Zeitreihen gibt. Erstellen Sie daher zeilenweise Trainingsdaten, damit das Ende des vorherigen Zitats → der Stamm des nächsten Zitats nicht verbunden sind. Lassen Sie uns zunächst sehen, wie viele Zitate es gibt.
Zeile für Zeile lesen
'''Datei lesen'''
path = './jojo.txt'
'''Holen Sie sich Zeilen Zeile für Zeile'''
nline = 0
with io.open(path, encoding='utf-8') as f:
lines = f.readlines()
for line in lines:
nline += 1
print('Anzahl der Zeilen:', nline)
Ergebnis
Anzahl der Zeilen: 283
Insgesamt gab es 283 Zitate. Als nächstes zerlegen wir alle Anführungszeichen in Teile und füllen die Elemente in den Container aller Wörter, die erscheinen (Korpus), den Container aller Sätze, die die Trainingsdaten (Sätze) sein werden, und den Container des Etiketts für Sätze (next_chars). .. Die Länge der Trainingsdaten beträgt 3 Wörter, und das Verschiebungsintervall beträgt 1 Wort, um die nächsten Daten zu erstellen. "Sie sind jetzt" → "bis" "Bis jetzt" → "Essen" ・ ・ ・
python
'''Stellen Sie die Satzgröße und das Intervall ein, um zu lernen'''
corpus = []
sentences = []
next_chars = []
maxlen = 3
step = 1
mecab= MeCab.Tagger('-Ochasen')
mecab.parse('')
for line in lines:
'''Holen Sie sich Teiltexte für jede Zeile'''
corpusl = []
nodel = mecab.parseToNode(line)
while nodel:
corpusl.append(nodel.surface)
corpus.append(nodel.surface)
nodel = nodel.next
'''Generieren Sie Lernsätze und Lehreretiketten'''
for i in range(0, len(corpusl) - maxlen, step):
sentences.append(corpusl[i: i + maxlen])
next_chars.append(corpusl[i + maxlen])
print('Anzahl der Sätze', len(sentences))
print('Anzahl der Wörter: ', len(corpus))
'''Generieren Sie einen Korpus, bei dem doppelte Wörter entfernt wurden'''
chars = set(corpus)
print('Korpusgröße: ', len(chars))
Ergebnis
Anzahl der Sätze 8136
Anzahl der Wörter: 8984
Korpusgröße: 1883
Informationen zur Verwendung von Mecab finden Sie in diesem Artikel. corpusl ist ein temporärer Korpus, der die Wörter in dieser Zeile speichert. Die Gesamtzahl der Wörter, die dieses Mal herauskamen, ist 1883, und die erzeugten Sätze werden aus diesen Wörtern gebildet. Da der Computer Wörter nicht so verarbeiten kann, wie sie sind, erstellen Sie Wörterbücher, die Wörtern → Index bzw. Index → Wort entsprechen. Erstellen Sie abschließend die Trainingsdaten x und die Lehrerbezeichnung y als One-Hot-Vektor.
python
'''Erstellen Sie Wörterbücher, die Wörtern → Zahlen und Zahlen → Wörtern entsprechen'''
char_indices = dict((c, i) for i, c in enumerate(chars))
indices_char = dict((i, c) for i, c in enumerate(chars))
'''Vektorisierung'''
x = np.zeros((len(sentences), maxlen, len(chars)), dtype=np.bool)
y = np.zeros((len(sentences), len(chars)), dtype=np.bool)
for i, sentence in enumerate(sentences):
for t, char in enumerate(sentence):
x[i, t, char_indices[char]] = 1
y[i, char_indices[next_chars[i]]] = 1
Erstellen Sie ein LSTM-Modell. Die Anzahl der Hidden-Layer-Einheiten beträgt 128, die Kostenfunktion ist die kategoriale Kreuzentropie und die Optimierungsmethode ist Adam.
LSTM
'''LSTM-Modellerstellung'''
model = Sequential()
model.add(LSTM(128, input_shape = (maxlen, len(chars))))
model.add(Dense(len(chars), activation='softmax'))
optimizer = Adam()
model.compile(loss='categorical_crossentropy', optimizer=optimizer)
model.summary()
Ergebnis
Model: "sequential_1"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
lstm_1 (LSTM) (None, 128) 1030144
_________________________________________________________________
dense_1 (Dense) (None, 1883) 242907
=================================================================
Total params: 1,273,051
Trainable params: 1,273,051
Non-trainable params: 0
_________________________________________________________________
Jetzt, da wir bereit sind, werden wir lernen.
Lernen
def sample(preds, temperature=1.0):
# helper function to sample an index from a probability array
preds = np.asarray(preds).astype('float64')
preds = np.log(preds) / temperature
exp_preds = np.exp(preds)
preds = exp_preds / np.sum(exp_preds)
probas = np.random.multinomial(1, preds, 1)
return np.argmax(probas)
'''Eine Funktion, die die für jede Epoche generierten Linien anzeigt'''
def on_epoch_end(epoch, _):
print()
print('----- %d epoch:' % epoch)
start_index = random.randint(0, len(corpus) - maxlen -1)
for diversity in [8.0, 16.0, 32.0, 64.0, 128.0, 256, 512, 1024]:
print('----- diversity:', diversity)
generated = ''
sentence = corpus[start_index: start_index + maxlen]
generated += ''.join(sentence)
print('-----Samen"' + ''.join(sentence) + '"Erstellt von:')
sys.stdout.write(generated)
for i in range(10):
x_pred = np.zeros((1, maxlen, len(chars)))
for t, char in enumerate(sentence):
x_pred[0, t, char_indices[char]] = 1.
preds = model.predict(x_pred, verbose = 0)[0]
next_index = sample(preds, diversity)
next_char = indices_char[next_index]
sentences.append(next_char)
sys.stdout.write(next_char)
sys.stdout.flush()
print()
sample ist eine Funktion, die die Wahrscheinlichkeitsverteilung abtastet, und es scheint, dass die Vorhersage von Wörtern umso niedriger ist, je höher die Temperatur ist. (https://www.freecodecamp.org/news/applied-introduction-to-lstms-for-text-generation-380158b29fb3/) Ursprünglich werden niedrige Werte wie 0,2 bis 1,2 verwendet, aber in diesen Daten werden wahrscheinlich nur dieselben Wörter ausgegeben, weil die Anzahl zu klein ist (wahrscheinlich werden "sichere" häufig vorkommende Wörter sorgfältig ausgegeben. ), Also versuche ich verschiedene Wörter mit einem großen Wert zu verwenden. Wählen Sie zufällig 3 Wörter für jede Epoche aus, sagen Sie die nächsten 10 Wörter voraus und zeigen Sie den Satz an.
Übergeben Sie die obige Funktion passend.
python
print_callback = LambdaCallback(on_epoch_end = on_epoch_end)
history = model.fit(x, y, batch_size=128, epochs=60, callbacks=[print_callback])
Das Ausführungsergebnis ist wie folgt. (Auszug)
Ausführungsergebnis nach 5 Epochen
~~~
Epoch 5/60
8136/8136 [==============================] - 1s 98us/step - loss: 5.5118
-----Dialog generiert nach 4 Epochen:
----- diversity: 8.0
-----Samen"Gah!"Erstellt von:
Gah! Es ist erfrischend, alle brennen aus, aber ich bin froh, dass Deutschland das hört
----- diversity: 16.0
-----Samen"Gah!"Erstellt von:
Gah! Es fühlt sich an, als würde ich dich anrufen
----- diversity: 32.0
-----Samen"Gah!"Erstellt von:
Gah! Es ist möglich, nach einem Affen zu suchen, aber er scheint
----- diversity: 64.0
-----Samen"Gah!"Erstellt von:
Gah! Kurz bevor du es weißt, vergib mir die nervige Prog Band
----- diversity: 128.0
-----Samen"Gah!"Erstellt von:
Gah! Schwer zu kommen. Es tut mir leid, es zu begraben. Eh
----- diversity: 256
-----Samen"Gah!"Erstellt von:
Gah! Suma Miro Fuji Sankai Venezia Jornot Weltkatastrophe
----- diversity: 512
-----Samen"Gah!"Erstellt von:
Gah! Respektiere den ersten elenden Mut, den W Isagi oft so nennt
----- diversity: 1024
-----Samen"Gah!"Erstellt von:
Gah! Combat F Shark Slapstick, vielleicht die richtige Liebeswette
~~~
Es ist ein Jojo-ähnliches Wort, aber es ist inkohärent und so ähnlich ...
Ausführungsergebnis nach 33 Epochen
~~~
Epoch 33/60
8136/8136 [==============================] - 1s 98us/step - loss: 2.3640
-----Dialog nach 32 Epochen generiert:
----- diversity: 8.0
-----Samen"Großvater Joseph"Erstellt von:
Die Joseph-Geschichte meines Großvaters, ich bin nicht zum ersten Mal in einen Stern verliebt
----- diversity: 16.0
-----Samen"Großvater Joseph"Erstellt von:
Das Gehirn meines Großvaters Joseph hat das Leben eines niedlichen Gottes auf dem Land.
----- diversity: 32.0
-----Samen"Großvater Joseph"Erstellt von:
Großvater Joseph, Krieger aaaaaaa--.. von!
----- diversity: 64.0
-----Samen"Großvater Joseph"Erstellt von:
Sie wurden von Ihrem Großvater Joseph erschossen und haben Rakai Handsome Ooohehehehe verlassen
----- diversity: 128.0
-----Samen"Großvater Joseph"Erstellt von:
Mein Großvater Joseph erinnert sich an das Leben, das Kuranenza geformt hat
----- diversity: 256
-----Samen"Großvater Joseph"Erstellt von:
Großvater Joseph Pig Joseph wird hier beschützt Jojooooooo Desert Suka
----- diversity: 512
-----Samen"Großvater Joseph"Erstellt von:
Großvater Joseph Mach es mit einem echten Gesicht Sui Eee Eee Eee Ein Apothekengeheimnis, das im Weg steht
----- diversity: 1024
-----Samen"Großvater Joseph"Erstellt von:
Mein Großvater Joseph Teme gewinnt und erschüttert die Wüste
~~~
Ich habe nicht das Gefühl, ein bisschen Japaner geworden zu sein. Trotzdem gibt es einige erschreckende Worte wie "Grandfather Joseph Brains Country".
60epoch Ausführungsergebnis
~~~
Epoch 60/60
8136/8136 [==============================] - 1s 104us/step - loss: 0.7271
-----Dialog nach 59 Epoche erzeugt:
----- diversity: 8.0
-----Samen"Problem bis kurz zuvor"Erstellt von:
Bis kurz vor dem Problem o Scary Menge erhielt Cherry Shooting über irrelevante Verletzungen
----- diversity: 16.0
-----Samen"Problem bis kurz zuvor"Erstellt von:
Bis kurz vor dem Problem Jojo, stärken Sie immer mysteriöse König Zentimeter Schönheitsbeziehung Asahi
----- diversity: 32.0
-----Samen"Problem bis kurz zuvor"Erstellt von:
Bis kurz vor dem Problem sind die Eingeweide der Passagiere überzeugt. Große Räder Nützliche alte Tochter, um auf Ihrer Seite zu stehen
----- diversity: 64.0
-----Samen"Problem bis kurz zuvor"Erstellt von:
Es scheint bis kurz zuvor ein Problem zu sein, und es ist unwissend und grausam
----- diversity: 128.0
-----Samen"Problem bis kurz zuvor"Erstellt von:
Bis kurz vor dem Problem ist es mir egal, bis ich meine Gefühle wegnehme
----- diversity: 256
-----Samen"Problem bis kurz zuvor"Erstellt von:
Bis kurz vor dem Problem Mutter Cola 216 Was ist die Gedged Person Papau Stammbaum Ehre aufgereiht
----- diversity: 512
-----Samen"Problem bis kurz zuvor"Erstellt von:
Treffen Sie eine Problemnadelentscheidung, bis Star Valkyrie danach sucht
----- diversity: 1024
-----Samen"Problem bis kurz zuvor"Erstellt von:
Bis kurz vor dem Problem Glückskind versteht den alten Mann und bekommt einen Befehl
Es ist eine Zeichenkette, die in Ihrem Gehirn herauszukommen scheint, wenn Sie aufgrund einer Erkältung Schwierigkeiten haben, einzuschlafen. Ich lief 60epoch, aber ich konnte keinen Satz machen, der auf Japanisch nicht seltsam war. Ich denke, es ist angemessen, wenn man die Anzahl der Wörter und die Anzahl der Daten berücksichtigt. Aber gibt es so etwas wie "Papau Pedigree" oder "Star Valkyrie"? Für Jojo-Fans war es sehr interessant, Worte zu sehen, die mich zum Nachdenken brachten. Ich denke, es gibt viele Punkte, die verbessert werden müssen, aber ich denke, es wird schwierig sein, sich zu verbessern, also werde ich diesmal hier aufhören. Es war vernünftig für einen Prozess. Immerhin ist die Satzerzeugung interessant. Ich habe den Code in GitHub eingefügt. Wenn Sie also interessiert sind, spielen Sie bitte damit. Zeichnen Sie abschließend die Kostenfunktion.
Kostenfunktionsdiagramm
'''Verlustvisualisierung'''
plt.figure(figsize=(10,7))
loss = history.history['loss']
plt.plot(loss, color='b', linewidth=3)
plt.tick_params(labelsize=18)
plt.ylabel('loss', fontsize=20)
plt.xlabel('epoch', fontsize=20)
plt.legend(['training'], loc='best', fontsize=20)
plt.show()