共计 5062 个字符,预计需要花费 13 分钟才能阅读完成。
作者 |DR. VAIBHAV KUMAR
编译 |VK
起源 |Analytics In Diamag
自然语言解决(NLP)有很多乏味的利用,文本生成就是其中一个乏味的利用。
当一个机器学习模型工作在诸如循环神经网络、LSTM-RNN、GRU 等序列模型上时,它们能够生成输出文本的下一个序列。
PyTorch 提供了一组功能强大的工具和库,这些工具和库为这些基于 NLP 的工作削减了能源。它不仅须要较少的预处理量,而且放慢了训练过程。
在本文中,咱们将在 PyTorch 中训练几种语言的循环神经网络(RNN)。训练胜利后,RNN 模型将预测属于以输出字母结尾的语言的名称。
PyTorch 实现
这个实现是在 Google Colab 中实现的,其中的数据集是从 Google 驱动器获取的。所以,首先,咱们将用 Colab Notebook 装置 Google 驱动器。
from google.colab import drive
drive.mount('/content/gdrive')
当初,咱们将导入所有必须的库。
from __future__ import unicode_literals, print_function, division
from io import open
import glob
import os
import unicodedata
import string
import torch
import torch.nn as nn
import random
import time
import math
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
上面的代码片段将读取数据集。
all_let = string.ascii_letters + ".,;'-"
n_let = len(all_let) + 1
def getFiles(path):
return glob.glob(path)
# Unicode 字符串到 ASCII
def unicodeToAscii(s):
return ''.join(c for c in unicodedata.normalize('NFD', s)
if unicodedata.category(c) != 'Mn'
and c in all_let
)
# 读一个文件并分成几行
def getLines(filename):
lines = open(filename, encoding='utf-8').read().strip().split('\n')
return [unicodeToAscii(line) for line in lines]
# 建设 cat_lin 字典,存储每个类别的行列表
cat_lin = {}
all_ctg = []
for filename in getFiles('gdrive/My Drive/Dataset/data/data/names/*.txt'):
categ = os.path.splitext(os.path.basename(filename))[0]
all_ctg.append(category)
lines = getLines(filename)
cat_lin[categ] = lines
n_ctg = len(all_ctg)
在下一步中,咱们将定义 module 类来生成名称。该模块将是一个循环神经网络。
class NameGeneratorModule(nn.Module):
def __init__(self, inp_size, hid_size, op_size):
super(NameGeneratorModule, self).__init__()
self.hid_size = hid_size
self.i2h = nn.Linear(n_ctg + inp_size + hid_size, hid_size)
self.i2o = nn.Linear(n_ctg + inp_size + hid_size, op_size)
self.o2o = nn.Linear(hid_size + op_size, op_size)
self.dropout = nn.Dropout(0.1)
self.softmax = nn.LogSoftmax(dim=1)
def forward(self, category, input, hidden):
inp_comb = torch.cat((category, input, hidden), 1)
hidden = self.i2h(inp_comb)
output = self.i2o(inp_comb)
op_comb = torch.cat((hidden, output), 1)
output = self.o2o(op_comb)
output = self.dropout(output)
output = self.softmax(output)
return output, hidden
def initHidden(self):
return torch.zeros(1, self.hid_size)
以下函数将用于从列表中抉择随机项,从类别中抉择随机行
def randChoice(l):
return l[random.randint(0, len(l) - 1)]
def randTrainPair():
category = randChoice(all_ctg)
line = randChoice(cat_lin[category])
return category, line
以下函数将数据转换为 RNN 模块的兼容格局。
def categ_Tensor(categ):
li = all_ctg.index(categ)
tensor = torch.zeros(1, n_ctg)
tensor[0][li] = 1
return tensor
def inp_Tensor(line):
tensor = torch.zeros(len(line), 1, n_let)
for li in range(len(line)):
letter = line[li]
tensor[li][0][all_let.find(letter)] = 1
return tensor
def tgt_Tensor(line):
letter_indexes = [all_let.find(line[li]) for li in range(1, len(line))]
letter_id.append(n_let - 1) # EOS
return torch.LongTensor(letter_id)
以下函数将创立随机训练示例,包含类别、输出和指标张量。
# 损失
criterion = nn.NLLLoss()
#学习率
lr_rate = 0.0005
def train(category_tensor, input_line_tensor, target_line_tensor):
target_line_tensor.unsqueeze_(-1)
hidden = rnn.initHidden()
rnn.zero_grad()
loss = 0
for i in range(input_line_tensor.size(0)):
output, hidden = rnn(category_tensor, input_line_tensor[i], hidden)
l = criterion(output, target_line_tensor[i])
loss += l
loss.backward()
for p in rnn.parameters():
p.data.add_(p.grad.data, alpha=-lr_rate)
return output, loss.item() / input_line_tensor.size(0)
为了显示训练期间的工夫,定义以下函数。
def time_taken(since):
now = time.time()
s = now - since
m = math.floor(s / 60)
s -= m * 60
return '%dm %ds' % (m, s)
在下一步中,咱们将定义 RNN 模型。
model = NameGenratorModule(n_let, 128, n_let)
咱们将看到定义的 RNN 模型的参数。
print(model)
下一步,该模型将训练 10000 个 epoch。
epochs = 100000
print_every = 5000
plot_every = 500
all_losses = []
total_loss = 0 # 每次迭代时重置
start = time.time()
for iter in range(1, epochs + 1):
output, loss = train(*rand_train_exp())
total_loss += loss
if iter % print_every == 0:
print('Time: %s, Epoch: (%d - Total Iterations: %d%%), Loss: %.4f' % (time_taken(start), iter, iter / epochs * 100, loss))
if iter % plot_every == 0:
all_losses.append(total_loss / plot_every)
total_loss = 0
咱们将可视化训练中的损失。
plt.figure(figsize=(7,7))
plt.title("Loss")
plt.plot(all_losses)
plt.xlabel("Epochs")
plt.ylabel("Loss")
plt.show()
最初,咱们将对咱们的模型进行测试,以测试在给定起始字母表字母时生成属于语言的名称。
max_length = 20
# 类别和起始字母中的示例
def sample_model(category, start_letter='A'):
with torch.no_grad(): # no need to track history in sampling
category_tensor = categ_Tensor(category)
input = inp_Tensor(start_letter)
hidden = NameGenratorModule.initHidden()
output_name = start_letter
for i in range(max_length):
output, hidden = NameGenratorModule(category_tensor, input[0], hidden)
topv, topi = output.topk(1)
topi = topi[0][0]
if topi == n_let - 1:
break
else:
letter = all_let[topi]
output_name += letter
input = inp_Tensor(letter)
return output_name
# 从一个类别和多个起始字母中获取多个样本
def sample_names(category, start_letters='XYZ'):
for start_letter in start_letters:
print(sample_model(category, start_letter))
当初,咱们将查看样本模型,在给定语言和起始字母时生成名称。
print("Italian:-")
sample_names('Italian', 'BPRT')
print("\nKorean:-")
sample_names('Korean', 'CMRS')
print("\nRussian:-")
sample_names('Russian', 'AJLN')
print("\nVietnamese:-")
sample_names('Vietnamese', 'LMT')
因而,正如咱们在下面看到的,咱们的模型曾经生成了属于语言类别的名称,并从输出字母开始。
参考文献:
- Trung Tran,“Text Generation with Pytorch”.
- “NLP from scratch: Generating names with a character level RNN”, PyTorch Tutorial.
- Francesca Paulin,“Character-Level LSTM in PyTorch”, Kaggle.
原文链接:https://analyticsindiamag.com…
欢送关注磐创 AI 博客站:
http://panchuang.net/
sklearn 机器学习中文官网文档:
http://sklearn123.com/
欢送关注磐创博客资源汇总站:
http://docs.panchuang.net/