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 befasst sich mit "Datenvorverarbeitung". Hier sind die allgemeinen Schritte:
Im Allgemeinen bezieht sich "Vorverarbeitung" auf Datenverarbeitung zur Verbesserung der Genauigkeit, wie z. B. Normalisierung, aber diese "Vorverarbeitung" bedeutet Formung, so dass sie eine Eingabe oder Ausgabe von tiefem Lernen wird. ..
Rahmen: Pytorch Modell: seq2seq mit Aufmerksamkeit
Dies ist eine der Methoden für die "maschinelle Übersetzung". Das Folgende ist ein Bild von seq2seq.
Zitierter Artikel: [Encoder-Decoder-Modell und Teacher Forcing, Scheduled Sampling, Professor Forcing](https://satopirka.com/2018/02/encoder-decoder%E3%83%A2%E3%83%87%E3%83] % AB% E3% 81% A8Lehrer-forcieren geplant-Sampling-Professor-Forcen /)
Dies ermöglicht es dem Decoder, Sätze basierend auf den auf der Encoderseite codierten Informationen zu generieren, aber es gibt tatsächlich einige Probleme. Das heißt, der Decodereingang kann nur durch einen Vektor fester Länge dargestellt werden. Die Ausgabe von Encoder ist versteckte Ebene $ h $, aber diese Größe ist fest. Daher kann ein Datensatz mit einer zu langen Länge der Eingabeserie die Informationen nicht ordnungsgemäß in $ h $ komprimieren, und ein Datensatz mit einer zu kurzen Länge der Eingabeserie enthält verschwenderische Informationen in $ h $. Ich werde. Daher möchten Sie ** nicht nur den Status der letzten verborgenen Ebene des Encoders verwenden, sondern auch den Status der verborgenen Ebene in der Mitte **.
Dies ist der Hintergrund hinter dem Erfinder von Attention.
Aufmerksamkeit ist eine Methode, um beim Umgang mit Zeitreihendaten auf wichtige Punkte in der Vergangenheit (= Aufmerksamkeit) zu achten. Dieses Mal wird die "nächste Passage" für die "lyrische Passage" eines bestimmten Liedes vorhergesagt. Um die nächste Passage vorherzusagen, worauf sollten wir in der vorherigen Passage achten? Werden. Unten ist ein Bild von Attention.
source: Effective Approaches to Attention-based Neural Machine Translation
Dem Referenzpapier zufolge wird es genauer als Global Attention-Modell bezeichnet. Durch Sammeln aller verborgenen Zustände des Codierers als Vektor und Nehmen des inneren Produkts von ihnen und der Ausgabe des Decoders ** "Ähnlichkeit zwischen allen verborgenen Zuständen des Codierers und der Ausgabe des Decodierers" ** kann erhalten werden. Die Messung dieser Ähnlichkeit anhand des internen Produkts ist der Grund, warum es als Aufmerksamkeit bezeichnet wird, die sich "auf wichtige Faktoren konzentriert".
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 **
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.
Holen Sie sich die Texte, indem Sie mit dem folgenden Code kratzen Diese werden von Google Colab ausgeführt.
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.support.select import Select
import requests
from bs4 import BeautifulSoup
import re
import time
setting
# Chrome-Option zum Starten von Selen in jeder Umgebung
options = Options()
options.add_argument('--disable-gpu');
options.add_argument('--disable-extensions');
options.add_argument('--proxy-server="direct://"');
options.add_argument('--proxy-bypass-list=*');
options.add_argument('--start-maximized');
options.add_argument('--headless');
class DriverConrol():
def __init__(self, driver):
self.driver = driver
def get(self, url):
self.driver.get(url)
def get_text(self, selector):
element = self.driver.find_element_by_css_selector(selector)
return element.text
def get_text_by_attribute(self, selector, attribute='value'):
element = self.driver.find_element_by_css_selector(selector)
return element.get_attribute(attribute)
def input_text(self, selector, text):
element = self.driver.find_element_by_css_selector(selector)
element.clear()
element.send_keys(text)
def select_option(self, selector, text):
element = driver.find_element_by_css_selector(selector)
Select(element).select_by_visible_text(text)
def click(self, selector):
element = self.driver.find_element_by_css_selector(selector)
element.click()
def get_lyric(self, url):
self.get(url)
time.sleep(2)
element = self.driver.find_element_by_css_selector('#kashi_area')
lyric = element.text
return lyric
def get_url(self):
return self.driver.current_url
def quit(self):
self.driver.quit()
BASE_URL = 'https://www.uta-net.com/'
search_word = 'Genshi Yonezu'
search_jenre = 'Name des Schriftstellers'
driver = webdriver.Chrome(chrome_options=options)
dc = DriverConrol(driver)
dc.get (BASE_URL) #access
# Suche
dc.input_text('#search_form > div:nth-child(1) > input.search_input', search_word)
dc.select_option('#search_form > div:nth-child(2) > select', search_jenre)
dc.click('#search_form > div:nth-child(1) > input.search_submit')
time.sleep(2)
# Holen Sie sich sofort eine URL mit Anfragen
response = requests.get(dc.get_url())
response.encoding = response.apparent_encoding # Anti-verstümmelte Zeichen
soup = BeautifulSoup(response.text, "html.parser")
side_td1s =oup.find_all (class _ = "side td1") # Ruft alle td-Elemente mit der Klassenseite td1 ab
lyric_urls = [side_td1.find ('a', href = re.compile ('song')). get ('href') für side_td1 in side_td1s] # side_td1s enthält, href enthält 'song ein Tag Holen Sie sich das href-Element von
music_names = [side_td1.find ('a', href = re.compile ('song')). text für side_td1 in side_td1s] # Alle Songtitel abrufen
# Holen Sie sich die Texte und fügen Sie sie zu lyric_lis hinzu
lyric_lis = list()
for lyric_url in lyric_urls:
lyric_lis.append(dc.get_lyric(BASE_URL + lyric_url))
with open(search_word + '_lyrics.txt', 'wt') as f_lyric, open(search_word + '_musics.txt', 'wt') as f_music:
for lyric, music in zip(lyric_lis, music_names):
f_lyric.write(lyric + '\n\n')
f_music.write(music + '\n')
** Auszug aus den erworbenen Texten **
Ich freue mich sehr, dich zu sehen
Alle sind selbstverständlich traurig
Ich habe jetzt schmerzlich glückliche Erinnerungen
Erhebe dich und gehe zum Abschied, der eines Tages kommen wird
Es reicht aus, jemanden einzunehmen und zu leben
Ich wünschte, ich könnte ein Stein sein
Wenn ja, gibt es kein Missverständnis oder Verwirrung
Auf diese Weise, ohne dich zu kennen
...
Gegenwärtig ist es weit von den in [Problemeinstellung] gezeigten Daten entfernt, daher wird "Daten formatieren" durchgeführt.
Das heißt, es macht das.
Formatieren Sie die Daten mit dem folgenden Code Der Code ist verwirrend, aber die Vorverarbeitung ist jetzt abgeschlossen.
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):]
from sklearn.model_selection import train_test_split
from janome.tokenizer import Tokenizer
import torch
from utils import *
class LyricDataset(torch.utils.data.Dataset):
def __init__(self, file_path, edited_file_path, transform=None):
self.file_path = file_path
self.edited_file_path = edited_file_path
self.tokenizer = Tokenizer(wakati=True)
self.input_lines = [] # NN Eingabearray (jedes Element ist Text)
self.output_lines = [] # NNs korrektes Datenarray (jedes Element ist Text)
self.word2id = {} # e.g.) {'word0': 0, 'word1': 1, ...}
self.input_data = [] # Eine Textpassage, in der jedes Wort ID ist
self.output_data = [] # Die nächste Passage, in der jedes Wort ID ist
self.word_num_max = None
self.transform = transform
self._no_brank()
def prepare(self):
# Gibt ein Array (Text) zurück, das die Eingabe von NN ist, und ein Array, das die richtigen Antwortdaten (Text) von NN enthält.
self.get_text_lines()
Weisen Sie jedem Zeichen, das in # date.txt angezeigt wird, eine ID zu
für Zeile in self.input_lines + self.output_lines: # Erste Passage und nachfolgende Passagen
self.get_word2id(line)
# Finden Sie die maximale Anzahl von Wörtern in einer Passage
self.get_word_num_max()
# Gibt das Eingabearray (ID) von NN und das Array der korrekten Antwortdaten (ID) von NN zurück
for input_line, output_line in zip(self.input_lines, self.output_lines):
self.input_data.append([self.word2id[word] for word in self.line2words(input_line)] \
+ [self.word2id[" "] for _ in range(self.word_num_max - len(self.line2words(input_line)))])
self.output_data.append([self.word2id[word] for word in self.line2words(output_line)] \
+ [self.word2id[" "] for _ in range(self.word_num_max - len(self.line2words(output_line)))])
def _no_brank(self):
# Nehmen Sie ein Leerzeichen zwischen den Zeilen
with open(self.file_path, "r") as fr, open(self.edited_file_path, "w") as fw:
for line in fr.readlines():
if isAlpha(line) or line == "\n":
weiter # Buchstaben und Leerzeichen überspringen
fw.write(line)
def get_text_lines(self, to_file=True):
"""
Nimmt den Pfad file_path der Lyrics-Datei ohne Leerzeilen und gibt ein Array zurück, das dem folgenden ähnlich ist
"""
# Yonezu Genshi_lyrics.txt wird zeilenweise gelesen, in "eine Textpassage" und "nächste Passage" unterteilt und durch Eingabe und Ausgabe getrennt.
with open(self.edited_file_path, "r") as f:
line_list = f.readlines () #Lyrics Passage ... line
line_num = len(line_list)
for i, line in enumerate(line_list):
if i == line_num - 1:
weiter # Am Ende gibt es keine "nächste Passage"
self.input_lines.append(line.replace("\n", ""))
self.output_lines.append("_" + line_list[i+1].replace("\n", ""))
if to_file:
with open(self.edited_file_path, "w") as f:
for input_line, output_line in zip(self.input_lines, self.output_lines):
f.write(input_line + " " + output_line + "\n")
def line2words(self, line: str) -> list:
word_list = [token for token in self.tokenizer.tokenize(line)]
return word_list
def get_word2id(self, line: str) -> dict:
word_list = self.line2words(line)
for word in word_list:
if not word in self.word2id.keys():
self.word2id[word] = len(self.word2id)
def get_word_num_max(self):
#Suchen Sie am längsten
word_num_list = []
for line in self.input_lines + self.output_lines:
word_num_list.append(len([self.word2id[word] for word in self.line2words(line)]))
self.word_num_max = max(word_num_list)
def __len__(self):
return len(self.input_data)
def __getitem__(self, idx):
out_data = self.input_data[idx]
out_label = self.output_data[idx]
if self.transform:
out_data = self.transform(out_data)
return out_data, out_label
Der Code scheint länger zu sein als ich erwartet hatte, daher werde ich ihn diesmal auf "Datenvorverarbeitung" beschränken.
Recommended Posts