在这篇文章中,我们将了解 RNN(即循环神经网络),并尝试通过 PyTorch 从头开始实现其中的部分内容。是的,这并不完全是从头开始,因为我们仍然依赖 PyTorch autograd 来计算梯度并实现反向传播,但我仍然认为我们也可以从这个实现中收集到有价值的见解。
有关 RNN 的简要介绍性概述,我建议您查看上一篇文章,其中我们不仅探讨了 RNN 是什么及其工作原理,还探讨了如何使用 Keras 实现 RNN 模型。这次,我们将使用 PyTorch,但采取更实际的方法从头开始构建一个简单的 RNN。
完全免责声明,这篇文章很大程度上改编自PyTorch 教程这个 PyTorch 教程。我修改并改变了预处理和训练中涉及的一些步骤。我仍然建议您将其作为补充材料查看。考虑到这一点,让我们开始吧。
数据准备
任务是建立一个简单的分类模型,可以根据名字正确确定一个人的国籍。更简单地说,我们希望能够分辨出特定名称的来源。
下载
我们将使用 PyTorch 教程中的一些标记数据。我们只需输入即可下载
!curl -O https://download.pytorch.org/tutorial/data.zip; unzip data.zip
此命令将下载文件并将其解压到当前目录中,文件夹名称为data.
现在我们已经下载了所需的数据,让我们更详细地看一下数据。首先,这是我们需要的依赖项。
import os
import random
from string import ascii_letters
import torch
from torch import nn
import torch.nn.functional as F
from unidecode import unidecode
_ = torch.manual_seed(42)
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
我们首先指定一个目录,然后尝试打印出其中的所有标签。然后我们可以构建一个字典,将语言映射到数字标签。
data_dir = "./data/names"
lang2label = {
file_name.split(".")[0]: torch.tensor([i], dtype=torch.long)
for i, file_name in enumerate(os.listdir(data_dir))
}
我们看到一共有18种语言。我将每个标签包装为张量,以便我们可以在训练期间直接使用它们。
lang2label
{
'Czech': tensor([0]),
'German': tensor([1]),
'Arabic': tensor([2]),
'Japanese': tensor([3]),
'Chinese': tensor([4]),
'Vietnamese': tensor([5]),
'Russian': tensor([6]),
'French': tensor([7]),
'Irish': tensor([8]),
'English': tensor([9]),
'Spanish': tensor([10]),
'Greek': tensor([11]),
'Italian': tensor([12]),
'Portuguese': tensor([13]),
'Scottish': tensor([14]),
'Dutch': tensor([15]),
'Korean': tensor([16]),
'Polish': tensor([17])}
让我们将语言数量存储在某个变量中,以便稍后在模型声明中使用它,特别是当我们指定最终输出层的大小时。
num_langs = len(lang2label)
预处理
现在,让我们对名称进行预处理。我们首先要用来unidecode标准化所有名称并删除任何锐利符号或类似符号。例如,
unidecode("Ślusàrski")
'Slusarski'
一旦我们有了解码后的字符串,我们就需要将其转换为张量,以便模型可以处理它。这可以首先通过构建映射来完成char2idx,如下所示。
char2idx = {
letter: i for i, letter in enumerate(ascii_letters + " .,:;-'")}
num_letters = len(char2idx); num_letters
59
我们看到我们的字符词汇表中共有 59 个标记。这包括空格和标点符号,例如 .,:;-' . This also means that each name will now be expressed as a tensor of size (num_char, 59) ; in other words, each character will be a tensor of size (59,)。我们现在可以构建一个完成此任务的函数,如下所示:
def name2tensor(name):
tensor = torch.zeros(len(name), 1, num_letters)
for i, char in enumerate(name):
tensor[i][0][char2idx[char]] = 1
return tensor
如果你仔细阅读代码,你会发现输出张量的大小是(num_char, 1, 59),这与上面的解释不同。嗯,这个额外维度的原因是我们在本例中使用的批量大小为 1。在 PyTorch 中,RNN 层期望输入张量的大小为(seq_len, batch_size, input_size)。由于每个名称都有不同的长度,因此为了简单起见,我们不会对输入进行批处理,而只是将每个输入用作单个批处理。有关更详细的讨论,请查看此论坛讨论。
name2tensor()让我们使用虚拟输入快速验证函数的输出。
name2tensor("abc")
tensor([[[1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0.,

本文介绍了如何使用PyTorch从头开始实现循环神经网络(RNN),用于根据姓名预测国籍。作者通过实例展示了数据预处理、模型构建、训练过程以及简单RNN和GRU模型的性能对比。

1408

被折叠的 条评论
为什么被折叠?



