在过去的几周里,我花了很多时间在PyTorch中实现一个char-rnn版本。我以前从未训练过神经网络,所以这可能是一个有趣的起点。这个想法(来自递归神经网络的不合理影响)允许您在文本上训练基于字符的递归神经网络(RNN)并获得一些令人惊讶的好结果。然而,我没有得到我想要的结果,但我想分享一些示例代码和结果,希望对其他开始尝试PyTorch和RNN的人有所帮助。这是JupyterNotebook格式的代码:PyTorch.ipynb中的char-rnn。您可以点击本页面顶部的“OpeninColab”按钮,在谷歌的Colab服务中打开,使用免费的GPU进行训练。所有内容大约有75行代码,我将尝试在这篇博文中尽可能详细地解释它。第一步:准备数据首先,我们需要下载数据。我正在使用古腾堡计划中的这些数据:汉斯·克里斯蒂安·安德森的童话故事。!wget-Ofairy-tales.txt这是准备数据的代码。我使用fastai库中的Vocab类进行数据处理,它将一堆字母转换成一个“词汇表”,然后用这个“词汇表”将字母变成数字。之后,我们有大量数字(training_set)可用于训练我们的模型。fromfastai.textimport*text=unidecode.unidecode(open('fairy-tales.txt').read())v=Vocab.create((xforxintext),max_vocab=400,min_freq=1)training_set=torch.张量(v.nu??mericalize([xforxintext])).type(torch.LongTensor).cuda()num_letters=len(v.itos)第二步:定义模型这是LSTM类在PyTorch中的封装。除了包装LSTM类之外,它还做了三件事:One-hot对输入向量进行编码,使它们具有正确的维度。在LSTM层之后加一个线性变换,因为LSTM的输出是一个长度为hidden_??size的向量,我们需要的是一个长度为input_size的向量,这样才能转换成一个字符。将LSTM隐藏层的输出向量(实际有2个向量)保存为实例变量,然后在每一轮之后执行.detach()函数。(我很难解释.detach()的作用,但我的理解是它以某种方式“结束”了模型的导数计算)(LCTT译注:detach()函数是将tensor的requires_grad参数设置为False,即反向传播到张量结束。)classMyLSTM(nn.Module):def__init__(self,input_size,hidden_??size):super().__init__()self.lstm=nn.LSTM(input_size,hidden_??size,batch_first=True)self.h2o=nn.Linear(hidden_??size,input_size)self.input_size=input_sizeself.hidden=Nonedefforward(self,input):input=torch.nn.functional.one_hot(input,num_classes=self.input_size).type(torch.FloatTensor).cuda().unsqueeze(0)ifself.hiddenisNone:l_output,selfself.hidden=self.lstm(input)else:l_output,selfself.hidden=self.lstm(input,self.hidden)self.hidden=(self.hidden[0].detach(),self.hidden[1].detach())returnsself.h2o(l_output)这段代码还做了一些神奇但不太明显的功能。如果你的输入是一个向量(比如[1,2,3,4,5,6]),对应六个字母,那么我的理解是nn.LSTM内部会使用反向传播沿时间更新隐藏向量6秒-速度。第三步:编写训练代码模型不会自己训练!我首先尝试使用fastai库中的一个辅助类(也是PyTorch中的一个包)。我当时有点懵,不知道它是干什么的,最后还是自己写了模型训练的代码。下面的代码(epoch()方法)是一轮训练过程的基本信息。基本上,它会重复执行以下操作:将字符串传递到RNN模型中,例如andtheyshouldnottoteas。(要作为数值向量传入)得到下一个字母的预测计算RNN模型预测和真正的下一个字母(e,因为单词tease以e结尾)之间的损失函数计算梯度(使用loss.backward()函数)沿梯度下降的方向修改模型中参数的权重(使用self.optimizer.step()函数)classTrainer():def__init__(self):self.rnn=MyLSTM(input_size,hidden_??size)。cuda()self.optimizer=torch.optim.Adam(self.rnn.parameters(),amsgrad=True,lrlr=lr)defepoch(self):i=0while
