LSTM网络结构

参考资料:(都写的很好!!!推!!!)

理解 LSTM 网络 - 简书

深度解析深度学习中的长短期记忆网络(LSTM)(含代码实现)_lstm 代码实现-CSDN博客

https://zhuanlan.zhihu.com/p/36101196 

https://www.zhihu.com/question/34878706

RNN存在的问题:

当两个相关的词的间隔不断增大时,RNN 会丧失学习到连接如此远的信息的能力。在理论上,RNN 绝对可以处理这样的 长期依赖 问题,但在实践中,RNN 肯定不能够成功学习到这些知识。除此之外,当RNN也存在梯度消失和爆炸的问题。

LSTM网络:

 

LSTM 的关键就是细胞状态,它直接在整个链上运行,只有一些少量的线性交互。信息在上面流传保持不变会很容易。

所以可以看见C状态改变的慢一点,Ct是在Ct-1的基础上加了些什么。

从这里可以来说一下梯度消失的问题,LSTM是RNN的改进版,它改进了共享的神经网络模块,引入了cell模块,同时把RNN里面的连乘符合改成了连加操作。所以这里的梯度流是最稳定,但是在其它路径里,梯度消失和爆炸依然是存在的。

总的远距离梯度 = 各条路径的远距离梯度之和,即便其他远距离路径梯度消失了,只要保证有一条远距离路径(就是上面说的那条高速公路)梯度不消失,总的远距离梯度就不会消失(正常梯度 + 消失梯度= 正常梯度)。因此 LSTM 通过改善一条路径上的梯度问题拯救了总体的远距离梯度消失。但同样的,对于梯度爆炸:总的远距离梯度 = 正常梯度 + 爆炸梯度 = 爆炸梯度,因此 LSTM 仍然有可能发生梯度爆炸。不过,由于 LSTM 的其他路径非常崎岖,和普通 RNN 相比多经过了很多激活函数(导数都小于 1),因此 LSTM 发生梯度爆炸的频率要低得多。实践中梯度爆炸一般通过梯度裁剪来解决。

LSTM的三个门:

遗忘门:决定丢弃什么信息。

LSTM 中的第一步是决定我们会从细胞状态中丢弃什么信息。遗忘门读取ht-1和xt,输出一个在0到1之间的数值给每个在细胞状态Ct-1中的数字,1表示完全保留,0表示完全舍弃。

输入门:确定更新的信息

这里有两个部分,sigmoid层称 “输入门层” 决定什么值我们将要更新。然后,一个 tanh 层创建一个新的候选值向量,然后C~t会被加入到状态中。

然后把旧状态与 ft 相乘,丢弃掉我们确定需要丢弃的信息。接着加上 it*c~t ,所以有了新的传递值。

输出门:确定输出什么值

输出将会基于我们的细胞状态,但是也是一个过滤后的版本。首先,我们运行一个 sigmoid 层来确定细胞状态的哪个部分将输出出去。接着,我们把细胞状态通过 tanh 进行处理(得到一个在-1到1之间的值)并将它和 sigmoid 门的输出相乘,最终我们仅仅会输出我们确定输出的那部分。

激活函数:

sigmoid函数:

tanh激活函数:

它和sigmoid相比:

  • 在靠近0处的导数值较sigmoid更大,即神经网络的收敛速度相对于sigmoid更快;在一般的分类问题中,可将tanh用于隐藏层,sigmoid 函数用于输出层。
  • tanh导数范围在(0, 1)之间,相比sigmoid导数的范围(0, 0.25),梯度消失问题会得到缓解,但仍然存在。

使用pytorch实现一个简单的LSTM模型:

import torch
import torch.nn as nn
import torch.optim as optim
import numpy as np

class LSTMModel(nn.Module):
  def __init__(self,input_size,hidden_size,num_layers,output_size):
    super(LSTMModel,self).__init__()
    self.hidden_size = hidden_size
    self.num_layers = num_layers
    self.lstm = nn.LSTM(input_size,hidden_size,num_layers,batch_first = True)#batch_first也就是指在input的维度顺序是(batch_size,seq_len,input_size)
    self.fc = nn.Linear(hidden_size,output_size)

  def forward(self,x):
    h0 = torch.zeros(self.num_layers, x.size(0), self.hidden_size)#(层数,batch,隐藏层大小)
    print(h0.size())
    c0 = torch.zeros(self.num_layers, x.size(0), self.hidden_size)
    out,(_,_) = self.lstm(x,(h0,c0))
    out = self.fc(out[:,-1, :])
    return out

inputs = new_inputs = torch.randn(3,5,1,dtype=torch.float) #(batch_size,seq_len,input_size)
labels = torch.tensor([0,1,1])

input_size = 1 #表示一个单词只用一个向量表示
hidden_size = 64
num_layers = 1
output_size = 2

model = LSTMModel(input_size,hidden_size,num_layers,output_size)
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)

num_epochs = 5
for epoch in range(num_epochs):
  outputs = model(inputs)
  loss = criterion(outputs,labels)

  #模型参数更新
  optimizer.zero_grad()
  loss.backward()
  optimizer.step()

只迭代了5次的结果:

outputs = model(new_inputs)
print(outputs)
predicted = torch.argmax(outputs,dim = 1)#这个dim = 1 指的是按行来找最大值,dim = 0 是按列来找
print(predicted)


#输出
tensor([[-0.1003,  0.0417],
        [-0.1050,  0.0573],
        [-0.1077,  0.0854]], grad_fn=<AddmmBackward0>)
tensor([1, 1, 1])

  • 16
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值