自用——备战实习 基于RNN的名称分类

100 阅读3分钟
数据准备

1.定义了一个Unicode字符转到acsii字符的函数 unicodeToASCII

2.定义了一个函数,用上面定义的函数把一些可能不是ascii码的Unicode转到ascii,并且.txt文件中的数据按行存储

3.查找文件用glob.glob()

4.查找文件后定义了一个字典和列表 字典中存储国家名字对应的姓氏,列表中则存储文件名即国家名字

6.定义一个string类型的变量,把所有的大小写字母按照顺序存到这个letters里面(n_letters = len(letters)

7.定义一个函数,给一个字母,返回在上面letters这个变量中字母对应的索引

8.定义一个函数,自变量是一个string,意义是姓氏,返回了一个len(line)1n_letters的tensor变量,将姓氏转化成tensor变量

模型定义

1.模型使用的是rnn模型

2.在rnn模型中,使用了两个线性层,(

self.i2h = nn.Linear(input_size + hidden_size, hidden_size)

self.i2o = nn.Linear(input_size + hidden_size, output_size)

) 激活函数的是logSoftmax,就是softmax函数外面套了一层log函数

3.在前向传播过程中,先把输入和隐藏层合并成一个大小为input_size+hidden_size的矩阵(torch.cat()函数实现,dim=1)

4.hidden计算,output计算 5.output激活

6.返回output和hidden

7.定义了一个函数,功能是返回一个1*hidden_size的tensor,用来在训练的时候创建隐藏层

模型训练

1.首先定义了几个变量 hidden_size=128 隐藏层大小

epochs=100000 训练轮数

print_every=5000 每训练五千个名字打印一个训练结果

learning_rate=0.005 学习率

2.定义一个随机选择器,可以随机选择国家和这个国家对应的一个姓氏,并把国家对应的索引和这个姓氏转换成tensor,返回这四个值

3.rnn = RNN(n_letters, hidden_size, len(categories)) # n_letters表明了是针对单个字母训练,训练到姓氏的最后一个字母

4.优化器用的是SGD,损失函数用的是nn.NLLLoss()(NLLLoss+Logsoftmax = 交叉熵损失函数)

5.定义训练函数,将line_tensor和category_tensor传入,先创建一个hidden表示隐藏层,然后梯度清零防止梯度累积(为什么要防止梯度累积?),然后开始训练,batchsize就是len(line_tensor.size[0])(也就是单个姓氏的长度),训练完计算损失,反向传播,更新参数,返回输出和损失

6.定义current_loss = 0和all_losses = [] 存储损失函数 用来画表

7.开始训练,用随机选择器选择一个国家和对应的一个姓氏,将两个tensor传入train函数,并且用current_loss函数存储损失

每训练print_every个姓氏,就把对应结果打印输出(取出output中最大概率对应的i索引,在用索引找到对应的国家,并且和实际的真实值对比)

每训练plot_every个姓氏就把平均损失存入列表中,并把current——loss清零

8.训练完毕,存储参数。

模型验证

为了查看网络在不同类别上的表现如何,我们将创建一个混淆矩阵,为每种实际语言(行)指示网络猜测(列)哪种语言。 为了计算混淆矩阵,使用evaluate()通过网络运行一堆样本,该样本等于train()减去反向传播器。

  1. 定义函数,预测使用训练好的rnn网络训练单个名字。
  2. 随机选择10000个名字预测,将预测的结果保存在矩阵中。
  3. 定义矩阵大小为国家数量。
  4. 每训练一个名字 就把预测结果位置的数+1
  5. 最后除以对应行的总数,算出概率。
  6. 最后绘图
在用户输入上运行