Dans cet article, nous visons à créer un modèle qui génère automatiquement un roman en entrant un titre arbitraire à l'aide d'une paire de titre et de texte de roman.
Google Colaboratory est utilisé comme infrastructure d'analyse. Google Colaboratory est un environnement de bloc-notes cloud fourni par Google, et toute personne disposant d'un compte Google peut l'utiliser gratuitement. Non seulement la bibliothèque requise pour l'analyse des données est préparée à l'avance, mais elle peut également être utilisée avec le GPU, c'est pourquoi elle est fortement recommandée lorsque vous voulez vous sentir libre d'essayer quelque chose sur votre ordinateur portable. Pour plus de détails sur la configuration de Google Colaboratory, consultez cet article.
Après l'installation, ouvrez le notebook pour cette analyse et exécutez la commande suivante pour installer la bibliothèque qui n'est pas installée à l'avance.
!pip install PyDrive
!pip install janome
!pip install mojimoji
Les nouvelles données sont obtenues auprès de Github d'Aozora Bunko. Tout d'abord, copiez le référentiel cible sur votre propre Google Drive. Vous pouvez également exécuter les commandes suivantes à partir de Google Colaboratory.
!git clone --branch master --depth 1 https://github.com/aozorabunko/aozorabunko.git "drive/My Drive/Annuaire arbitraire"
Ensuite, extrayez les données utilisées pour la construction du modèle à partir des fichiers copiés et formatez-les. Cette fois, j'utiliserai un roman dont le texte comporte moins de 3 000 caractères. De plus, «id sur le lecteur» dans le code fait référence à la chaîne de caractères sous les dossiers / inclus dans l'URL du répertoire cible.
#----------------------
#Obtenir une liste de fichiers cibles
#----------------------
from pydrive.auth import GoogleAuth
from pydrive.drive import GoogleDrive
from google.colab import auth
from oauth2client.client import GoogleCredentials
import pandas as pd
#Autoriser l'accès à Google Drive
auth.authenticate_user()
gauth = GoogleAuth()
gauth.credentials = GoogleCredentials.get_application_default()
drive = GoogleDrive(gauth)
#Obtenez le titre de toutes les œuvres et identifiant sur Drive
def get_list_file_recursively(parent_id, l=None):
if l is None:
l = []
file_list = drive.ListFile({'q': '"{}" in parents and trashed = false'.format(parent_id)}).GetList()
l += [f for f in file_list if f['mimeType'] != 'application/vnd.google-apps.folder']
for f in file_list:
if f['mimeType'] == 'application/vnd.google-apps.folder':
get_list_file_recursively(f['id'], l)
return l
listed = []
for f in get_list_file_recursively('L'identifiant sur le lecteur du répertoire de niveau supérieur du référentiel copié'):
print(f['title'])
if 'html' in f['title'] and 'card' not in f['title']:
list = [f['title'], f['id']]
listed.append(list)
listed = pd.DataFrame(listed)
#----------------------
#Acquisition de titre / texte
#----------------------
from bs4 import BeautifulSoup
#Lire le fichier html de la liste
Stories = []
for i in range(0, len(listed)):
if i % 100 == 0:
print('{} / {}'.format(i, len(listed)))
#Identifier les fichiers à partir de l'identifiant de la liste
file_data = drive.CreateFile({'id': listed.iloc[i, 2]})
file_data.GetContentFile(listed.iloc[i, 1])
with open(listed.iloc[i, 1], 'rb') as html:
soup = BeautifulSoup(html, 'lxml')
#Obtenir le titre / texte
title = soup.find("h1", class_='title')
main_text = soup.find("div", class_='main_text')
#Si le titre ou le texte est manquant, ignorez-le
if title == None or main_text == None:
continue
#Retirer le rubis
for yomigana in main_text.find_all(["rp", "h4", "rt"]):
yomigana.decompose()
#Formater et convertir en chaîne
title = [line.strip() for line in
title.text.strip().splitlines()]
main_text = [line.strip() for line in
main_text.text.strip().splitlines()]
title = ''.join(title)
text=''.join(main_text)
#Le texte est 3,Limitez-vous aux œuvres dans les 000 caractères
if len(text) <= 3000:
Stories.append([title, text])
#Enregistrer sous csv
Stories = pd.DataFrame(Stories)
Stories.to_csv('drive/My Drive/Stories.csv', index=False, header=False)
Enfin, enregistrez une répartition aléatoire de 80% des données pour la formation et 20% pour les tests.
#----------------------
#Répartition des données
#----------------------
from sklearn.model_selection import KFold
kf = KFold(n_splits=5, shuffle=True, random_state=12345)
tr_idx, te_idx = list(kf.split(df))[0]
train = df.iloc[tr_idx, :]
test = df.iloc[te_idx, :]
train.to_csv('drive/My Drive/train.csv', index=False, header=False)
test.to_csv('drive/My Drive/test.csv', index=False, header=False)
Utilisez le texte de la torche pour lire les données. Pour une explication de base de torchtext, voir cet article.
Tout d'abord, définissez la fonction de prétraitement à appliquer lors de la lecture de données avec torchtext. Utilisez janome pour l'analyse morphologique.
#----------------------
#Définition du prétraitement
#----------------------
from torchtext import data
from janome.tokenizer import Tokenizer
import re
import mojimoji
#Définition du traitement des chaînes
def preprocessing(text):
#Supprimer les sauts de ligne, les espaces demi-largeur et les espaces pleine largeur
text = re.sub('\r', '', text)
text = re.sub('\n', '', text)
text = re.sub(' ', '', text)
text = re.sub(' ', '', text)
#"0" uniforme pour les caractères numériques
text = re.sub(r'[0-9 0-9]', '0', text)
#Angle complet
text = mojimoji.han_to_zen(text)
return text
#Définition de tokenizer
j_t = Tokenizer()
def tokenizer(text):
return [tok for tok in j_t.tokenize(text, wakati=True)]
#Traitement des chaînes+ Tokenizer
def tokenizer_with_preprocessing(text):
text = preprocessing(text)
text = tokenizer(text)
return text
Ensuite, définissez la méthode de lecture à l'aide de torchtext.
#----------------------
#Définition du champ
#----------------------
TEXT = data.Field(
sequential=True,
init_token='<sos>',
eos_token='<eos>',
tokenize=tokenizer_with_preprocessing,
lower=True,
use_vocab=True,
batch_first=True
)
Lisez le fichier csv divisé pour l'apprentissage et le test, et créez un dictionnaire de vocabulaire.
#----------------------
#Lire les données
#----------------------
train_ds, test_ds = data.TabularDataset.splits(
path='drive/My Drive',
train='train.csv',
test='test.csv',
format='csv',
skip_header=False,
fields=[('title', TEXT), ('text', TEXT)]
)
#Vérification
train_ds[0].__dict__.keys()
test_ds[0].__dict__.keys()
for i in range(0, 10):
print(vars(train_ds[i]))
print(vars(test_ds[i]))
#Créer un dictionnaire
TEXT.build_vocab(train_ds, test_ds, min_freq=2)
#Nombre de mots
print(TEXT.vocab.freqs)
print('Nombre de vocabulaire:{}'.format(len(TEXT.vocab)))
#Créer un itérateur
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
# -->Sélectionnez à l'avance le GPU dans "Modifier le type d'exécution".
train_iter = data.Iterator(train_ds, batch_size=16, shuffle=True, device=device)
test_iter = data.Iterator(test_ds, batch_size=16, shuffle=False, device=device)
#Vérification
batch = next(iter(train_iter))
print(batch.title)
print(batch.text)
batch = next(iter(test_iter))
print(batch.title)
print(batch.text)
Implémentez Transformer. Cet article n'explique pas comment fonctionne Transformer, mais en japonais c'est cet article et en anglais c'est [cet article](http: // jalammar). .github.io / illustré-transformer /) est très facile à comprendre. Aussi, pour l'implémentation, veuillez vous référer à ici. C'était. La signification de chaque processus est également expliquée en détail, veuillez donc la lire avant d'essayer.
Tout d'abord, définissez un encodeur qui vectorise le titre du roman.
import torch
from torch import nn
class Encoder(nn.Module):
def __init__(self,
input_dim,
hid_dim,
n_layers,
n_heads,
pf_dim,
dropout,
device,
max_length=100):
super().__init__()
self.device = device
self.tok_embedding = nn.Embedding(input_dim, hid_dim)
self.pos_embedding = nn.Embedding(max_length, hid_dim)
self.layers = nn.ModuleList([EncoderLayer(hid_dim,
n_heads,
pf_dim,
dropout,
device)
for _ in range(n_layers)])
self.dropout = nn.Dropout(dropout)
self.scale = torch.sqrt(torch.FloatTensor([hid_dim])).to(device)
def forward(self, src, src_mask):
#src = [batch size, src len]
#src_mask = [batch size, src len]
batch_size = src.shape[0]
src_len = src.shape[1]
pos = torch.arange(0, src_len).unsqueeze(0).repeat(batch_size, 1).to(self.device)
#pos = [batch size, src len]
src = self.dropout((self.tok_embedding(src) * self.scale) + self.pos_embedding(pos))
#src = [batch size, src len, hid dim]
for layer in self.layers:
src = layer(src, src_mask)
#src = [batch size, src len, hid dim]
return src
class EncoderLayer(nn.Module):
def __init__(self,
hid_dim,
n_heads,
pf_dim,
dropout,
device):
super().__init__()
self.layer_norm = nn.LayerNorm(hid_dim)
self.self_attention = MultiHeadAttentionLayer(hid_dim, n_heads, dropout, device)
self.positionwise_feedforward = PositionwiseFeedforwardLayer(hid_dim, pf_dim, dropout)
self.dropout = nn.Dropout(dropout)
def forward(self, src, src_mask):
#src = [batch size, src len, hid dim]
#src_mask = [batch size, src len]
#self attention
_src, _ = self.self_attention(src, src, src, src_mask)
#dropout, residual connection and layer norm
src = self.layer_norm(src + self.dropout(_src))
#src = [batch size, src len, hid dim]
#positionwise feedforward
_src = self.positionwise_feedforward(src)
#dropout, residual and layer norm
src = self.layer_norm(src + self.dropout(_src))
#src = [batch size, src len, hid dim]
return src
class MultiHeadAttentionLayer(nn.Module):
def __init__(self, hid_dim, n_heads, dropout, device):
super().__init__()
assert hid_dim % n_heads == 0
self.hid_dim = hid_dim
self.n_heads = n_heads
self.head_dim = hid_dim // n_heads
self.fc_q = nn.Linear(hid_dim, hid_dim)
self.fc_k = nn.Linear(hid_dim, hid_dim)
self.fc_v = nn.Linear(hid_dim, hid_dim)
self.fc_o = nn.Linear(hid_dim, hid_dim)
self.dropout = nn.Dropout(dropout)
self.scale = torch.sqrt(torch.FloatTensor([self.head_dim])).to(device)
def forward(self, query, key, value, mask = None):
batch_size = query.shape[0]
#query = [batch size, query len, hid dim]
#key = [batch size, key len, hid dim]
#value = [batch size, value len, hid dim]
Q = self.fc_q(query)
K = self.fc_k(key)
V = self.fc_v(value)
#Q = [batch size, query len, hid dim]
#K = [batch size, key len, hid dim]
#V = [batch size, value len, hid dim]
Q = Q.view(batch_size, -1, self.n_heads, self.head_dim).permute(0, 2, 1, 3)
K = K.view(batch_size, -1, self.n_heads, self.head_dim).permute(0, 2, 1, 3)
V = V.view(batch_size, -1, self.n_heads, self.head_dim).permute(0, 2, 1, 3)
#Q = [batch size, n heads, query len, head dim]
#K = [batch size, n heads, key len, head dim]
#V = [batch size, n heads, value len, head dim]
energy = torch.matmul(Q, K.permute(0, 1, 3, 2)) / self.scale
#energy = [batch size, n heads, seq len, seq len]
if mask is not None:
energy = energy.masked_fill(mask == 0, -1e10)
attention = torch.softmax(energy, dim = -1)
#attention = [batch size, n heads, query len, key len]
x = torch.matmul(self.dropout(attention), V)
#x = [batch size, n heads, seq len, head dim]
x = x.permute(0, 2, 1, 3).contiguous()
#x = [batch size, seq len, n heads, head dim]
x = x.view(batch_size, -1, self.hid_dim)
#x = [batch size, seq len, hid dim]
x = self.fc_o(x)
#x = [batch size, seq len, hid dim]
return x, attention
class PositionwiseFeedforwardLayer(nn.Module):
def __init__(self, hid_dim, pf_dim, dropout):
super().__init__()
self.fc_1 = nn.Linear(hid_dim, pf_dim)
self.fc_2 = nn.Linear(pf_dim, hid_dim)
self.dropout = nn.Dropout(dropout)
def forward(self, x):
#x = [batch size, seq len, hid dim]
x = self.dropout(torch.relu(self.fc_1(x)))
#x = [batch size, seq len, pf dim]
x = self.fc_2(x)
#x = [batch size, seq len, hid dim]
return x
Ensuite, définissez un décodeur qui reçoit le vecteur titre et génère le corps du roman.
class Decoder(nn.Module):
def __init__(self,
output_dim,
hid_dim,
n_layers,
n_heads,
pf_dim,
dropout,
device,
max_length=1000):
super().__init__()
self.device = device
self.tok_embedding = nn.Embedding(output_dim, hid_dim)
self.pos_embedding = nn.Embedding(max_length, hid_dim)
self.layers = nn.ModuleList([DecoderLayer(hid_dim,
n_heads,
pf_dim,
dropout,
device)
for _ in range(n_layers)])
self.fc_out = nn.Linear(hid_dim, output_dim)
self.dropout = nn.Dropout(dropout)
self.scale = torch.sqrt(torch.FloatTensor([hid_dim])).to(device)
def forward(self, trg, enc_src, trg_mask, src_mask):
#trg = [batch size, trg len]
#enc_src = [batch size, src len, hid dim]
#trg_mask = [batch size, trg len]
#src_mask = [batch size, src len]
batch_size = trg.shape[0]
trg_len = trg.shape[1]
pos = torch.arange(0, trg_len).unsqueeze(0).repeat(batch_size, 1).to(self.device)
#pos = [batch size, trg len]
trg = self.dropout((self.tok_embedding(trg) * self.scale) + self.pos_embedding(pos))
#trg = [batch size, trg len, hid dim]
for layer in self.layers:
trg, attention = layer(trg, enc_src, trg_mask, src_mask)
#trg = [batch size, trg len, hid dim]
#attention = [batch size, n heads, trg len, src len]
output = self.fc_out(trg)
#output = [batch size, trg len, output dim]
return output, attention
class DecoderLayer(nn.Module):
def __init__(self,
hid_dim,
n_heads,
pf_dim,
dropout,
device):
super().__init__()
self.layer_norm = nn.LayerNorm(hid_dim)
self.self_attention = MultiHeadAttentionLayer(hid_dim, n_heads, dropout, device)
self.encoder_attention = MultiHeadAttentionLayer(hid_dim, n_heads, dropout, device)
self.positionwise_feedforward = PositionwiseFeedforwardLayer(hid_dim, pf_dim, dropout)
self.dropout = nn.Dropout(dropout)
def forward(self, trg, enc_src, trg_mask, src_mask):
#trg = [batch size, trg len, hid dim]
#enc_src = [batch size, src len, hid dim]
#trg_mask = [batch size, trg len]
#src_mask = [batch size, src len]
#self attention
_trg, _ = self.self_attention(trg, trg, trg, trg_mask)
#dropout, residual connection and layer norm
trg = self.layer_norm(trg + self.dropout(_trg))
#trg = [batch size, trg len, hid dim]
#encoder attention
_trg, attention = self.encoder_attention(trg, enc_src, enc_src, src_mask)
#dropout, residual connection and layer norm
trg = self.layer_norm(trg + self.dropout(_trg))
#trg = [batch size, trg len, hid dim]
#positionwise feedforward
_trg = self.positionwise_feedforward(trg)
#dropout, residual and layer norm
trg = self.layer_norm(trg + self.dropout(_trg))
#trg = [batch size, trg len, hid dim]
#attention = [batch size, n heads, trg len, src len]
return trg, attention
Enfin, connectez l'encodeur et le décodeur pour terminer le transformateur.
class Seq2Seq(nn.Module):
def __init__(self,
encoder,
decoder,
src_pad_idx,
trg_pad_idx,
device):
super().__init__()
self.encoder = encoder
self.decoder = decoder
self.src_pad_idx = src_pad_idx
self.trg_pad_idx = trg_pad_idx
self.device = device
def make_src_mask(self, src):
#src = [batch size, src len]
src_mask = (src != self.src_pad_idx).unsqueeze(1).unsqueeze(2)
#src_mask = [batch size, 1, 1, src len]
return src_mask
def make_trg_mask(self, trg):
#trg = [batch size, trg len]
trg_pad_mask = (trg != self.trg_pad_idx).unsqueeze(1).unsqueeze(3)
#trg_pad_mask = [batch size, 1, trg len, 1]
trg_len = trg.shape[1]
trg_sub_mask = torch.tril(torch.ones((trg_len, trg_len), device = self.device)).bool()
#trg_sub_mask = [trg len, trg len]
trg_mask = trg_pad_mask & trg_sub_mask
#trg_mask = [batch size, 1, trg len, trg len]
return trg_mask
def forward(self, src, trg):
#src = [batch size, src len]
#trg = [batch size, trg len]
src_mask = self.make_src_mask(src)
trg_mask = self.make_trg_mask(trg)
#src_mask = [batch size, 1, 1, src len]
#trg_mask = [batch size, 1, trg len, trg len]
enc_src = self.encoder(src, src_mask)
#enc_src = [batch size, src len, hid dim]
output, attention = self.decoder(trg, enc_src, trg_mask, src_mask)
#output = [batch size, trg len, output dim]
#attention = [batch size, n heads, trg len, src len]
return output, attention
Bien que cela ne soit pas fait cette fois, il est possible de visualiser le poids d'attention après l'apprentissage en utilisant l'attention de la valeur de retour.
Apprenez le modèle. Dans le script de référence, l'époque est arrêtée en examinant l'exactitude des données de validation, mais dans cet essai, l'exactitude des données de validation a diminué à mesure que l'apprentissage progressait à partir de la première époque, donc le surajustement a été ignoré et le modèle après l'époque finale Est adopté.
#----------------------
#Préparation à l'apprentissage
#----------------------
#Paramétrage
INPUT_DIM = len(TEXT.vocab)
OUTPUT_DIM = len(TEXT.vocab)
HID_DIM = 256
ENC_LAYERS = 3
DEC_LAYERS = 3
ENC_HEADS = 8
DEC_HEADS = 8
ENC_PF_DIM = 512
DEC_PF_DIM = 512
ENC_DROPOUT = 0.1
DEC_DROPOUT = 0.1
#Initialisation du codeur
enc = Encoder(INPUT_DIM,
HID_DIM,
ENC_LAYERS,
ENC_HEADS,
ENC_PF_DIM,
ENC_DROPOUT,
device)
#Initialisation du décodeur
dec = Decoder(OUTPUT_DIM,
HID_DIM,
DEC_LAYERS,
DEC_HEADS,
DEC_PF_DIM,
DEC_DROPOUT,
device)
#Spécification de l'ID pour le remplissage
PAD_IDX = TEXT.vocab.stoi[TEXT.pad_token]
#Initialisation du modèle
model = Seq2Seq(enc, dec, PAD_IDX, PAD_IDX, device).to(device)
#Initialisation du poids
def initialize_weights(m):
if hasattr(m, 'weight') and m.weight.dim() > 1:
nn.init.xavier_uniform_(m.weight.data)
model.apply(initialize_weights)
#Paramètres de l'optimiseur
LEARNING_RATE = 0.0005
optimizer = torch.optim.Adam(model.parameters(), lr=LEARNING_RATE)
#Paramètres de la fonction de perte
criterion = nn.CrossEntropyLoss(ignore_index=PAD_IDX)
#Définition de la fonction d'apprentissage
def train(model, iterator, optimizer, criterion, clip):
model.train()
epoch_loss = 0
for i, batch in enumerate(iterator):
src = batch.title
trg = batch.text
optimizer.zero_grad()
output, _ = model(src, trg[:,:-1])
#output = [batch size, trg len - 1, output dim]
#trg = [batch size, trg len]
output_dim = output.shape[-1]
output = output.contiguous().view(-1, output_dim)
trg = trg[:,1:].contiguous().view(-1)
#output = [batch size * trg len - 1, output dim]
#trg = [batch size * trg len - 1]
loss = criterion(output, trg)
loss.backward()
torch.nn.utils.clip_grad_norm_(model.parameters(), clip)
optimizer.step()
epoch_loss += loss.item()
return epoch_loss / len(iterator)
#Définition de la fonction d'évaluation
def evaluate(model, iterator, criterion):
model.eval()
epoch_loss = 0
with torch.no_grad():
for i, batch in enumerate(iterator):
src = batch.title
trg = batch.text
output, _ = model(src, trg[:,:-1])
#output = [batch size, trg len - 1, output dim]
#trg = [batch size, trg len]
output_dim = output.shape[-1]
output = output.contiguous().view(-1, output_dim)
trg = trg[:,1:].contiguous().view(-1)
#output = [batch size * trg len - 1, output dim]
#trg = [batch size * trg len - 1]
loss = criterion(output, trg)
epoch_loss += loss.item()
return epoch_loss / len(iterator)
#Définition de la fonction de mesure du temps de traitement
def epoch_time(start_time, end_time):
elapsed_time = end_time - start_time
elapsed_mins = int(elapsed_time / 60)
elapsed_secs = int(elapsed_time - (elapsed_mins * 60))
return elapsed_mins, elapsed_secs
#Définition de la fonction de génération de phrases
def translate_sentence(sentence, src_field, trg_field, model, device, max_len=1000):
model.eval()
tokens = [token.lower() for token in sentence]
tokens = [src_field.init_token] + tokens + [src_field.eos_token]
src_indexes = [src_field.vocab.stoi[token] for token in tokens]
src_tensor = torch.LongTensor(src_indexes).unsqueeze(0).to(device)
src_mask = model.make_src_mask(src_tensor)
with torch.no_grad():
enc_src = model.encoder(src_tensor, src_mask)
trg_indexes = [trg_field.vocab.stoi[trg_field.init_token]]
for i in range(max_len):
trg_tensor = torch.LongTensor(trg_indexes).unsqueeze(0).to(device)
trg_mask = model.make_trg_mask(trg_tensor)
with torch.no_grad():
output, attention = model.decoder(trg_tensor, enc_src, trg_mask, src_mask)
pred_token = output.argmax(2)[:,-1].item()
trg_indexes.append(pred_token)
if pred_token == trg_field.vocab.stoi[trg_field.eos_token]:
break
trg_tokens = [trg_field.vocab.itos[i] for i in trg_indexes]
return trg_tokens[1:], attention
#----------------------
#Apprentissage de modèle
#----------------------
import time
import math
N_EPOCHS = 100
CLIP = 1
#Obtenez 1 exemple de travail
example_idx = 8
src_sample = vars(train_ds.examples[example_idx])['title']
trg_sample = vars(train_ds.examples[example_idx])['text']
#Afficher le titre et le corps
print(f'src = {src_sample}')
print(f'trg = {trg_sample}')
best_valid_loss = float('inf')
for epoch in range(N_EPOCHS):
start_time = time.time()
train_loss = train(model, train_iter, optimizer, criterion, CLIP)
valid_loss = evaluate(model, test_iter, criterion)
end_time = time.time()
epoch_mins, epoch_secs = epoch_time(start_time, end_time)
#if valid_loss < best_valid_loss:
# best_valid_loss = valid_loss
# torch.save(model.state_dict(), 'drive/My Drive/trained_model.pt')
#Dans le script de référence, la précision des données de validation est utilisée comme indice, mais dans cet essai, la précision des données de validation diminuait au fur et à mesure que l'apprentissage progressait, le surajustement a donc été ignoré et le modèle après l'époque finale a été adopté (compte tenu de la fin du processus). Enregistrer après chaque époque)
torch.save(model.state_dict(), 'drive/My Drive/trained_model.pt')
#Afficher l'exactitude des données de formation / validation pour chaque époque
print(f'Epoch: {epoch+1:02} | Time: {epoch_mins}m {epoch_secs}s')
print(f'\tTrain Loss: {train_loss:.3f} | Train PPL: {math.exp(train_loss):7.3f}')
print(f'\t Val. Loss: {valid_loss:.3f} | Val. PPL: {math.exp(valid_loss):7.3f}')
#Afficher le résultat de la génération du texte à partir du titre d'un exemple de travail toutes les 10 époques
if epoch % 10 == 0:
translation, attention = translate_sentence(src_sample, TEXT, TEXT, model, device)
print(f'predicted trg = {translation}')
Vous pouvez générer un roman en entrant votre titre préféré ci-dessous.
translation, attention = translate_sentence(['Tout titre'], TEXT, TEXT, model, device)
print(f'predicted trg = {translation}')
J'en ai essayé. Les deux premiers sont des titres inclus dans les données d'entraînement, et les deux derniers sont des titres non inclus (pour être exact, ils sont inclus dans le dictionnaire (= deux fois dans le titre ou le corps des données d'entraînement ou des données de test). Parmi les combinaisons de mots (qui apparaissent ci-dessus), celles qui ne sont pas les titres des données d'apprentissage).
Titre d'entrée | Texte généré |
---|---|
souvenirs | Quand j'avais la vingtaine, j'ai rencontré M. Ogai cinq ou six fois. Puis quelques fois du ministère de l'armée(unk)Je l'ai vu quand j'ai livré l'étalonnage à la station, mais c'était facile,(unk)Je n'ai pas assez de matériel pour raconter l'histoire. À cette époque, Hiroshi Yosano, Nagae Ikuta et Kafu Nagai étaient les élèves de M. Kogai, et j'étais comme le petit-fils du professeur. Pour cette raison, je n'ai aucune relation directe avec le professeur, mais je le respecte pour son travail littéraire. Il semble que l'enseignant ait toujours fait attention à ne pas que l'autre personne se sente à l'étroit, souffrant de ce qui semble être une personne difficile, mais c'était plutôt à l'étroit ici. En parlant de pensées, un jour, pour fêter la publication d'un magazine intitulé "Nous" ... (Omis ci-dessous) |
Empreintes | ずつと昔のこと一匹の狐が河岸の粘土層を走つていつたそれから何万年かたつたあとにその粘土層が化石となつてEmpreintesが残つたそのEmpreintesを見ると、むかし狐が何を考えて走つていつたのかがわかる |
cheveux | Ah, tu es triste et je suis mélancolique, Segawa(unk)Si vous regardez la lumière de Fufunabata, vous pouvez voir les yeux de la jeune fille de Yufugure.(unk), Kuchi(unk) |
musiques | (unk)Est(unk)Est(unk)太陽が落ちて太陽の世界が始つた[#「始つた」Est底本でEst「始まつた」](unk)Est戸袋(unk)Est(unk)Le soleil s'est levé et le monde nocturne a commencé(unk)Est妖怪下痢Est(unk)Higurashi a dessiné un diamètre et le monde de Dada a commencé (il(unk)Regardez-le et le Christ l'imprime |
Pour les données de formation, il semble que le texte puisse être reproduit avec une grande précision à partir du titre. D'un autre côté, les titres qui ne sont pas inclus dans les données d'apprentissage sont devenus des phrases sans signification.
Il a été confirmé que le texte peut être généré à partir du titre du roman en utilisant Transformer. Cependant, je n'ai pas pu générer un titre approprié pour le titre qui ne figure pas dans les données d'entraînement, donc la prochaine fois, j'aimerais utiliser les données de validation que j'ai abandonnées cette fois et viser un modèle plus général.
Recommended Posts