您好, 欢迎来到 !    登录 | 注册 | | 设为首页 | 收藏本站

Python深度学习实战!全头条会的不超过一只手吧!不吹不黑!

5b51 2022/1/14 8:24:55 python 字数 19303 阅读 801 来源 www.jb51.cc/python

pridict(\'Hinton\') (-0.47)Scottish (-1.52)English (-3.57)Irish pridict(\'Schmidhuber\') (-0.19)German (-2.48)Czech

概述

Python深度学习实战!全头条会的不超过一只手吧!不吹不黑!

pridict('Hinton')
(-0.47) Scottish
(-1.52) English
(-3.57) Irish
pridict('Schmidhuber')
(-0.19) German
(-2.48) Czech
(-2.68) Dutch

Python深度学习实战!全头条会的不超过一只手吧!不吹不黑!

all_filenames结果

 ['data/Czech.txt','data/German.txt','data/Arabic.txt','data/Japanese.txt','data/Chinese.txt','data/Vietnamese.txt','data/Russian.txt','data/French.txt','data/Irish.txt','data/English.txt','data/Spanish.txt','data/Greek.txt','data/Italian.txt','data/Portuguese.txt','data/Scottish.txt','data/Dutch.txt','data/Korean.txt','data/Polish.txt']

进群:548377875  即可获取不同的PDF哦!都是非常实用的呢!

Python深度学习实战!全头条会的不超过一只手吧!不吹不黑!

打印结果

57
'Slusarski'

构建 语言类别-姓名映射字典 ,形如 {language1: [name1,name2,...],language2: [name_x1,name_x2,...]}

Python深度学习实战!全头条会的不超过一只手吧!不吹不黑!

将姓名转化为Tensors

跟机器学习类似,在这里我们也需要将文本转化为具体的计算机能理解的数据形式。

为了表征单个的字符, 我们使用 独热编码向量one-hot vector , 该向量的尺寸为 1 x n_letters (每个字符是2维向量)

例如

Python深度学习实战!全头条会的不超过一只手吧!不吹不黑!

定义letter_to_tensor函数

import torch
# 将字符转化为 <1 x n_letters> 的Tensor
def letter_to_tensor(letter):
 tensor = torch.zeros(1,n_letters)
 letter_index = all_letters.find(letter)
 tensor[0][letter_index] = 1
 return tensor
# 将姓名转化成尺寸为
 
  的数据
# 使用的是one-hot编码方式转化
def name_to_tensor(name):
 tensor = torch.zeros(len(name),1,n_letters)
 for ni,letter in enumerate(name):
 letter_index = all_letters.find(letter)
 tensor[ni][0][letter_index] = 1
 return tensor

 

现在我们运行letter_to_tensor('J')

print(letter_to_tensor('J'))

显示上面代码运行结果

 tensor([[0.,0.,1.,0.]])
name_to_tensor('Jones').size()
print(name_to_tensor('Jones'))

显示上面代码运行结果

 torch.Size([5,57])
 tensor([[[0.,0.]],[[0.,0.]]])

构建神经网络

Python深度学习实战!全头条会的不超过一只手吧!不吹不黑!

注意看图中各个参数解读:

大家仔细看看琢磨琢磨这个图构造。现在我们先看看 combined 这个操作

a = t.Tensor(3,1)
b = t.Tensor(3,2)
print(a) #a
print(b) #b
print(t.cat((a,b),1)) #a、b合并后的样子

打印结果

 tensor([[0.0000],[0.0000],[0.0000]])
 tensor([[ 0.0000,0.0000],[ 0.0000,-0.0000],0.0000]])
 tensor([[ 0.0000,0.0000,0.0000]])

开始DIY我们第一个循环神经网络RNN,各个参数解读:

import torch.nn as nn
class RNN(nn.Module):
 def __init__(self,input_size,hidden_size,output_size):
 super(RNN,self).__init__()
 self.input_size = input_size
 self.hidden_size = hidden_size
 self.output_size = output_size
 self.i2h = nn.Linear(input_size + hidden_size,hidden_size)
 self.i2o = nn.Linear(input_size + hidden_size,output_size)
 def forward(self,input,hidden):
 #将input和之前的网络中的隐藏层参数合并。
 combined = torch.cat((input,hidden),1)
 hidden = self.i2h(combined) #计算隐藏层参数
 output = self.i2o(combined) #计算网络输出的结果
 return output,hidden 
 def init_hidden(self):
 #初始化隐藏层参数hidden
 return torch.zeros(1,self.hidden_size)

检验我们构建的RNN网络

定义好 RNN 类之后,我们可以创建RNN的实例

rnn = RNN(input_size=57,#输入每个字母向量的长度(57个字符)
 hidden_size=128,#隐藏层向量的长度,神经元个数。这里可自行调整参数大小
 output_size=18) #语言的种类数目

要运行此网络,我们需要给网络传入:

经过网络内部的运算,我们将得到:

input = letter_to_tensor('A')
hidden = rnn.init_hidden()
output,next_hidden = rnn(input,hidden)
print('output.size =',output.size())

显示上面代码运行结果

 output.size = torch.Size([1,18])

现在我们使用 line_to_tensor 替换 letter_to_tensor 来构件输入的数据。注意在本例子中,给RNN网络一次输入一个姓名数据,但对该网络而言,是将姓名数据拆分成字母数组数据,逐次输入训练网络,直到这个姓名最后一个字母数组输入完成,才输出真正的预测结果(姓名所属的语言类别)。

输入 RNN神经网络 的数据的粒度变细,不再是 姓名数组数据(三维) ,而是 组成姓名的字母的数组或矩阵(二维) 。

input = name_to_tensor('Albert')
hidden = torch.zeros(1,128) #这里的128是hidden_size
#给rnn传入的初始化hidden参数是尺寸为(1, 128)的zeros矩阵
#input[0]是传入姓名的第一个字符数组,注意这个数组是batch_size=1的矩阵。因为在pytorch中所有输入的数据都是batch方式输入的
output,next_hidden = rnn(input[0],hidden)
print(output.shape)
print(output)

显示上述结果

 torch.Size([1,18])
 tensor([[-0.0785,0.0147,0.0940,-0.0518,-0.0286,0.0175,-0.0641,-0.0449,-0.0013,0.0421,0.0153,0.0269,-0.0556,0.0304,-0.0133,-0.0572,0.0217,0.1066]],grad_fn=
 
  )

 

现在我们看看output这个tensor中的含有数据,想办法从中提取出预测的 语言类别信息 。

具体思路:

该索引值就是 所属语言类别的索引值,具体我们可以看下面的例子更好的理解tensor的操作方法

output.data
output.data.topk(1)

显示上面两行代码运行结果

 tensor([[-0.0785,0.1066]])
 (tensor([[0.1066]]),tensor([[17]]))

上面的两行代码

其中第一行代码得到tensor中的data

第二行代码得到某姓姓名(这里我们实际上只输入了一个字母,姑且当成只有一个字母的姓名)的 所属语言的似然值 及 所属语言类别的索引值

top_n,top_i = output.data.topk(1)
top_n #所属语言的似然值,我们可以将其想象成概率
top_i #所属语言类别信息

显示上面tpo_n和 top_i

 tensor([[0.1066]])
 tensor([[17]])

接下来我们继续看

top_n,top_i = output.data.topk(1)
top_i[0][0] #所属语言类别的索引值

显示top_i[0][0]

 tensor(17)

准备训练RNN

在训练前,我们把上面刚刚测试的求 所属语言类别的索引值 方法封装成函数 category_from_output 。

函数输入:

函数输出

def category_from_output(output):
 _,top_i = output.data.topk(1) 
 category_i = top_i[0][0]
 return all_categories[category_i],category_i
category_from_output(output)

显示category_from_output(output)运行结果

 ('Polish',tensor(17))

类比机器学习中需要将数据打乱,这里我们也要增入随机性(打乱)。

但不是将训练数据打乱,而是每次训练时随机的从数据集中抽取一种语言中的一个姓名。

这里我们定义了 random_training_pair 函数函数返回的是一个元组 (category,name,category_tensor,name_tensor) :

在定义函数前先看下面几个例子,更好的理解函数内部的运算过程。

category = random.choice(all_categories)
category

显示category

 'Polish'

上面的随机抽取了 一种语言 , 接下来我们在 该语言 中抽取一个 姓名

name = random.choice(category_names[category])
name

显示name

 'Krol'

训练过程中我们要有标签数据,在本文中 所属语言的索引值 作为 标签

由于pytorch中训练过程中使用的都是tensor结构数据,其中的元素都是浮点型数值,所以这里我们使用LongTensor, 可以保证标签是整数。

另外要注意的是,pytorch中运算的数据都是batch。所以我们要将 所属语言的索引值 放入一个list中,再将该list传入torch.LongTensor()中

category_tensor = torch.LongTensor([all_categories.index(category)])
category_tensor

显示category_tensor

 tensor([17])

同理,name也要转化为tensor,这里我们调用name_to_tensor函数即可。

name_tensor = name_to_tensor(name)
name_tensor

显示name_tensor

 tensor([[[0.,0.]]])

刚刚几个例子,相信大家已经明白了函数内部的实现方法,现在将其封装成 random_training_pair函数

import random
def random_training_pair(): 
 category = random.choice(all_categories)
 name = random.choice(category_names[category])
 category_tensor = torch.LongTensor([all_categories.index(category)])
 name_tensor = name_to_tensor(name)
 return category,name_tensor
#我们从数据集中抽取十次
for i in range(10):
 category,name_tensor = random_training_pair()
 print('category =',category,'/ name =',name)

上述代码块运行结果

 category = Vietnamese / name = Truong
 category = Arabic / name = Malouf
 category = German / name = Messner
 category = Arabic / name = Boulos
 category = English / name = Batchelor
 category = Spanish / name = Guerrero
 category = Italian / name = Monti
 category = Scottish / name = Thomson
 category = Irish / name = Connell
 category = Korean / name = Youn

训练RNN网络

我们使用 nn.CrossEntropyLoss 作为评判标准,来检验 姓名真实所属的语言truth 与 预测该姓名得到预测所属语言类别predict 比对,计算RNN网络训练的误差。

criterion = nn.CrossEntropyLoss()

我们也创建了 优化器optimizer , 常用的优化器是 SGD算法 。当 每次训练网络,我们比对结果,好则改之,无则加勉, 让该网络改善的学习率learning rate(改进的速度)设置为0.005 。

注意学习率learning rate不能设置的太大或者太小:

learning_rate = 0.005 
optimizer = torch.optim.SGD(rnn.parameters(),#给优化器传入rnn网络参数
 lr=learning_rate) #学习率

每轮训练将:

def train(category_tensor,name_tensor):
 rnn.zero_grad() #将rnn网络梯度清零
 hidden = rnn.init_hidden() #只对姓名的第一字母构建起hidden参数
 #对姓名的每一个字母逐次学习规律。每次循环的得到的hidden参数传入下次rnn网络中
 for i in range(name_tensor.size()[0]):
 output,hidden = rnn(name_tensor[i],hidden)
 #比较最终输出结果与 该姓名真实所属语言,计算训练误差
 loss = criterion(output,category_tensor)
 #将比较后的结果反向传播给整个网络
 loss.backward()
 #调整网络参数。有则改之无则加勉
 optimizer.step()
 #返回预测结果 和 训练误差
 return output,loss.data[0]

现在我们可以使用一大堆姓名和语言数据来训练RNN网络,因为 train函数 会同时返回 预测结果 和 训练误差 , 我们可以打印并可视化这些信息。

为了方便,我们每训练5000次(5000个姓名),就打印 一个姓名的预测结果 ,并 查看该姓名是否预测正确 。

我们对每1000次的训练累计误差,最终将误差 可视化出来。

import time
import math
n_epochs = 100000 # 训练100000次(可重复的从数据集中抽取100000姓名)
print_every = 5000 #每训练5000次,打印一次
plot_every = 1000 #每训练1000次,计算一次训练平均误差
current_loss = 0 #初始误差为0
all_losses = [] #记录平均误差
def time_since(since):
 #计算训练使用的时间
 Now = time.time()
 s = Now - since
 m = math.floor(s / 60)
 s -= m * 60
 return '%dm %ds' % (m,s)
#训练开始时间点
start = time.time()
for epoch in range(1,n_epochs + 1):
 # 随机获取训练数据name和对应的language
 category,name_tensor = random_training_pair()
 output,loss = train(category_tensor,name_tensor)
 current_loss += loss
 #每训练5000次,预测一个姓名,并打印预测情况
 if epoch % print_every == 0:
 guess,guess_i = category_from_output(output)
 correct = '?' if guess == category else '? (%s)' % category
 print('%d %d%% (%s) %.4f %s / %s %s' % (epoch,epoch / n_epochs * 100,time_since(start),loss,guess,correct))
 # 每训练5000次,计算一个训练平均误差,方便后面可视化误差曲线图
 if epoch % plot_every == 0:
 all_losses.append(current_loss / plot_every)
 current_loss = 0

上面代码块运行结果

 5000 5% (0m 8s) 1.6642 San / Chinese ? (Korean)
 10000 10% (0m 15s) 3.1045 Sobol / Arabic ? (Polish)
 15000 15% (0m 23s) 2.9460 Hill / Vietnamese ? (Scottish)
 20000 20% (0m 30s) 1.3255 Uemura / Japanese ?
 25000 25% (0m 37s) 0.0889 Antonopoulos / Greek ?
 30000 30% (0m 45s) 2.0578 Keighley / Russian ? (English)
 35000 35% (0m 53s) 3.4646 Gaspar / Arabic ? (Spanish)
 40000 40% (1m 1s) 2.6537 Soto / Japanese ? (Spanish)
 45000 45% (1m 8s) 0.7883 Lykoshin / Russian ?
 50000 50% (1m 17s) 3.1190 Blau / Vietnamese ? (German)
 55000 55% (1m 26s) 1.4374 Sacco / Portuguese ? (Italian)
 60000 60% (1m 33s) 0.0793 O'Boyle / Irish ?
 65000 65% (1m 41s) 1.0468 Kong / Chinese ?
 70000 70% (1m 47s) 0.6785 Davidson / Scottish ?
 75000 75% (1m 55s) 3.3509 Serafin / Irish ? (Polish)
 80000 80% (2m 2s) 0.1848 Portelli / Italian ?
 85000 85% (2m 8s) 1.0430 Gabrisova / Czech ?
 90000 90% (2m 15s) 1.3065 Loyola / Czech ? (Spanish)
 95000 95% (2m 22s) 0.2379 Coelho / Portuguese ?
 100000 100% (2m 29s) 0.3560 Teng / Chinese ?

绘制训练误差

import matplotlib.pyplot as plt
%matplotlib inline
plt.figure()
plt.plot(all_losses)

Python深度学习实战!全头条会的不超过一只手吧!不吹不黑!

从误差图中可以看出,随着训练轮数的增加,模型的每1000次训练的平均误差越来越小。

手动检验训练的模型

为了方便,我们定义了 predict(rnn,input_name,n_predictions=3)函数

def predict(rnn,n_predictions=3):
 hidden = rnn.init_hidden()
 #name_tensor.size()[0] 名字的长度(字母的数目)
 for i in range(name_tensor.size()[0]):
 output,hidden)
 print('
> %s' % input_name)
 # 得到该姓名预测结果中似然值中前n_predictions大的 似然值和所属语言
 topv,topi = output.data.topk(n_predictions,True)
 predictions = []
 for i in range(n_predictions):
 value = topv[0][i]
 category_index = topi[0][i]
 print('(%.2f) %s' % (value,all_categories[category_index]))
 predictions.append([value,all_categories[category_index]])
predict(rnn,'Dovesky')
predict(rnn,'Jackson')
predict(rnn,'Satoshi')

上述代码块运行结果

Python深度学习实战!全头条会的不超过一只手吧!不吹不黑!

思考Exercises

比照本文,我们还可做很多类似的训练,比如

为了得到更准确的神经网络(更准确):

总结

以上是编程之家为你收集整理的Python深度学习实战!全头条会的不超过一只手吧!不吹不黑!全部内容,希望文章能够帮你解决Python深度学习实战!全头条会的不超过一只手吧!不吹不黑!所遇到的程序开发问题。


如果您也喜欢它,动动您的小指点个赞吧

除非注明,文章均由 laddyq.com 整理发布,欢迎转载。

转载请注明:
链接:http://laddyq.com
来源:laddyq.com
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。


联系我
置顶