使用Pytorch从零开始构建RNN

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

在这篇文章中,我们将了解 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.,
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值