[PYTHON] Ich brachte AI dazu, über die Texte von Genshi Yonezu nachzudenken (Implementierung)

Einführung

Genshi Yonezu verkauft jedes Mal, wenn er komponiert. Die Texte, die herausgesponnen werden, scheinen die Kraft zu haben, Menschen zu faszinieren. Dieses Mal beschloss ich, tiefes Lernen seinen Charme lernen zu lassen.


Dieser Artikel ist "** Implementierung **". Im vorherigen Artikel finden Sie den Code "Vorverarbeitung". Der allgemeine Ablauf der Implementierung ist wie folgt.

  1. Einstellung von Hyperparameter / Modell / Verlustfunktion / Optimierungsmethode
  2. Code lernen
  3. Testcode

Modell verwendet

Rahmen: Pytorch Modell: seq2seq mit Aufmerksamkeit Morphologisches Analysemodul: Jonome Umgebung: Google Colaboratory


Informationen zum Mechanismus von seq2seq und Attention finden Sie unter Vorheriger Artikel.

Das schematische Diagramm dieses Modells ist wie folgt. Referenzartikel

スクリーンショット 2020-05-10 19.40.37.png

Hier ist SOS "_".


Implementierung

Nach dem Hochladen des erforderlichen selbst erstellten Moduls in Google Colab Kopieren Sie die später beschriebene main.py und führen Sie sie aus.

** Erforderliches selbst erstelltes Modul **

スクリーンショット 2020-05-09 18.28.25.png

Den Code dieser selbst erstellten Module finden Sie unter github.


Problemeinstellung (letztes Mal neu gepostet)

Wie unten gezeigt, sagt Genji Yonezu die "nächste Passage" aus der "einen Passage" der bisher veröffentlichten Songs voraus.

|Eingabetext|Text ausgeben| |-------+-------| |Ich freue mich sehr, dich zu sehen| _Alle sind selbstverständlich traurig| |Alle sind selbstverständlich traurig| _Ich habe jetzt schmerzlich glückliche Erinnerungen| |Ich habe jetzt schmerzlich glückliche Erinnerungen| _Erhebe dich und gehe zum Abschied, der eines Tages kommen wird| |Erhebe dich und gehe zum Abschied, der eines Tages kommen wird| _Es reicht aus, jemanden einzunehmen und zu leben|

Dies wurde durch Scraping von Lyrics Net erstellt.


Einstellung von Hyperparameter / Modell / Verlustfunktion / Optimierungsmethode

Hier ist eine Ergänzung zum vorherigen Inhalt. Letztes Mal war mein Ziel, "Eingabetext" und "Ausgabetext" zu erstellen, die auf Japanisch waren, aber in Wirklichkeit werden sie mit "yonedu_dataset.prepare ()" identifiziert (quantifiziert), damit DL gelesen werden kann. Ich werde.


Der Parameter ** hyper ** wird von oben wie folgt angegeben.


Das ** Modell ** ist seq2seq, daher teilt es seine Rolle in einen Codierer und einen Decodierer auf.

encoder: embedding layer + hidden layer with LSTM decoder with attention: embedding layer + hidden layer with LSTM + attention system + softmax layer


Die ** Verlustfunktion ** verwendet die Kreuzentropiefehlerfunktion, und die ** Optimierungsmethode ** verwendet Adam sowohl für den Codierer als auch für den Decodierer.

Wenn ein Modellparameter vorhanden ist, wird dieser geladen.


from datasets import LyricDataset
import torch
import torch.optim as optim
from modules import *
from device import device
from utils import *
from dataloaders import SeqDataLoader
import math
import os
from utils

 ==========================================
# Datenaufbereitung
 ==========================================
# Pfad Genshi Yonezu_lyrics.txt
 file_path = "lyric / Genshi Yonezu_lyrics.txt"
 editierter_Dateipfad = "lyric / Genshi Yonezu_lyrics_edit.txt"

yonedu_dataset = LyricDataset(file_path, edited_file_path)
yonedu_dataset.prepare()
 check
print(yonedu_dataset[0])

# In Zug teilen und um 8: 2 testen
train_rate = 0.8
data_num = len(yonedu_dataset)
train_set = yonedu_dataset[:math.floor(data_num * train_rate)]
test_set = yonedu_dataset[math.floor(data_num * train_rate):]

# Soweit letztes Mal

 ================================================
# Hyperparametereinstellung / Modell / Verlustfunktion / Optimierungsmethode
 ================================================
# Hyperparameter
embedding_dim = 200
hidden_dim = 128
BATCH_NUM = 100
EPOCH_NUM = 100
 vocab_size = len (yonedu_dataset.word2id) #Anzahl des Wortschatzes
 padding_idx = yonedu_dataset.word2id [""] # Leere ID

# Modell-
encoder = Encoder(vocab_size, embedding_dim, hidden_dim, padding_idx).to(device)
attn_decoder = AttentionDecoder(vocab_size, embedding_dim, hidden_dim, BATCH_NUM, padding_idx).to(device)

# Verlustfunktion
criterion = nn.CrossEntropyLoss()

# Optimierungsmethode
encoder_optimizer = optim.Adam(encoder.parameters(), lr=0.001)
attn_decoder_optimizer = optim.Adam(attn_decoder.parameters(), lr=0.001)

# Laden Sie Parameter, wenn Sie ein trainiertes Modell haben
encoder_weights_path = "yonedsu_lyric_encoder.pth"
decoder_weights_path = "yonedsu_lyric_decoder.pth"
if os.path.exists(encoder_weights_path):
    encoder.load_state_dict(torch.load(encoder_weights_path))
if os.path.exists(decoder_weights_path):
    attn_decoder.load_state_dict(torch.load(decoder_weights_path))

Code lernen

Als nächstes kommt der Lerncode. Ich denke, dass seq2seq mit Aufmerksamkeit so aussehen wird, aber ich werde nur einen Punkt hinzufügen. Mit ** meinem eigenen Datenlader ** erhalte ich einen Mini-Batch für 100 Batch-Größen für jede Epoche, propagiere den Gesamtverlust in diesen Daten zurück, erhalte den Gradienten und aktualisiere die Parameter.

Informationen zum ** selbst erstellten Datenlader ** finden Sie in Yasuki Saitos Quellcode für Deep Learning 3 von Grund auf neu. Ich mache es.


 ================================================
# Lernen
 ================================================
all_losses = []
print("training ...")
for epoch in range(1, EPOCH_NUM+1):
    epoch_loss = 0
 # Teilen Sie die Daten in Mini-Batch
    dataloader = SeqDataLoader(train_set, batch_size=BATCH_NUM, shuffle=False)

    for train_x, train_y in dataloader:

 #Initialisierung des Gradienten
        encoder_optimizer.zero_grad()
        attn_decoder_optimizer.zero_grad()

 #Encoder Forward Propagation
        hs, h = encoder(train_x)

 # Achtung Decoder Eingang
        source = train_y[:, :-1]

 Richtige Antwortdaten von # Attention Decoder
        target = train_y[:, 1:]

        loss = 0
        decoder_output, _, attention_weight = attn_decoder(source, hs, h)
        for j in range(decoder_output.size()[1]):
            loss += criterion(decoder_output[:, j, :], target[:, j])

        epoch_loss += loss.item()

 # Fehler bei der Weitergabe
        loss.backward()

 # Parameteraktualisierung
        encoder_optimizer.step()
        attn_decoder_optimizer.step()

 # Verlust anzeigen
    print("Epoch %d: %.2f" % (epoch, epoch_loss))
    all_losses.append(epoch_loss)
    if epoch_loss < 0.1: break
print("Done")

import matplotlib.pyplot as plt
plt.plot(all_losses)
plt.savefig("attn_loss.png ")

# Modell speichern
torch.save(encoder.state_dict(), encoder_weights_path)
torch.save(attn_decoder.state_dict(), decoder_weights_path)

Testcode

Hier ist der Testcode. Ich erstelle die in ** [Ergebnisse] ** gezeigte Tabelle. Es gibt zwei Punkte zu beachten.


 =======================================
# Prüfung
 =======================================
# Word-> ID-Konvertierungswörterbuch
word2id = yonedu_dataset.word2id
# ID-> Wortkonvertierungswörterbuch
id2word = get_id2word(word2id)

# Anzahl der Elemente in einer richtigen Antwortdaten
output_len = len(yonedu_dataset[0][1])

# Bewertungsdaten
test_dataloader = SeqDataLoader(test_set, batch_size=BATCH_NUM, shuffle=False)

# Datenrahmen zur Anzeige des Ergebnisses
df = pd.DataFrame(None, columns=["input", "answer", "predict", "judge"])
# Drehen Sie den Datenlader, um den Datenrahmen zu füllen, in dem die Ergebnisse angezeigt werden
for test_x, test_y in test_dataloader:
    with torch.no_grad():
        hs, encoder_state = encoder(test_x)

 Zunächst wird "_", das den Beginn der Zeichenfolgengenerierung angibt, in # Decoder eingegeben
 # Erstellen Sie den Tensor "_" für die Stapelgröße
        start_char_batch = [[word2id["_"]] for _ in range(BATCH_NUM)]
        decoder_input_tensor = torch.tensor(start_char_batch, device=device)

        decoder_hidden = encoder_state
        batch_tmp = torch.zeros(100,1, dtype=torch.long, device=device)
        for _ in range(output_len - 1):
            decoder_output, decoder_hidden, _ = attn_decoder(decoder_input_tensor, hs, decoder_hidden)
 # Während das vorhergesagte Zeichen abgerufen wird, wird es so wie es ist die Eingabe des nächsten Decoders
            decoder_input_tensor = get_max_index(decoder_output.squeeze(), BATCH_NUM)
            batch_tmp = torch.cat([batch_tmp, decoder_input_tensor], dim=1)
 predicts = batch_tmp [:, 1:] # Empfangen Sie vorhergesagte Stapel
        if test_dataloader.reverse:
 test_x = [Liste (Zeile) [:: -1] für Zeile in test_x] # Die invertierte Zeile zurückgeben
        df = predict2df(test_x, test_y, predicts, df)
df.to_csv("predict_yonedsu_lyric.csv", index=False)

Ergebnis

Alle Fragen sind falsch. Dieses Mal war das Ziel jedoch "** Erfassung der Eigenschaften der Texte von Herrn Genji Yonezu **". Ein Teil der Tabelle ist ein Auszug.

** Eingabe **: Text eingeben ** Ausgabe **: Korrigieren Sie den Ausgabetext ** vorhersagen **: DL vorhergesagter Text ** Richter **: Stimmen Ausgabe und Vorhersage überein?

input | output | predict | judge ---------+----------------+----------------+------------ Es war mir egal, ob es ein Fehler oder eine richtige Antwort war|In dem blassen Dunst, der in einem Augenblick fiel|Ich bin traurig, weil ich geliebt werden möchte, also bist du vielleicht der einzige|X Ich hatte das Gefühl, dass sich seit diesem Tag alles geändert hatte|Lass dich nicht vom Wind umhauen, einer tiefen Frühlingsecke|Der warme Ort ist immer noch schön|X Lassen Sie uns eins nach dem anderen herausfinden|Wie ein Weckkind|Verwelktes Blau, sogar diese Farbe|X Egal was du heute machst|ich werde nach dir suchen|Ich suchte nach einer Stadt, die sich nicht ändern würde|X


Was ich fand

Da diesmal kein Überlernen festgestellt wurde, wird angenommen, dass die Ursache für den Mangel an Lernen hauptsächlich in der geringen Anzahl von Daten liegt. Nein, wir sind die einzigen, die entschieden haben, dass sie "nicht ausreichend lernen", und sie denken möglicherweise auf ihre eigene Weise ...

Recommended Posts

Ich brachte AI dazu, über die Texte von Genshi Yonezu nachzudenken (Implementierung)
Ich brachte AI dazu, über die Texte von Genshi Yonezu nachzudenken (Vorverarbeitung)
Die Python-Projektvorlage, an die ich denke.
Ich habe die Implementierung von range gelesen (Objects / rangeobject.c)
Ich habe versucht, die Texte von Hinatazaka 46 zu vektorisieren!
Ich verfolgte die Implementierung des Befehls du (erste Hälfte)
Denken Sie an das Rack und WSGI der nächsten Generation
Über das Testen bei der Implementierung von Modellen für maschinelles Lernen
Ich verfolgte die Implementierung des Befehls du (zweite Hälfte)
Ich habe mir den Inhalt von sklearn (scikit-learn) angesehen. (1) ~ Was ist mit der Implementierung von CountVectorizer? ~
Ein Memorandum über die Umsetzung von Empfehlungen in Python
Denken Sie an die Analyseumgebung (Teil 1: Übersicht) * Stand Januar 2017
Ich habe eine Funktion erstellt, um das Modell von DCGAN zu überprüfen
Ich habe ein Punktbild des Bildes von Irasutoya gemacht. (Teil 1)
Ich habe ein Punktbild des Bildes von Irasutoya gemacht. (Teil 2)
Über die Komponenten von Luigi
Über die Funktionen von Python
Ich habe versucht, Othello AI mit Tensorflow zu erstellen, ohne die Theorie des maschinellen Lernens zu verstehen ~ Implementierung ~
[Python] Ich habe die Theorie und Implementierung der logistischen Regression gründlich erklärt
Ich habe einen schlaffen Bot gemacht, der mich über die Temperatur informiert
Ich habe versucht, die häufig verwendete Implementierungsmethode von pytest-mock zusammenzufassen
[Kaggle] Ich habe mit dem Titanic-Tutorial eine Sammlung von Problemen erstellt
Denken Sie an das Problem der minimalen Änderung
Ich habe den Mechanismus der Flaschenanmeldung untersucht!
Über den Rückgabewert von pthread_mutex_init ()
Über den Rückgabewert des Histogramms.
Über den Grundtyp von Go
Über die Obergrenze von Threads-max
Über das Verhalten von Yield_per von SqlAlchemy
Über die Größe der Punkte in Matplotlib
Informationen zur Grundlagenliste der Python-Grundlagen
Denken Sie grob über die Verlustfunktion nach
Ich habe einen Kalender erstellt, der den Verteilungsplan von Vtuber automatisch aktualisiert
Ich wollte vorsichtig mit dem Verhalten der Standardargumente von Python sein
Ich möchte meine Gefühle mit den Texten von Mr. Children ausdrücken
Ich habe versucht, die logische Denkweise über Objektorientierung zusammenzufassen.
Ich habe GAN mit Keras gemacht, also habe ich ein Video des Lernprozesses gemacht.
Ich habe ein Programm erstellt, um die Größe einer Datei mit Python zu überprüfen
Ich habe einen Fehler beim Abrufen der Hierarchie mit MultiIndex von Pandas gemacht
Ich denke, die Grenze des Rucksacks ist nicht das Gewicht, sondern das Volumen w_11 / 22update
Ich habe eine Funktion erstellt, um die Bewegung eines zweidimensionalen Arrays (Python) zu sehen.