文章目录
- 0 前言
- 0.1 课程视频链接:
- 0.2 课件下载地址:
- 1 本节课任务描述
- 模型的处理过程
- 训练循环
- 初始化分类器
- 是否使用GPU
- 构造损失函数和优化器
- 每个epoch所要花费的时间
- 遍历每个epoch时进行训练和测试
- 记录每次测试的准确率加入到列表中
- 具体实现(经典的4步)
- 1、准备数据
- 1.1 输入数据的处理
- 1.2 输出数据的处理
- 1.2.1 编写数据集类
- 1.2.2 实例化数据集类并加载DataLoader
- 2、设计模型
- Bi-direction RNN/LSTM/GRU的实现
- 将name转换为tensor
- 实现-测试
- 实现-训练模型的结果展示
- 练习13-1 电影评论的情感分析
- 本系列的总结
0 前言
0.1 课程视频链接:
《PyTorch深度学习实践》完结合集
大佬的笔记:大佬的笔记
pytorch=0.4
0.2 课件下载地址:
链接:https://pan.baidu.com/s/1_J1f5VSyYl-Jj2qIuc1pXw
提取码:wyhu
1 本节课任务描述
本节将构建一个RNN来做分类
具体是名字的分类
复习RNN
嵌入层负责将词的one-hot表示(高维稀疏)映射到一个低维稠密的向量中
隐层的h不一定和输出一致,因此需要添加一个线性层,把输出映射成和要求一致的
有些任务是不需要对所有的隐层状态h都做线性映射的,比如本节的目标是让RNN最后的输出是一个分类,对o1,o2,o3,o4是没有要求的,
实际上可以让网络简化为下面(分类结果只与最后一个隐藏状态相关):
具体如下:
每个名字中的字母就是序列中的x1,x2,。。。
序列有的长有的短,之后还要解决序列长度不一的情况
模型的处理过程
训练循环
初始化分类器
RNNClassifier是自己定义的分类模型
N_CHARS:字符的数量
HIDDEN_SIZE:GRU输出的维度
N_COUNTRY:国籍的类别数量
N_LAYER:GRU的层数
是否使用GPU
构造损失函数和优化器
分类问题使用交叉熵损失函数
每个epoch所要花费的时间
elapsed:消逝
这里定义的time_since函数将当前时间减去since时间,再转换成分钟
遍历每个epoch时进行训练和测试
记录每次测试的准确率加入到列表中
记录到列表中后便于之后画图查看准确率变化情况
具体实现(经典的4步)
1、准备数据
1.1 输入数据的处理
77是M的ASCII值,M的one-hot表示则为索引为77的那一位为1,其余值为0的向量
长短不一:使用padding进行扩充
RNN的输入需要保证是张量,不进行padding的话不是矩阵
填充的长度为一个batch中最长的那个单词的字符数
1.2 输出数据的处理
1.2.1 编写数据集类
将所有的国家名字做成一个词典,给每个国家一个索引值,字典的格式为键为国家名,值为索引值
is_train_set=True:判断文件是否是训练集
使用了gzip和csv这两个包进行读取数据集,如果数据集的文件格式是pickle或者是HD5格式,此时需要用相应的包进行读取,需随机应变
rows是一个列表,这个列表中每一个元素都是元组(name,name所归属的国家)
此时name是一个字符串,国家是一个索引值
len:返回数据集的长度
函数getCountryDict()可以将国家与国家对应的索引值做出来,其中国家名为键,索引为值
其他的工具函数:
idx2country():给一个索引需要将国家这个字符串拿出来
getCountriesNum():返回国家的数量
1.2.2 实例化数据集类并加载DataLoader
参数配置:
2、设计模型
隐藏层的维度设置
Embedding层的维度设置
GRU的输入维度是hidden_size,输出维度也是hidden_size
bidirectional是设置这个GRU网络是否是双向的,如果为True则为双向,如果为False则为单向
设置n_directions值,如果bidirectional值为True则n_directions=2,否则n_directions=1
Bi-direction RNN/LSTM/GRU的实现
x_N-1只包含了前面的词的影响,也应该考虑后面的词的影响
下面的图中h0f中的f意思是序列的前向处理,h0b中的b就是序列的反向处理,将正向和反向的信息进行拼接
双向的GRU的输出信息包含两种内容:output和hidden
out包含h0,h1,…,hN
hidden只包含hNb和hNf
这里的hidden_size*self.n_directions是指隐藏层h维度是拼接起来的,所以需要乘以一个层数
_init_hidden是隐层的初始化,初始设置为一个全是0的张量
n_directions是指方向的个数,如果值为2,则为双向,如果值为1则为单项
n_linear是指网络的层数
.t():是张量的转置
转置之后的结果:
对序列长度不一的数据进行padding0的操作,0在实际计算的时候其实不需要参与计算,不计算的话可以提高神经网络的运算速度
在pytorch中的一个函数是pack_padded_sequence()
,这个函数就可以实现上面的功能,它需要Embedding和序列长度seq_lengths,这个函数的工作原理如下:
左侧的每个字都会变成一个向量,如上红色画出的部分,像padding的0都是映射为同一个向量,如下图右侧深色部分,如果显示不是0.11开头,那是up主写错了,所以他在图中标识出来了
Embeddin函数会将左边的图片变成右边的方块(seqLen,batchsize,hiddensize),如下
pack_padded_sequence()
会返回一个打包的对象,
这个对象的文档解释:
看不懂的话看下面:
在处理长短不一的情况下,需要将0对应的词向量拿出去不参与计算,把非0的词向量给依次的堆叠在一起,等于说是一个这样的筛选工作,如果没有按照非0词的个数进行排列的话,pack_padded_sequence是不能work的
但是pack_padded_sequence
这个函数要求按照非0个数进行排列,人话讲就是按照句子中词的多少来排序这个词向量,见下图:
首先需要按照序列长度进行排序
排序映射为向量:
之后按照下面的排序顺序进行排列,中间省去了两个满的,下面的10,10,10,9,6,表示左边那个图一横行有多少个非padding0的词向量,应该是up主写错了,应该写成9,9,9,8,5,数错了应该是
pack_padded_sequence将上图中的data
和seq_length
两个数据进行打包,其中seq_length会变成batch_sizes,即data和batch_sizes将作为gru的输入,gru会根据batch_sizes中存储的数字来每次从data中取出来多少的向量
通过上面的操作得到了下面gru的输入:gru_input
之后将gru_input作为输入得到最终的hidden,如果是双向GRU的话hidden如下:
hidden[-1]:GRU的最后一个隐藏层状态
hidden[-2]:GRU的倒数第二个隐藏层状态,
之后再将hidden放进全连接层,转换为想要的那种维度
不懂可以再看下单层的GRU结构:
双向的GRU的hidden如下操作:
如果使用的是双向的GRU,则需要将前向和后向的hidden进行拼接
最后使用一个全连接网络
将name转换为tensor
这个过程的最终结果需要得出3个值,一个batch的大小B,一个每个name的向量长度S,一个是每个name的向量表示中非0元素的个数,
过程:
字符串—>字符—>ASCII码—>填充—>转置—>排序
字符串—>字符—>ASCII码:
ASCII码—>填充:
填充—>转置:
转置—>排序:
name2list将名字name中的每个字符转成ASCII值
序列长度装成longtensor:
padding0的操作:先创造一个全是0的张量,然后将非0的张量给贴到0张量上
排序
将这三个都转为张量
一个epoch上进行训练训练
经典5步骤:
打印输出:
实现-测试
测试时不需要求梯度,因此使用with torch.no_grad():
计算输出:
output.max()这里是计算预测对了多少
实现-训练模型的结果展示
大概20个epoch之后模型在测试集上的效果表现最好,此时可以将模型保存下来
练习13-1 电影评论的情感分析
数据集下载地址:kaggle
数据示例展示
最后一列的数字表示这句话的情感分类
本系列的总结
1、通读pytorch文档
2、多读新的文献
3、多动手写代码
文章看不懂或者视频看不懂的可以参考以下优秀的博文:
1、【Pytorch深度学习实践】B站up刘二大人课程笔记——目录与索引(已完结)(该博主的博文建议多看看)
2、玩一玩 Typora
3、刘二大人《PyTorch深度学习实践》循环神经网络RNN高级篇