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

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深度学习实战!全头条会的不超过一只手吧!不吹不黑!

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

  • input : 输入的数据
  • hidden : 神经网络现有的参数矩阵
  • combined : input矩阵与hidden矩阵合并,两个矩阵的行数一致,input和hidden分布位于新矩阵的 左侧和右侧
  • i2o :对输入的数据转化为output的计算过程
  • 12h :将输入的数据转化为hidden参数的计算过程
  • output :当前网络的输出
  • hidden :当前网络传递给下层网络的参数

大家仔细看看琢磨琢磨这个图构造。现在我们先看看 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,各个参数解读:

  • input_size : 表征字母的向量的特征数量(向量长度)
  • hidden_size : 隐藏层特征数量(列数)
  • output_size : 语言数目,18
  • i2h : 隐藏网络参数的计算过程。输入的数据尺寸为 input_size + hidden_size,输出的尺寸为 hidden_size
  • i2o : 输出网络参数的计算过程。输入的数据尺寸为 input_size + hidden_size,输出的尺寸为 output_size
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(在我们的例子中,是当前字母的Tensor)
  • hidden(我们首先将隐藏层参数初始化为零)

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

  • output(每种语言的可能性的大小)
  • next_hidden(传递给下一个网络的隐藏状态hidden)
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中的含有数据,想办法从中提取出预测的 语言类别信息 。

具体思路:

  1. 因为output是tensor,我们可以先获取这个tensor中的data
  2. 再使用基于data的topk方法提取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 。

函数输入:

  • output : RNN网络输出的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: 语言名
  • 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) #学习率

每轮训练将:

  • 创建input(name_tensor)和 input对应的语言类别标签(category_tensor)
  • 当输入姓名第一个字母时,需要初始化隐藏层参数。
  • 读取姓名中的 每个字母的数组信息 ,传入rnn,并将网络输出的hidden_state和下一个字母数组信息传入之后的RNN网络中
  • 使用criterion比对 最终输出结果 与 姓名真实所属的语言标签 作比较
  • 更新网络参数,改进网络。
  • 循环往复以上几步
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)函数

  • rnn: 训练得到的rnn网络
  • input_name: 姓名字符串
  • n_predictions:该姓名预测结果的前n_predictions个预测结果
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

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

  • 根据任意词汇 -> 所属语言
  • 根据名字 -> 名字的性别
  • 文章标题 -> 文章所属话题

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

  • 添加更多层Add more linear layers
  • 尝试使用 nn.LSTM 或者 nn.GRU
  • 聚合多种(如rnn、lstm、gru)为更高级的网络

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


我最近重新拾起了计算机视觉,借助Python的opencv还有face_recognition库写了个简单的图像识别demo,额外定制了一些内容,原本想打包成exe然后发给朋友,不过在这当中遇到了许多小问题,都解决了,记录一下踩过的坑。 1、Pyinstaller打包过程当中出现warning,跟d
说到Pooling,相信学习过CNN的朋友们都不会感到陌生。Pooling在中文当中的意思是“池化”,在神经网络当中非常常见,通常用的比较多的一种是Max Pooling,具体操作如下图: 结合图像理解,相信你也会大概明白其中的本意。不过Pooling并不是只可以选取2x2的窗口大小,即便是3x3,
记得大一学Python的时候,有一个题目是判断一个数是否是复数。当时觉得比较复杂不好写,就琢磨了一个偷懒的好办法,用异常处理的手段便可以大大程度帮助你简短代码(偷懒)。以下是判断整数和复数的两段小代码: 相信看到这里,你也有所顿悟,能拓展出更多有意思的方法~
文章目录 3 直方图Histogramplot1. 基本直方图的绘制 Basic histogram2. 数据分布与密度信息显示 Control rug and density on seaborn histogram3. 带箱形图的直方图 Histogram with a boxplot on t
文章目录 5 小提琴图Violinplot1. 基础小提琴图绘制 Basic violinplot2. 小提琴图样式自定义 Custom seaborn violinplot3. 小提琴图颜色自定义 Control color of seaborn violinplot4. 分组小提琴图 Group
文章目录 4 核密度图Densityplot1. 基础核密度图绘制 Basic density plot2. 核密度图的区间控制 Control bandwidth of density plot3. 多个变量的核密度图绘制 Density plot of several variables4. 边
首先 import tensorflow as tf tf.argmax(tenso,n)函数会返回tensor中参数指定的维度中的最大值的索引或者向量。当tensor为矩阵返回向量,tensor为向量返回索引号。其中n表示具体参数的维度。 以实际例子为说明: import tensorflow a
seaborn学习笔记章节 seaborn是一个基于matplotlib的Python数据可视化库。seaborn是matplotlib的高级封装,可以绘制有吸引力且信息丰富的统计图形。相对于matplotlib,seaborn语法更简洁,两者关系类似于numpy和pandas之间的关系,seabo
Python ConfigParser教程显示了如何使用ConfigParser在Python中使用配置文件。 文章目录 1 介绍1.1 Python ConfigParser读取文件1.2 Python ConfigParser中的节1.3 Python ConfigParser从字符串中读取数据
1. 处理Excel 电子表格笔记(第12章)(代码下载) 本文主要介绍openpyxl 的2.5.12版处理excel电子表格,原书是2.1.4 版,OpenPyXL 团队会经常发布新版本。不过不用担心,新版本应该在相当长的时间内向后兼容。如果你有新版本,想看看它提供了什么新功能,可以查看Open
1. 发送电子邮件和短信笔记(第16章)(代码下载) 1.1 发送电子邮件 简单邮件传输协议(SMTP)是用于发送电子邮件的协议。SMTP 规定电子邮件应该如何格式化、加密、在邮件服务器之间传递,以及在你点击发送后,计算机要处理的所有其他细节。。但是,你并不需要知道这些技术细节,因为Python 的
文章目录 12 绘图实例(4) Drawing example(4)1. Scatterplot with varying point sizes and hues(relplot)2. Scatterplot with categorical variables(swarmplot)3. Scat
文章目录 10 绘图实例(2) Drawing example(2)1. Grouped violinplots with split violins(violinplot)2. Annotated heatmaps(heatmap)3. Hexbin plot with marginal dist
文章目录 9 绘图实例(1) Drawing example(1)1. Anscombe’s quartet(lmplot)2. Color palette choices(barplot)3. Different cubehelix palettes(kdeplot)4. Distribution
Python装饰器教程展示了如何在Python中使用装饰器基本功能。 文章目录 1 使用教程1.1 Python装饰器简单示例1.2 带@符号的Python装饰器1.3 用参数修饰函数1.4 Python装饰器修改数据1.5 Python多层装饰器1.6 Python装饰器计时示例 2 参考 1 使
1. 用GUI 自动化控制键盘和鼠标第18章 (代码下载) pyautogui模块可以向Windows、OS X 和Linux 发送虚拟按键和鼠标点击。根据使用的操作系统,在安装pyautogui之前,可能需要安装一些其他模块。 Windows: 不需要安装其他模块。OS X: sudo pip3
文章目录 生成文件目录结构多图合并找出文件夹中相似图像 生成文件目录结构 生成文件夹或文件的目录结构,并保存结果。可选是否滤除目录,特定文件以及可以设定最大查找文件结构深度。效果如下: root:[z:/] |--a.py |--image | |--cat1.jpg | |--cat2.jpg |
文章目录 VENN DIAGRAM(维恩图)1. 具有2个分组的基本的维恩图 Venn diagram with 2 groups2. 具有3个组的基本维恩图 Venn diagram with 3 groups3. 自定义维恩图 Custom Venn diagram4. 精致的维恩图 Elabo
mxnet60分钟入门Gluon教程代码下载,适合做过深度学习的人使用。入门教程地址: https://beta.mxnet.io/guide/getting-started/crash-course/index.html mxnet安装方法:pip install mxnet 1 在mxnet中使
文章目录 1 安装2 快速入门2.1 基本用法2.2 输出图像格式2.3 图像style设置2.4 属性2.5 子图和聚类 3 实例4 如何进一步使用python graphviz Graphviz是一款能够自动排版的流程图绘图软件。python graphviz则是graphviz的python实