当前位置: 首页 > news >正文

NLP——RNN变体LSTM和GRU

LSTM

一、概念

 LSTM(Long Short-Term Memory)也称长短时记忆结构, 它是传统RNN的变体, 与经典RNN相比能够有效捕捉长序列之间的语义关联, 缓解梯度消失或爆炸现象. 同时LSTM的结构更复杂, 它的核心结构可以分为四个部分去解析:

遗忘门:控制上一个时间步的细胞状态遗忘多少,通过门宽的保留下来

输入门:控制当前时间步的候选记忆( 传统RNN公式得到的结果 )保留多少

细胞状态:存储长期记忆,贯穿计算的全过程

输出门:从当前细胞状态中得到当前隐层输出

这种分工使LSTM既能捕捉长期依赖(如小说伏笔),又能灵活处理局部特征(如对话语气)。

二、LSTM内部结构

计算过程

简单来讲,LSTM一个时间步的计算通过以下几步进行运行:

  1. 遗忘门筛选历史记忆: 决定从长期记忆(细胞状态)选择遗忘丢弃哪些旧信息

    1. 输入:拼接后的参数矩阵[h(t-1), x(t)]

    2. 输出:遗忘门门值f(t)

  2. 输入门吸取新信息:选并整合当前输入中的关键信息生成候选记忆

    1. 输入:拼接后的参数矩阵[h(t-1), x(t)]

    2. 输出:输入门门值i(t),生成候选记忆C~(t) (RNN的计算方式)

  3. 细胞状态更新融合新旧记忆:通过线性叠加更新长期记忆C(t)。

    1. 输入:候选记忆C~(t),遗忘系数 f(t), 上一个时间步的细胞状态C(t-1) , 输入门值i(t)

    2. 输出:长期记忆 C(t)

  4. 输出门生成隐藏状态:控制细胞状态中哪些信息作为当前输出(短期记忆)

    1. 输入:当前时间步的细胞状态 C(t),拼接后的参数矩阵[h(t-1), x(t)]

    2. 输出:输出门门值o(t) (中间变量),短期记忆h(t)

三、代码实现

实例化LSTM是默认参数batch_first=False,

所以构建的输入参数先sequence_length后batch_size;

如果更改参数batch_first=True,则构建的输入参数先batch_size后sequence_length。

# -*- coding: utf-8 -*-
import torch.nn as nn
import torch# 第一个参数:input_size代表输入数据的词嵌入表示维度
# 第二个参数:hidden_size代表隐藏层输出维度
# 第三个参数:num_layers代表隐藏层的个数
lstm = nn.LSTM(input_size=5, hidden_size=6, num_layers=1)# 第一个参数:sequence_length代表输入数据的每个样本的句子长度
# 第二个参数:batch_size代表一个批次几个样本
# 第三个参数:input_size代表输入数据的词嵌入表示维度
input_x = torch.randn(4, 3, 5)# 第一个参数:num_layers代表隐藏层的个数
# 第二个参数:batch_size代表一个批次几个样本
# 第三个参数:hidden_size代表隐藏层输出维度
h0 = torch.randn(1, 3, 6)
c0 = torch.randn(1, 3, 6)output, (hn, cn) = lstm(input_x, (h0, c0))
print(f'output: {output}')
print(f'hn: {hn}')
print(f'cn: {cn}')

四、LSTM优缺点

优点:

LSTM的门结构能够有效减缓长序列问题中可能出现的梯度消失或爆炸, 虽然并不能杜绝这种现象, 但在更长的序列问题上表现优于传统RNN。

缺点:

由于内部结构相对较复杂, 因此训练效率在同等算力下较传统RNN低很多。

五、BI-LSTM

定义: 不改变原始的LSTM模型内部结构,只是将文本从左到右计算一遍,再从右到左计算一遍,把最终的输出结果拼接得到模型的完整输出。

GRU

一、概念

GRU(Gated Recurrent Unit)也称门控循环单元结构, 它也是传统RNN的变体, 同LSTM一样能够有效捕捉长序列之间的语义关联, 缓解梯度消失或爆炸现象. 同时它的结构和计算要比LSTM更简单, 它的核心结构可以分为两个部分去解析:

更新门:

作用:决定当前时刻的隐藏状态需要保留多少上一时刻的隐藏状态信息,以及吸收多少新的候选隐藏状态信息。(类似于LSTM中的“输入门”和“遗忘门”的结合,但更高效)

门值越趋近于1,保留上一时间步信息越多;越趋近于0,表示更新的越多,采用当前状态越多。

重置门:

作用:控制上一时刻的隐藏状态对当前候选隐藏状态的影响程度。(决定是否“忽略”过去的信息,以便更好地捕捉短期依赖)

门值越趋近于1,表示将上一时刻状态与当前输入结合生成候选状态;门值越趋近0,忽略上一时刻状态越多,候选状态更依赖当前输入。

二、GRU内部结构

1. 计算更新门和重置门的门值

        更新门值        z_{t}=\sigma \left ( W_{z}\cdot \left [ h_{t-1},x_{t} \right ] \right )

        重置门值        r_{t}=\sigma \left ( W_{r}\cdot \left [ h_{t-1},x_{t} \right ] \right )

2. 然后重置门值作用在h(t-1)上,控制上一时间步的输入保留下多少(作用类似遗忘门),再用留下的部分进行基本RNN运算(与x(t)拼接进行线性变换,经过tanh激活),得到新\widetilde{h_{t}},再使用新值与z_{t}相乘。

\widetilde{h_{t}}=tanh\left ( W\cdot \left [ r_{t}*h_{t-1},x_{t} \right ] \right )

z_{t}*\widetilde{h_{t}}

3. 使用(1-z(t))作用再h(t-1)上再与第二步结果相加输出新的h(t)

h_{t}=\left ( 1-z_{t} \right )*h_{t}+z_{t}*\widetilde{h_{t}}

三、代码实现

# -*-coding:utf-8-*-
import torch
import torch.nn as nn
# 实例化GRU模型
#todo: 1.GRU实例化主要参数说明:
# 第一个参数:input_size代表输入数据的词嵌入表示维度
# 第二个参数:hidden_size代表隐藏层输出维度
# 第三个参数:num_layers代表隐藏层的个数gru = nn.GRU(5, 6, 1)#todo: 2.输入数据参数说明:
# 第一个参数:sequence_length代表输入数据的每个样本的句子长度
# 第二个参数:batch_size代表一个批次几个样本
# 第三个参数:input_size代表输入数据的词嵌入表示维度
input_x = torch.randn(3, 4, 5)#todo: 3.隐藏状态参数说明:
# 第一个参数:num_layers代表隐藏层的个数
# 第二个参数:batch_size代表一个批次几个样本
# 第三个参数:hidden_size代表隐藏层输出维度
h0 = torch.randn(1, 4, 6)# todo:将数据送入模型
output, hn = gru(input_x, h0)
print(f'output-->{output}')
print(f'hn-->{hn}')

四、GRU优缺点

GRU的优势:

GRU和LSTM作用相同, 在捕捉长序列语义关联时, 能有效抑制梯度消失或爆炸, 效果都优于传统RNN且计算复杂度相比LSTM要小、重置门直接作用于上一隐藏状态,而LSTM遗忘门作用于细胞状态。更像一个滑动开关,决定保留与更新的比例。

GRU的缺点:

GRU仍然不能完全解决梯度消失问题, 同时其作用RNN的变体, 有着RNN结构本身的一大弊端, 即不可并行计算, 这在数据量和模型体量逐步增大的未来, 是RNN发展的关键瓶颈。

五、BI-GRU

Bi-GRU与Bi-LSTM的逻辑相同, 都是不改变其内部结构, 而是将模型应用两次且方向不同, 再将两次得到的LSTM结果进行拼接作为最终输出. 具体参见上小节中的Bi-LSTM。

http://www.lryc.cn/news/578611.html

相关文章:

  • 关于vue2使用elform的rules校验
  • 深度学习进阶:自然语言处理的推荐点评
  • (LeetCode 面试经典 150 题) 42. 接雨水 (单调栈)
  • Gartner《Choosing Event Brokers to Support Event-DrivenArchitecture》心得
  • 振荡电路Multisim电路仿真实验汇总——硬件工程师笔记
  • .NET跨平台开发工具Rider v2025.1——支持.NET 10、C# 14
  • K8s Pod调度基础——2
  • Langgraph 学习教程
  • 位运算经典题解
  • python+uniapp基于微信小程序的流浪动物救助领养系统nodejs+java
  • 用 YOLOv8 + DeepSORT 实现目标检测、追踪与速度估算
  • SeaTunnel 社区 2 项目中选“开源之夏 2025”,探索高阶数据集成能力!
  • 华为设备 QoS 流分类与流标记深度解析及实验脚本
  • flv.js视频/直播流测试demo
  • 欢乐熊大话蓝牙知识24:LE Secure Connections 是 BLE 的安全升级术
  • 视频内存太大怎么压缩变小一点?视频压缩的常用方法
  • Nginx重定向协议冲突解决方案:The plain HTTP request was sent to HTTPS port
  • Apache HTTP Server部署全攻略
  • 第八十六篇 大数据排序算法:从厨房整理到分布式排序的智慧
  • DBA 命令全面指南:核心操作、语法与最佳实践
  • 爱回收平台接口开发指南
  • 变幻莫测:CoreData 中 Transformable 类型面面俱到(七)
  • 打造 AI 产品的前端架构:响应式、流式、智能交互三合一
  • 基于SSM万华城市货运服务系统的设计与实现
  • OpenCV CUDA模块设备层-----反向二值化阈值处理函数thresh_binary_inv_func()
  • Python学习Day48
  • golang generic 2022-04-13
  • 技术学习_人工智能_1_神经网络是如何实现的?
  • IDE全家桶专用快捷键----------个人独家分享!!
  • 02.SpringBoot常用Utils工具类详解