0
点赞
收藏
分享

微信扫一扫

深度学习之 12 循环神经网络RNN 3

本文是接着上一篇深度学习之 12 循环神经网络RNN2_水w的博客-CSDN博客

目录

序列数据处理

1 基本处理

◼ 固定长度滑动窗口

◼ 数据集划分注意事项

◼ 数据集划分示例代码

2 高级处理

◼ 序列重采样

◼ 序列插分

◼ 固定时间跨度滑动窗口

◼ 不等长序列填充&打包

3 面向对象的数据集构造

◼ 数据读取与标准化

 ◼ 逆标准化函数

◼ 数据集的构建

循环神经网络

1 基本原理

2 动手实现

◼ 模型实现 – 定义和初始化参数 

◼ 隐状态更新

◼ 数据读取

◼模型训练

 ◼ eval()函数

◼ 测试函数:把模型切成测试模式,

◼ 可视化函数:使用PIL

◼ 训练结果可视化

3 torch.nn.RNN

◼ 训练结果可视化

长短期记忆网络

1 基本原理

2 动手实现

◼ 模型实现 – 初始化参数

◼ 模型实现

◼ 优化模型实现思路

◼ 优化模型实现

◼ 训练结果可视化

3 torch.nn.LSTM

​编辑

◼ 训练结果可视化

​编辑

门控循环单元

1 基本原理

2 动手实现

◼ 模型实现(优化后)

◼ 训练结果可视化

3 torch.nn.GRU

 ◼ 训练结果可视化​编辑

4 RNN的一些应用 

 ◼ 序列到类别

 ◼ 序列到序列

 ◼ 写字、作诗

 ◼  看图说话


序列数据处理

(1)序列数据:

 (2)读取数据,

 (3)

1 基本处理

固定长度滑动窗口

 

切分之前,只有一条长度为720的长序列。经过切分之后,就变成了709条长度是12的短序列。这样既给我们提供了足够多的样本供模型学习,而且同时也减少了序列的长度,方便我们构造模型。

数据集划分注意事项

这么做的主要的这个目的就是为了避免交叉,因为我们的划窗操作它是每次向后走一个元素,每次向后滑长度为1,那这样就必然会造成后一个滑窗和前一个滑窗是存在一些交叉部分的,如果说先对整个所有的长序列进行了一个滑窗。那再去对这些得到的短序列进行划分的时候,必然会产生我验证级当中一部分的特征,其实在训练集当中已经出现过了。

当然咱们既然是滑窗,不可能完全出现,但你出现过一部分了。那这其实产生了一种交叉,出现了一种特征层面的数据泄露。那这样其实是我们不希望看到的。这样划分出来验证集和测试集并不能很好的去衡量模型的泛化能力。

所以说我们要一定要先把长序列给切分好,按照训练集,验证集,测试集切分好,然后再在各自内部进行划窗。

数据集划分示例代码

先对这个长序列进行索引,取出这个三条。短序列分别作为 训练集,验证集,测试集,然后我再对它们各自进行一个划窗。所以说这个先后顺序,大家一定要把握好,绝对不能说我先划窗生成短序列,再划分,那这样就会产生重叠。

高级处理

序列重采样

作为一个时间序列,它很有可能出现那种情况,就是在时间戳上它是不连续的。那这个时候我们可以对它进行 重采样和差分。

①序列重采样

重采样的操作:首先在时间戳序列上,对它进行一个补齐。那这个时候我们具体的做法呢?用到了几个稍微那个可能复杂一点儿的操作,比如我们要把这个时间出维度,把它转化成这个date time,这个形式。这是一种数据类型。哈date time型,然后把它要设为索引。

序列插分

固定时间跨度滑动窗口

这个长序列,我对它进行这个固定时间窗口滑动之后,它得到的短序列,其实长度是不一样的。因为在那个时间维度上,它的分布是不均匀的。所以我固定时间窗口去对它进行滑动,得到短序列,也是完全有可能不等长的。

不等长序列填充&打包

我们知道不管是porch还是tensor它处理的数据必须是一个向量,或者是方阵。除了说像刚才我们提到说固定时间窗口滑动可能产生这种不等长序列,其实大家在这个真正今后的科研过程当中很大概率会遇到这种各个样本之间,它长度就是不一样。那这个时候我们怎么办?

我们首先要做的第一步呢,是将它填充这个填充的本质就是一个padding操作补零。

但是它是不知道你哪些数字是你自己补上去的,哪些是真实有效的数字的?如果你要是直接把它往里放的话,它会认为比如说这个第三条序列。它会认为后四个0也是要学习的东西,那这个就可能很大程度上会影响模型的学习,那这个时候我们怎么办呢?

我们需要把这种padded后的数据,进行一个打包,吧padded_seq序列传入函数,同时还得 需要统计并输入每条序列的长度 ,告诉函数真实长度。

3 面向对象的数据集构造

数据读取与标准化

通过使用面向对象的方法可以将读取、标准化、重采样、差分等一系列对数据的处理封装起来, 提高代码可用性。

最后我们在这里做了一个数据标准化。那么这个数据标准化其实就是我们此次要使用面向对象最关键的一个点。因为我们使用了面向对象,我们就可以通过这种类内的这个变量去存储我当前数据集的最大和最小值情况,这样我们对它进行标准化之后,我们在后边是可以对它进行一个逆标准化的。

 ◼ 逆标准化函数

数据集的构建

得到datasets之后,放入dataloader 进行数据的迭代输出就可以了。

循环神经网络

基本原理

2 动手实现

模型实现 – 定义和初始化参数 

定义一个继承字model类的类。在里边定义好我所有要使用的参数以及隐藏层的激活函数,以及输出层的激活函数,drab函数是否要定义大家可以自行决定。

◼ 隐状态更新

forward函数这里注意,跟之前的网络有一点不一样。定义了一个for循环,长度是整个序列的长度。对于序列中的每一个位置进行x和h的计算。 

对整个序列来说,RNN的每一个单元处理序列,每一个位置的每一个单元,它的W和B实际上是共享的。就Wh, Uh, Bh。在整个序列上其实是共享的。

那这个时候大家要引起重视,这个RNN它并不是说我去初始化一个和序列一样长的模型,不是的。我是初始化了一个单元,这个单元在整个序列上滑动。相当于是我定义了一个前馈神经网络,沿着数据沿着我这个数据的序列。去做这样一步一步的输出的。这个本质它底层是有一个参数共享的机制。

 返回的是最后一步的隐藏层和所有Y的输出。

◼ 数据读取

得到3个数据集, 

模型训练

调用训练函数, 

 ◼ eval()函数

 测试函数:把模型切成测试模式,

在测试过程中,不使用droupout。如果还测试过程中继续使用droupout可能会影响模型的表现。在训练过程中使用droupout,相当于进行正则化提升模型的泛化能力。

 可视化函数:使用PIL

两个函数:一个可以用来画loss,一个可以用来画各个指标。 

◼ 训练结果可视化

torch.nn.RNN

 

 把batch_first置为true。

单独定义输出层之后,得保证它和RNN的承诺书是一起学习的,此时我们就把它们各自的参数用list相加的形式,放到adam优化器中去。这样我们在做梯度下降和优化的时候就可以一起优化了。

◼ 训练结果可视化

长短期记忆网络

1 基本原理

2 动手实现

◼ 模型实现 – 初始化参数

对当前状态,对当前输入和上一时刻隐藏层的计算做了4次线性操作加激活函数。最终得到的是一个输出门权重,遗忘门权重,以及候选细胞状态。

◼ 模型实现

 如果没有GPU,那么模型跑起来非常慢。

◼ 优化模型实现思路

1)各门控计算优化,以遗忘门为例:

 2)所有门控一起合并计算:

◼ 优化模型实现

◼ 训练结果可视化

3 torch.nn.LSTM

 

◼ 训练结果可视化

门控循环单元

1 基本原理

 

2 动手实现

◼ 模型实现(优化后)

◼ 训练结果可视化

时间效率上和预测准确率的区别。

torch.nn.GRU

 

 ◼ 训练结果可视化

4 RNN的一些应用 

 ◼ 序列到类别

 ◼ 序列到序列

 ◼ 写字、作诗

 ◼  看图说话

举报

相关推荐

0 条评论