Pytorch官方教程代码翻译_ClassifyingNames_Charter-Level_RNN

Pytorch官方教程代码翻译_ClassifyingNames_Charter-Level_RNN

我们将建立并训练一个基于caharacter-level RNN(个人理解:字符级的RNN模型)来分类单词,该模型将单词当做一串字母读入,在每一轮训练中输出预测结果和隐藏状态,将其以前的隐藏状态提供给下一步。我们将单词属于哪种语言作为最后的预测结果当做输出。
训练数据集采用来自18种语言的姓氏大概有1000多条。预测结果基于名字的拼写方式得出。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# coding=utf-8
from __future__ import unicode_literals,print_function,division
from io import open
import glob
import torch
import unicodedata
import string
'''
准备数据:
在数据集data/names目录下有18个TXT文件被命名为"[language].txt",每个文件包含一串名字,每行一个
大多数名字都是罗马字符(但我们仍需要将Unicode转为ASCII码)
我们最终要得到一个将每种语言与其名字相对应的字典列表形式{language:[names...]}
变量 category 和 line (在例子中对应language和name)为以后方便扩展被使用
'''
def findFiles(path):return glob.glob(path)
print(findFiles('data/names/*.txt'))
all_letters = string.ascii_letters + " .,;'"
n_letters = len(all_letters)
#将Unicode转为ASCII码
def unicodeToAscii(s):
return ''.join(
c for c in unicodedata.normalize('NFD',s)
if unicodedata.category(c) != 'Mn'
and c in all_letters
)
print(unicodeToAscii('Ślusàrski'))
#建立category-line字典,每种语言与其名字相对应的字典列表形式{language:[names...]}
category_lines = {}
all_categories = []
#读取文件进行行分割
def readLines(filename):
lines = open(filename,encoding='utf-8').read().strip().split('\n')
return [unicodeToAscii(line) for line in lines]
for filename in findFiles('data/names/*.txt'):
category = filename.split('/')[-1].split('.')[0]
all_categories.append(category)
lines = readLines(filename)
category_lines[category] = lines
n_categories = len(all_categories)
'''
将名字转为Tensor:
我们需要将已经组织好的名字转为Tensor变量使得GPU和pytorch可以使用
'''
def letterToIndex(letter):
return all_letters.find((letter))
def letterToTensor(letter):
tensor = torch.zeros(1,n_letters)
tensor[0][letterToIndex(letter)] = 1
return tensor
def lineToTensor(line):
tensor = torch.zeros(len(line),1,n_letters)
for li,letter in enumerate(line):
tensor[li][0][letterToIndex(letter)] = 1
return tensor
print (letterToIndex('J'))
print (lineToTensor('Jones').size())

创建网络

在自动求导梯度之前,在这之前在Torch中创建一个RNN网络涉及到每层参数的拷贝需要消耗部分时间。以前神经层包含的隐藏层和梯度现在全部被计算图自动处理。这意味着你可以以更纯粹的方式搭建RNN网。。。
这个RNN模型仅仅采用两个线性层分别处理输入数据和隐藏层,通过LogSoftmax层产生输出。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import torch.nn as nn
from torch.autograd import Variable
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()
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 Variable(torch.zeros(1, self.hidden_size))
n_hidden = 128
rnn = RNN(n_letters, n_hidden, n_categories)

为了使这个模型可以运行,我们需要传递一个输入(在这个例子中,是当前单词的张量)和之前的隐藏状态(最开始初始化为0)。我们将得到输出(每种语言的可能性)和下个隐藏状态的值(在下一轮训练中使用)。
注意:pytorch模型基于Variables而不是直接使用Tensor进行操作

1
2
3
4
input = Variable(letterToTensor('A'))
hidden = Variable(torch.zeros(1, n_hidden))
output, next_hidden = rnn(input, hidden)

为了更有效的进行计算,我们不想在进行每一步训练时都创建一个新的Tensor,因此我们将使用 lineToTnsor代替letterToTensor并且使用切片。这将会极大的优化Tensor的预计算消耗。

训练

训练准备

在训练之前我们需要准备几个辅助函数。第一个是用来将网络的输出翻译为

Donate comment here