[PYTHON] Satzerzeugung mit GRU (Keras)

Einführung

Beim letzten Mal habe ich einen Artikel mit dem Titel Ich habe versucht, automatisch einen Bericht mit der Markov-Kette zu erstellen erstellt. Zu diesem Zeitpunkt benutzte ich die Markov-Kette, sodass ich einen Satz erhielt, der den Fluss des Satzes ignorierte. Aus diesem Grund planen wir dieses Mal, mithilfe einer Technologie namens GRU Sätze zu erstellen, die sich des Kontexts bewusst sind.

Was ist GRU?

Ich denke, dass RNN und LSTM in Bezug auf die Satzgenerierung bekannt sind, aber ich habe mich dafür entschieden, weil es weniger Lernzeit erfordert als LSTM. Ich kenne die detaillierte Struktur nicht, daher werde ich sie nicht schreiben, aber praktisch kann ich sie mit fast demselben Code wie LSTM schreiben.

Implementierung

Lassen Sie es uns jetzt implementieren.

Laden Sie zunächst die zu verwendende Bibliothek.


import re
import MeCab
import numpy as np
from sklearn.model_selection import train_test_split
from gensim.models import word2vec

from keras.layers.core import Activation
from keras.layers.core import Dense, Dropout
from keras.layers.core import Masking
from keras.models import Sequential
from keras.layers.recurrent import GRU
from keras.layers.embeddings import Embedding
from keras.layers.normalization import BatchNormalization
from keras.utils import np_utils
from keras.optimizers import RMSprop

Lesen / morphologische Analyse

Die diesmal verwendeten Daten stammen von Aozora Bunko. Dieses Mal habe ich "Phantom Twenty Faces" von Ranpo Edogawa verwendet.

Definieren Sie eine Funktion, die unnötige Daten aus diesen Daten entfernt und eine morphologische Analyse durchführt.


def convert(text, train):
    if train:
        #Löschen Sie unnötige Dinge wie Rubin
        text = re.split(r"\-{5,}", text)[2]
        text = re.split(r"Unteres Buch:", text)[0]
        text = re.sub(r"《.*?》", "", text)
        text = re.sub(r"[.*?]", "", text)
        text = re.sub(r"[|]", "", text)
        text = re.sub("(\n){2,}", "\n", text)
        text = re.sub(r"\u3000", "", text)

    #Morphologische Analyse
    mecab = MeCab.Tagger("-Owakati")
    return mecab.parse(text).split()

Hier möchte ich es für die Vorverarbeitung von Vorhersagedaten verwenden, daher habe ich ein Argument des Bool-Werts namens Zug und gelöschter Rubin usw. nur zum Zeitpunkt des Trainings vorbereitet. Führen wir nun diese Funktion aus.


path = "text_raw/kaijin_nijumenso.txt"
with open(path, "r") as f:
    text = f.read()
text_split = convert(text, True)

Wenn so gelesen, ist text = Phantom Twenty Faces \ n Edogawa Ranpo \ n \ n ----------- Es wird wie gelesen. Und es ist aufgeteilt wie "text_split = [" hashi "," is "," ki "," that "," koro ",", ",,,".

Erstellen eines Datensatzes

Konvertieren Sie zunächst die morphologisch analysierten Wörter in Zahlen. Dies ist nur eine Zahl, also gehen Sie wie folgt vor: Hier wird 0 zum Maskieren verwendet (die überschüssigen Daten werden als 0 behandelt), daher ist es notwendig, "+ 1" zu setzen.


#Erstellen eines Wörterbuchs mit Wörtern und Zahlen
vocab_r = dict((key + 1, word) for (key, word) in enumerate(set(text_split)))
vocab = dict((word, key) for (key, word) in vocab_r.items())

text_num = list(map(lambda x:vocab[x], text_split))

Erstellen Sie als Nächstes einen Datensatz für das Training. Wie später beschrieben wird, setzen Sie die Dimension auf "(n_sample, n_seq) = (Anzahl der Eingabedaten, wie viele zu lernende Wörter)", da die Eingabedaten Wörter in der Einbettungsschicht vektorisieren. Da das richtige Antwortetikett später in One-Hot konvertiert wird, sollte dies auch in der Dimension "(n_sample) = (Anzahl der Eingabedaten)" liegen.


n_seq = 10 #Wie viele Wörter zu lernen
num_char = len(set(text_split)) + 1 #Worttyp (einschließlich Maskierung)
n_sample = len(text_num) - n_seq #Anzahl der Eingabedaten

#Daten erstellen
input_data = np.zeros((n_sample, n_seq))
correct_data = np.zeros((n_sample))

for i in range(n_sample):
    input_data[i] = text_num[i:i + n_seq]
    correct_data[i] = text_num[i + n_seq]

x_train, x_test, y_train, y_test = train_test_split(input_data, correct_data, test_size=0.1, shuffle=True)

Verteilter Ausdruck von Wörtern

Für die Eingabedaten werden Wörter in der Einbettungsebene vektorisiert. Wenn Sie sie jedoch nur einmal heiß machen, wird die Datengröße enorm, sodass wir eine verteilte Darstellung verwenden. Dies dient dazu, Wörter unter Berücksichtigung der Beziehung zwischen Wörtern zu vektorisieren, und auf diese Weise ist es möglich, Wörter in einer kleinen Anzahl von Dimensionen auszudrücken.


model_w2v = word2vec.Word2Vec([text_split], size=100, min_count=1, window=5, iter=10)
embedding_matrix = np.zeros((num_char, 100))
for w, vec in zip(model_w2v.wv.index2word, model_w2v.wv.vectors):
    embedding_matrix[vocab[w]] = vec

Verwenden Sie model_w2v.wv.index2word, model_w2v.wv.vectors

'Essstäbchen':[ 0.04145062, -0.01713059, -0.0444374 ,,,],
'Aber':[ 0.554178  , -0.19353375, -0.56997895,,,]

Es kann als vektorisiert werden. Kombinieren Sie dies mit dem zuvor erstellten Wort- und Zahlenwörterbuch

[[ 0.        ,  0.        ,  0.        , ...,  0.        ],
[ 0.00860965, -0.00045624, -0.00883528, ..., -0.00861127],
...
[ 0.00662873, -0.00499085, -0.01188819, ..., -0.01252057]]

Ich konnte einen solchen Gewichtsvektor erstellen.

Modell erstellen

Lass uns mit GRU lernen. Das Modell selbst kann die Parameter so lernen, wie sie sind, indem es einfach das LSTM in GRU ändert.


#Modell erstellen
model = Sequential()
model.add(Embedding(num_char, 100, weights=[embedding_matrix], trainable=False, input_length=n_seq))
model.add(BatchNormalization(axis=-1))
model.add(Masking(mask_value=0, input_shape=(n_seq, 100)))
model.add(GRU(128, input_shape=(n_seq, 100), kernel_initializer='random_uniform'))
model.add(Dropout(0.2))
model.add(Dense(num_char))
model.add(Activation('softmax'))

model.compile(loss='categorical_crossentropy', optimizer=RMSprop(lr=0.01), metrics=['categorical_accuracy'])
model.fit(x_train, np_utils.to_categorical(y_train, num_char), batch_size=128, validation_split=0.05, epochs=100,
          shuffle=True)

Ich bin mit den Parametern nicht vertraut, daher habe ich auf [diesen Artikel] verwiesen (https://www.atmarkit.co.jp/ait/articles/1807/05/news143.html).

Werfen wir einen Blick auf die Testdaten.


y_pred = model.predict(x_test)
print(list(map(lambda x:vocab_r[x], np.argmax(y_pred, axis=1))))

Die Ausgabe sieht folgendermaßen aus:

Hahaha ……. ", Lob ständig"Zu"
Ich habe nachgeschlagen. In der Tat die lange Hand"Ihr"
Du bist ein natürlicher Abenteurer und du bist in der Junior High School"、"

Es hat eine etwas subtile Atmosphäre.

Vorhersage durch Eingabezeichenfolge

Versuchen wir, welche Art von Sätzen unter der Eingabe der eingegebenen Zeichenfolge tatsächlich erstellt wird.

Zunächst wird das Wort morphologisch analysiert und geteilt. Ich werde es mit den Nachrichten versuchen, die zufällig im Trend auf Twitter waren.


input_text = "Anhäufung von verursachenden Substanzen der Demenz aufgrund von Parodontitis Kyushu University und andere angekündigt"
input_text_split = convert(input_text, False)

Konvertieren Sie Wörter in Zahlen. Zu diesem Zeitpunkt werden Wörter, die nicht in den Trainingsdaten enthalten sind, nicht im Wörterbuch registriert, und es tritt ein Fehler auf, sodass eine Ausnahmeverarbeitung ausgeführt wird, die 0 zurückgibt.


def word2vec_input(x):
    """
Zahlen in Wörter umwandeln
Gibt 0 für Zeichen zurück, die nicht im Wörterbuch enthalten sind
    """
    try:
        return vocab[x]
    except:
        return 0


vocab_r[0] = "<nodata>"

#Konvertieren Sie Wörter in Zahlen
input_text_num = list(map(lambda x:word2vec_input(x), input_text_split))

Stellen Sie bei Vorhersagen sicher, dass die Eingabedaten "(Anzahl der Eingabedaten, Anzahl der zu lernenden Wörter) = (1, n_seq)" sind.


#Füllen Sie mit 0, wenn die Anzahl der Wörter kurz ist
if len(input_text_num) < n_seq:
    input_text_num = [0]*(n_seq - len(input_text_num)) + input_text_num

#Vorhersagefunktion
def prediction(input_text_num):
    input_test = np.zeros((1, n_seq))
    input_test[0] = input_text_num[-n_seq:]
    y_pred = model.predict(input_test)
    return np.append(input_text_num, np.where(y_pred == np.sort(y_pred)[:, -1].reshape(-1, 1))[1])  # np.argmax(y_pred))
    #Ich habe das geschrieben, weil ich mit dem Schreiben von Sätzen mit der zweithöchsten Wahrscheinlichkeit gespielt habe, aber Argmax ist genug

#Führen Sie Vorhersagen aus
for i in range(1000):
    input_text_num = prediction(input_text_num)

Nach dem Lernen werden die Zahlen wieder in Wörter umgewandelt, um Sätze zu bilden.


test_pred = list(map(lambda x:vocab_r[x], input_text_num[len(input_text_split):])) #Schneiden Sie die Anzahl der zu lernenden Wörter aus
pred_text = input_text + "".join(test_pred) #Verwenden Sie den Eingang so wie er ist
print(pred_text)

Die erstellte Zeichenfolge sieht folgendermaßen aus.

Anhäufung von Erregern von Demenz aufgrund von Parodontitis Die Kyushu University und andere haben angekündigt. „Du, du, wie, du, was für ein Ding, ich habe hineingeschaut." Ja, du, wie du so etwas betrachtest ", siehst du. Zusätzlich zu den Untergebenen der Zwanzig Gesichter sagte einer von ihnen: "Ich bin begeistert, das ist es." Hahaha ... "Akechi sagte:" Ja, was, "Abend ..." "..." "Oh, was ist mit Kobayashi? Ich schaute in dich hinein und sah den Nigiri." Oh, wie bist du gekommen? Es hat sich in der Kunst des Tages und so niedergelassen Die Niedlichkeit war wie ein Dieb im Gesicht. "... in der heutigen Zeit war es das." Die Kunst sagte: "Dann das Regal. "Und der Dieb packte seinen Teint und Mr. Sotaro sagte

Mein Japanisch ist verrückt geworden ...

Speichern Sie danach das Modell nach Bedarf.


#Modell speichern
model.save('test.h5')
model.save_weights('param.hdf5')

#Lesen
from tensorflow.python.keras.models import load_model
model = load_model('model/test.h5')
model.load_weights('model/param.hdf5')

Schließlich

Wie Sie sehen können, ist die Genauigkeit sehr gering geworden. Wenn Sie Verbesserungsvorschläge haben, lassen Sie es mich bitte wissen.

Verweise

Recommended Posts

Satzerzeugung mit GRU (Keras)
Machen Sie einen idolartigen Tweet mit Keras LSTM (Satzgenerierung)
Ich habe versucht, Sätze mit GPT-2 zu generieren
Bilderkennung mit Keras
CIFAR-10-Tutorial mit Keras
07. Anweisungsgenerierung nach Vorlage
Multivariates LSTM mit Keras
Automatische Quizgenerierung mit COTOHA
Ich habe den Code für die japanische Satzgenerierung mit DeZero geschrieben
Künstliche Datengenerierung mit Numpy
Keras-Installation (von Anaconda verwendet)
Multiple Regressionsanalyse mit Keras
Dokumentenklassifizierung mit Satzstück
AutoEncodder-Notizen mit Keras
Word2vec mit Theano + Keras implementiert
Optimieren von Keras-Parametern mit Keras Tuner
Erstellen Sie einfach CNNs mit Keras
Bildunterschriftengenerierung mit Chainer
Effizientes GAN mit Keras implementiert
Bilderkennung mit Keras + OpenCV
[Lass uns mit Python spielen] Ziel ist die automatische Satzgenerierung ~ Abschluss der automatischen Satzgenerierung ~
MNIST (DCNN) mit Keras (TensorFlow-Backend)
Beschleunigen Sie die Abfragegenerierung mit SQLAlchemy ORM
Vorhersage der Titanic von Kaggle mit Keras (kaggle ⑦)
[TensorFlow] [Keras] Aufbau eines neuronalen Netzwerks mit Keras
Implementieren Sie Keras LSTM Feed Forward mit Numpy
Vergleichen Sie DCGAN und pix2pix mit Keras
Score-CAM-Implementierung mit Keras. Vergleich mit Grad-CAM
Vorhersage der Sinuswelle mit Keras
Satzvektorerstellung mit BERT (Keras BERT)
Anfänger RNN (LSTM) | Versuchen Sie es mit Keras
Passwort für Lehrbuch mit Python generieren
CSRF-Token-Generierung für Gegenmaßnahmen mit Python
Schreiben Sie Reversi AI mit Keras + DQN
[PyTorch] Japanische Satzgenerierung mit Transformer
Feature-Generierung mit Pandas gruppieren nach
Erzeugung von Verlaufsbildern mit Python [1] | np.linspace
4/22 Vorhersage der Sinuswelle mit Keras
[Lass uns mit Python spielen] Ziel ist die automatische Satzgenerierung ~ Morphologische Analyse durchführen ~