【NLP251】NLP RNN 系列网络

devtools/2025/2/6 21:09:30/

NLP251 系列主要记录从NLP基础网络结构到知识图谱的学习

1.原理及网络结构

1.1RNN 

在Yoshua Bengio论文中( http://proceedings.mlr.press/v28/pascanu13.pdf )证明了梯度求导的一部分环节是一个指数模型,当n<1时,就会出现“梯度消失"问题,而当η> 1时,“梯度爆炸”也就产生了。

1.2 双向-RNN

两个方向RNN的区别在于输入数据的不同,反向RNN数据是对正向RNN数据的反转

1.3深度双向-RNN

 

1.4LSTM

LSTM(长短期记忆网络)相较于RNN(循环神经网络)的主要优势如下:

1. 解决长期依赖问题

  • RNN在处理长序列数据时,容易出现梯度消失或梯度爆炸的问题,导致难以捕捉到序列中相隔较远的依赖关系。

  • LSTM通过引入“记忆单元”(Cell State)和门控机制(遗忘门、输入门、输出门),能够有效地学习和保持长期依赖关系。遗忘门可以有选择性地丢弃不再重要的信息,输入门可以添加新的重要信息,输出门则控制信息的输出,从而确保信息在长序列中能够稳定传递。

2. 缓解梯度消失问题

  • RNN在反向传播时,梯度可能会随着序列长度增加而迅速衰减或增大,导致训练困难。

  • LSTM通过门控机制,使得梯度可以直接通过记忆单元流动,减少了梯度在传播过程中的衰减,从而缓解了梯度消失问题。

LSTM 的关键在于其所特有的“细胞状态”,这一状态犹如一条贯穿始终的传送带。它在整个链条上顺畅运行 ,只有一些少量的线性交互。信息在 上面流传保持不变很容易。

LSTM怎么控制“细胞状态”? 

LSTM(长短期记忆网络)借助所谓的“门”结构,能够有选择地去除或增加“细胞状态”中存储的信息。这一过程包含一个sigmoid神经网络层以及一个逐元素的乘法操作。sigmoid层生成一个介于0到1之间的概率值,决定每个成分可以通过的量,其中0代表“完全阻止”,而1则表示“完全允许”。在LSTM中,存在三个主要的“门”结构,共同调控“细胞状态”的更新机制。

第一个“门”——“忘记门”或“遗忘门”, 决定从过去的“细胞状态”中 丢弃什么信息;比如在语言模型中,细胞状态可能包含了性别信息(“他” 或者“她”),当我们看到新的代名词的时候,可以考虑忘记旧的数据。
第二个“门”,即“信息 增加门”,负责决定哪些新信息可以添加到“细胞状态”中。 Sigmoid层决定什么值需要更新; Tanh层创建一个新的候选向量Ct; 主要是为了状态更新做准备

 

经过第一个和第二个“门”后,可以确定传递信息的删除和增加,进而执行“细胞状态”的更新操作。具体来说,首先将Ct-1更新为Ct,接着把旧状态与ft相乘,从而剔除那些确凿无误无需保留的信息。随后,加入新的候选值it *Ct,最终获得更新后的“细胞状态”。

 

第三个“门”即“输出门”,它基于“细胞状态”生成输出。首先,通过sigmoid层来决定细胞状态的哪一部分会被用于输出。然后,利用tanh函数处理细胞状态,得到一个介于-1到1之间的数值。最后,将这个数值与sigmoid门的输出相乘,从而确定最终输出的内容。

 

LSTM变种

 变种1 增加“peephole connections”层 ,让门层也接受细胞状态的输入

变种2 通过耦合忘记门和更新输入门(第一个和第二个门);也就是不再单独的考虑忘记什么、 增加什么信息,而是一起进行考虑

 

1.5GRU 

Gated Recurrent Unit (GRU) 是在2014年被提出的,它将LSTM中的忘记门和输出门合并为一个单一的更新门,同时还将数据单元状态和隐藏状态(即细胞状态和输出状态)进行了合并。这种结构相较于LSTM更为简单。

总结:RNN与GRU细胞状态信息与输出信息相同,而GRU细胞状态信息可能与输出信息不同 。

 2.API接口实现

2.1RNN API调用讲解

RNN返回值为两部分,第一部分是蓝框所示所有时刻 最后一个隐藏层的输出特征向量;

第二分是红色圈所示最后时刻 所有一个隐藏层的输出特征向量;

我们可以通过rnn.named_parameters()来查看详细的中间过程状态shape

rnn = nn.RNN(4, 8, num_layers=2, batch_first=True, bidirectional=True)
for name, param in rnn.named_parameters():print(name, param.shape)

  

RNN无法保持长时依赖(代码验证):

 2.2 LSTM API调用讲解 

 

 从网络结构图和代码中不难发现LSTM中ht与output输出相同 

 中间过程中的32从何而来?

weight_ih_l0 torch.Size([32, 4])
weight_hh_l0 torch.Size([32, 8])
bias_ih_l0 torch.Size([32])
bias_hh_l0 torch.Size([32])

附LSTM代码:

lstm = nn.LSTM(input_size=4,  # 每个样本每个时刻输入的向量维度大小hidden_size=16,  # 每个样本每个时刻输出的向量维度大小num_layers=1,  # RNN的层数,默认为1bias=True,  # 内部的线性转换是否添加bias,True表示添加,默认为Truebatch_first=True,  # 输入&输出数据的第一维是不是批次样本,True表示是,也就是输出的格式为:[N,T,E]; 默认为False,表示shape格式为[T,N,E]dropout=0,  # 针对输出的特征向量中,部分值重新为0的概率/可能性bidirectional=False,  # 是否构建双向的RNN,True表示构建,False表示不构建反向RNN;默认为Falseproj_size=0  # 是否针对每个时刻输出的hi进行一个线性转换,0表示不进行转换;>0的值表示会将hi映射(全连接)为proj_size大小的向量
)x = torch.randn(2, 3, 4)  # 2个样本,每个样本3个token,每个token对应的向量维度大小为4
# batch_first = True
# output: 所有样本、所有时刻对应的输出特征向量值,shape为: [N,T,?]
# ? = hidden_size * (2 if bidirectional else 1) if proj_size <=0 else proj_size
# ct: 最后一个时刻的状态信息/细胞信息, shape为: [1 * num_layers * (2 if bidirectional else 1), N, hidden_size]
# ht: 最后一个时刻的状态信息/细胞信息, shape为: [1 * num_layers * (2 if bidirectional else 1), N, hidden_size]
output, (ht, ct) = lstm(x)
print(type(output), output.shape)
print(type(ht), ht.shape)
print(type(ct), ct.shape)print(output[:, -1, :])
print(ht)
print(ct)rnn = nn.LSTM(4, 8, batch_first=True, bidirectional=False, num_layers=1)
for name, param in rnn.named_parameters():print(name, param.shape)

2.3 GRU API调用讲解 

lstm = nn.GRU(input_size=4,  # 每个样本每个时刻输入的向量维度大小hidden_size=16,  # 每个样本每个时刻输出的向量维度大小num_layers=1,  # RNN的层数,默认为1bias=True,  # 内部的线性转换是否添加bias,True表示添加,默认为Truebatch_first=True,  # 输入&输出数据的第一维是不是批次样本,True表示是,也就是输出的格式为:[N,T,E]; 默认为False,表示shape格式为[T,N,E]dropout=0,  # 针对输出的特征向量中,部分值重新为0的概率/可能性bidirectional=False  # 是否构建双向的RNN,True表示构建,False表示不构建反向RNN;默认为False
)# 2个样本,每个样本3个token,每个token对应的向量维度大小为4
x = torch.randn(2, 3, 4)
# batch_first = True
# output: 所有样本、所有时刻对应的输出特征向量值,shape为: [N,T,?]
# **** ? = hidden_size * (2 if bidirectional else 1)
# : 最后一个时刻的状态信息/细胞信息, shape为: [1 * num_layers * (2 if bidirectional else 1), N, hidden_size]
# ct/ht: 最后一个时刻的状态信息/细胞信息, shape为: [1 * num_layers * (2 if bidirectional else 1), N, hidden_size]
output, ct = lstm(x)
print(type(output), output.shape)
print(type(ct), ct.shape)rnn = nn.GRU(4, 8, batch_first=True, bidirectional=False, num_layers=1)
for name, param in rnn.named_parameters():print(name, param.shape)


http://www.ppmy.cn/devtools/156621.html

相关文章

日本工作面试基本礼仪-一篇梗概

面接の内容に加えて、エチケットも非常に重要です。日本のビジネス社会には独自のビジネスマナー&#xff08;ビジネスマナー[ビジネスマナー]&#xff09;があり、国際基準とは異なる場合がありますので、注意が必要です。 日本人、特に日本の伝統的な大企業の面接官は、一般…

熟练掌握Http协议

目录 基本概念请求数据Get请求方式和Post请求方式 响应数据响应状态码 基本概念 Http协议全称超文本传输协议(HyperText Transfer Protocol)&#xff0c;是网络通信中应用层的协议&#xff0c;规定了浏览器和web服务器数据传输的格式和规则 Http应用层协议具有以下特点&#…

【开源免费】基于SpringBoot+Vue.JS美食推荐商城(JAVA毕业设计)

本文项目编号 T 166 &#xff0c;文末自助获取源码 \color{red}{T166&#xff0c;文末自助获取源码} T166&#xff0c;文末自助获取源码 目录 一、系统介绍二、数据库设计三、配套教程3.1 启动教程3.2 讲解视频3.3 二次开发教程 四、功能截图五、文案资料5.1 选题背景5.2 国内…

如何开发一个大语言模型,开发流程及需要的专业知识

开发大型语言模型&#xff08;LLM&#xff09;是一个复杂且资源密集的过程&#xff0c;涉及多个阶段和跨学科知识。以下是详细的开发流程和所需专业知识指南&#xff1a; 一、开发流程 1. 需求分析与规划 目标定义&#xff1a;明确模型用途&#xff08;如对话、翻译、代码生成…

Kafka SSL(TLS)安全协议

文章目录 Kafka SSL&#xff08;TLS&#xff09;安全协议1. Kafka SSL 的作用1.1 数据加密1.2 身份认证1.3 数据完整性1.4 防止中间人攻击1.5 确保安全的分布式环境1.6 防止拒绝服务&#xff08;DoS&#xff09;攻击 2. Kafka SSL 配置步骤&#xff08;1&#xff09;创建 SSL 证…

FPGA|例化生成的PLL功能IP核

1、例化上一篇文章中调用的IP核&#xff0c;新建文件PLL_test.v 2、代码如图 timescale 1ns / 1ps module PLL_test(input clk,input rst_n,output clkout0,output clkout1,output clkout2,output clkout3,output clkout4);wire locked;PLL pll_inst(.inclk0(clk),.c0(clkout0)…

输入类控件和多元素控件【QT】

文章目录 输入类控件QLineEdit Text EditCombo BoxSpin BoxDialSlider多元素控件QListWidget TableWidetTreeWidgetQGroupBoxTab Widget# QVBoxLayout# QHBoxLayoutQGridLayoutQFormLayout 输入类控件 QLineEdit 例如&#xff1a; 实现一个用户输入姓名 密码 电话 性别 的功能…

SQL高级技巧:高效获取两表交集数据的三种方法(JOIN、IN、EXISTS)

一、引言 在SQL开发中&#xff0c;获取两表交集数据是常见的需求&#xff0c;而实现这一目标的主要方法有三种&#xff1a;JOIN、IN 和 EXISTS。虽然它们都能完成任务&#xff0c;但语法、性能和应用场景却各有不同。 我们将通过对比分析这三种方法的区别与优缺点&#xff0c…