『RNN』简单RNN到LSTM

本打算详细梳理下RNN这块的内容,但是看都下面这篇博客写的很好,就拿来细细阅读,并且多不理解的地方做出补充,同时加上代码进一步深入理解。

首先感谢博主:

https://blog.csdn.net/zhaojc1995/article/details/80572098

一.补充

1.RNN

在这里插入图片描述

  • 大项目中可能RNN和CNN共同存在。

2.LSTM

在这里插入图片描述

  • 细胞状态的改变只做线性运算。加分(增加信息)和乘法(去除信息)。

  • 更新之前细胞状态( 遗忘门 ):选择性通过信息。 softmax函数输出范围再0-1之间,不为0或者1。

  • 更新当前特征量(输入门): sigmoid函数 取值范围在0-1之间,tanh激活层与RNN一样,只有唯一的激活。将sigmoid函数得到的结果(0-1)与tanh激活层得到的结果(所有当前得到的特征量)相乘,控制tanh激活层输入细胞状态多少。

  • 输出门:将细胞状态使用tanh激活,得到当前状态,再使用sigmoid函数激活,表示当前输出多少。结果做当前输出和传给t+1时刻两种。

在这里插入图片描述

  • 乘法:忘掉细胞状态。
  • 加法:输入/更新细胞状态。
  • sigmoid函数选择更新内容,tanh函数创建更新候选。

3.变种

(1)GRU

  • 没有细胞状态,参数比普通LSTM网络少1/3(筛选越多,参数越少),计算更快。效果与LSTM差不多。广泛使用。
  • 只筛选了两次。

在这里插入图片描述

(2)SRU

  • 细胞状态没有激活,输出有激活。

在这里插入图片描述
在这里插入图片描述

(3)双向LSTM

在这里插入图片描述

二.LSTM代码理解

使用RNN识别MNIST数据集。

  • 图片大小:28x28。
  • CNN结构:NCHW
  • 全连接:NV。
  • RNN结构:NSV。
  • 将28x28的图片分为28步(如下图),所以向量为28,步长为1,需要28步。通道放到批次上,将N变大。

在这里插入图片描述

  • 从第一部往后走。后边一步代表前面所有步。

  • 输入大小28x28,通过权重变成128或者256个特征。

  • NSV:100,28,28。

  • (28,28)x(28,128)(权重)–>(28x128)。即,(28个步长,第一竖列28个像素)x(28x128)的权重,得到(28x128),这里的128代表第一竖列28个像素值。最后特征还是为128维度。并且将128变为10进行计算。神经网络简易图如下所示:
    在这里插入图片描述

  • LSTM原始API:

class RNNBase(Module):
    __constants__ = ['mode', 'input_size', 'hidden_size', 'num_layers', 'bias',
                     'batch_first', 'dropout', 'bidirectional']

    def __init__(self, mode, input_size, hidden_size,
                 num_layers=1, bias=True, batch_first=False,
                 dropout=0., bidirectional=False):
        super(RNNBase, self).__init__()
  • LSTM使用
    def __init__(self):
        super(Net, self).__init__()
        # nn.GRU()
        # nn.LSTMCell()
        self.lstm = nn.LSTM(
            input_size=28,#一个步长,28个特征点。
            hidden_size=128,#隐藏层128。
            num_layers=2,#LSTM做几次,层数越多,权重越多,更新起来越慢。一般双向用两层。单项用一层和两层没多大区别。
            batch_first=True,#是否将批次加到第一维。一般的,如果不把批次放到第一维,会跑到第二维,变成(S,N,V)。通常为True
            bidirectional=True#是否为双向。双向时,特征值增加一倍,变为128x2.
        )
        # self.out = nn.Linear(128, 10)
        self.out = nn.Linear(128*2, 10)
  • LSTM前向传播
    def forward(self, x):
        r_out, (h_t,c_t) = self.lstm(x, None)#r_out:(28,128);h_t:隐藏层的输出;c_t:细胞状态。每一步,h_t,c_t形状一样,一般不用,但是要输出,给个占位符。
        out = self.out(r_out[:, -1, :])#切片:N和V维度不变,S取最后一步,即,取第28步,拿到(100,128)。再乘以(128,10)(即self.out())变成(100,10)。r_out形状为(100,28,128),输出最后一步形状变为(100,128).其中,100为批次。(100,128)x(128,10)-->(100,10)
        return out
发布了29 篇原创文章 · 获赞 45 · 访问量 5037

猜你喜欢

转载自blog.csdn.net/sinat_39783664/article/details/104554675