用PyTorch平台搭建循环神经网络RNN用于char文本生成
首先,我们需要导入必要的库:
import torch
import torch.nn as nn
import string
import random
接下来,我们需要定义一个类来创建我们的循环神经网络模型:
class RNN(nn.Module):
def __init__(self, input_size, hidden_size, output_size):
super(RNN, self).__init__()
self.hidden_size = hidden_size
self.i2h = nn.Linear(input_size + hidden_size, hidden_size)
self.i2o = nn.Linear(input_size + hidden_size, output_size)
self.softmax = nn.LogSoftmax(dim=1)
def forward(self, input, hidden):
combined = torch.cat((input, hidden), 1)
hidden = self.i2h(combined)
output = self.i2o(combined)
output = self.softmax(output)
return output, hidden
def initHidden(self):
return torch.zeros(1, self.hidden_size)
这个类包含以下方法:
__init__方法:初始化模型的参数。它接受三个参数:input_size表示输入数据的大小,hidden_size表示隐藏层的大小,output_size表示输出数据的大小。在这个方法中,我们定义了三个神经网络层:一个输入到隐藏层的线性层,一个输入到输出层的线性层和一个LogSoftmax层。forward方法:定义如何在模型中传递数据。它接受两个参数:input表示输入数据,hidden表示隐藏层的状态。在这个方法中,我们将输入数据和隐藏层状态连接起来,并通过两个线性层传递数据。最后,我们使用LogSoftmax层计算输出结果,并返回输出和更新后的隐藏层状态。initHidden方法:初始化隐藏层状态。
接下来,我们需要定义一些辅助函数来处理数据和训练模型:
all_chars = string.ascii_letters + " .,;'"
n_chars = len(all_chars)
def char_to_tensor(char):
tensor = torch.zeros(1, n_chars)
tensor[0][all_chars.index(char)] = 1
return tensor
def random_training_pair():
input_char = random.choice(all_chars)
target_char = random.choice(all_chars)
return input_char, target_char
def train(rnn, input_char, target_char):
hidden = rnn.initHidden()
rnn.zero_grad()
loss = 0
for i in range(len(input_char)):
input_tensor = char_to_tensor(input_char[i])
output, hidden = rnn(input_tensor, hidden)
target_tensor = torch.tensor([all_chars.index(target_char[i])], dtype=torch.long)
loss += nn.functional.nll_loss(output, target_tensor)
loss.backward()
for p in rnn.parameters():
p.data.add_(p.grad.data, alpha=-0.1)
return output, loss.item() / len(input_char)
这些辅助函数包括:
all_chars:包含所有可能的字符的字符串。n_chars:字符集的大小。char_to_tensor:将字符转换为PyTorch张量。random_training_pair:从字符集中随机选择一个输入字符和目标字符。train:训练模型的函数。它接受三个参数:rnn表示RNN模型,input_char表示输入字符,target_char表示目标字符。在这个方法中,我们首先初始化隐藏层状态。然后,我们遍历输入字符,并将每个字符转换为张量,然后将其传递给RNN模型。我们使用目标字符计算损失,并使用反向传播算法更新模型参数。最后,我们返回输出结果和平均损失。
现在,我们可以训练我们的模型:
n_iters = 100000
print_every = 5000
plot_every = 1000
hidden_size = 100
lr = 0.005
rnn = RNN(n_chars, hidden_size, n_chars)
for iter in range(1, n_iters + 1):
input_char, target_char = random_training_pair()
output, loss = train(rnn, input_char, target_char)
if iter % print_every == 0:
print("Iter: %d, Loss: %.4f" % (iter, loss))
if iter % plot_every == 0:
torch.save(rnn.state_dict(), "char_rnn_generation.pth")
在这里,我们定义了一些训练参数,如迭代次数,打印和绘制频率,隐藏层大小和学习率。我们使用随机输入字符和目标字符训练我们的模型,并每隔一段时间打印训练损失。最后,我们保存模型参数。
现在,我们可以使用我们训练的模型来生成新的字符序列:
def generate(rnn, prime_str='A', predict_len=100, temperature=0.8):
hidden = rnn.initHidden()
prime_input = char_to_tensor(prime_str)
predicted = prime_str
for p in range(len(prime_str) - 1):
_, hidden = rnn(prime_input[:, p], hidden)
inp = prime_input[:, -1]
for p in range(predict_len):
output, hidden = rnn(inp, hidden)
output_dist = output.data.view(-1).div(temperature).exp()
top_i = torch.multinomial(output_dist, 1)[0]
predicted_char = all_chars[top_i]
predicted += predicted_char
inp = char_to_tensor(predicted_char)
return predicted
这个函数接受四个参数:rnn表示我们训练的RNN模型,prime_str表示我们要开始生成的字符序列,predict_len表示生成的字符序列的长度,temperature表示温度参数。在这个函数中,我们首先初始化隐藏层状态,并将输入的字符序列传递给模型。然后,我们使用模型生成新的字符序列,并根据温度参数随机选择一个字符。最后,我们返回生成的字符序列。
现在,我们可以使用我们的模型生成新的字符序列:
rnn.load_state_dict(torch.load("char_rnn_generation.pth"))
print(generate(rnn, prime_str="A"))
这里,我们首先加载我们训练的模型参数。然后,我们使用generate函数生成一个以'A'为开头的字符序列。输出结果可能如下所示:
Aulohrhnatrrt tthtahhrrthae arh htaaeahraooaeearttht hooetfeoatnhrheaaenaa tttetrr h h rhrae aateraeatn
这里是完整的代码
原文地址: https://www.cveoy.top/t/topic/hlTa 著作权归作者所有。请勿转载和采集!