【NLP笔记】RNN总结

文章目录

  • 经典RNN
    • 单向RNN
    • 双向RNN
    • Deep RNN
    • RNN特性总结
  • 变体RNN
    • LSTM
    • GRU

参考及转载内容:

  • 循环神经网络(RNN)
  • 深度学习05-RNN循环神经网络
  • 完全理解RNN(循环神经网络)

传统的CNN(Covolutional Neural Network,卷积神经网络)通常是给定输入预测对应的输出,是一对一的关系(输入层->隐藏层->输出层,隐藏层之间无关联,为顺序传播的关系),没有涉及输入信息间的关联关系。而在实际应用中,如自然语言处理、语音处理、时序数据处理等任务都依赖于上下文的输入才能够确定输出,因此CNN就无法很好地解决此类任务所需的关联关系提取。

CNN

RNN(Recurrent Neural Network,循环神经网络)就是针对这一类需要考虑上下文信息的数据分析与处理提出来的网络架构,循环神经网络的隐藏层会对之前的信息进行记忆存储,隐藏层之间的信息可以进行交互,当前隐藏层的输入可以包含上一个隐藏层的输出、上一个隐藏层存储的信息状态、输入层的输出。

未展开的RNN

经典RNN

单向RNN

在这里插入图片描述

假设 x t x_{t} xt表示第 t t t步的输入, s t s_{t} st表示第 t t t步的隐藏层的状态,该状态是根据上一个隐藏层状态 s t − 1 s_{t-1} st1计算得出,假设 U U U表示输入层的链接矩阵, W W W表示上一个隐藏时刻到下一个隐藏时刻的权重矩阵, f ( x ) f(x) f(x)为非线性层的激活函数,一般为 t a n h tanh tanh R e L U ReLU ReLU,则时刻 t t t的隐藏层计算为: s t = f ( U x t + W s t − 1 ) s_{t}=f(Ux_{t}+Ws_{t-1}) st=f(Uxt+Wst1)则时刻t的输出计算为: o t = g ( V ∗ s t ) o_{t}=g(V*s_{t}) ot=g(Vst)其中 V V V表示输出层的权重矩阵, g ( x ) g(x) g(x)为激活函数。可以看到当前时刻的输出与多个历史时刻的数据相关,因为每个当前时刻的输出都受到上个时刻的影响。但是单向RNN仅考虑了历史信息,很多时候需要共同结合上下文信息才能够得到更好的预测结果。

# pytorch中的单向RNN
import torch
import torch.nn as nn# 定义输入数据
input_size = 10   # 输入特征的维度
sequence_length = 5   # 时间步个数
batch_size = 3   # 批次大小# 创建随机输入数据
#输入数据的维度为(sequence_length, batch_size, input_size),表示有sequence_length个时间步,
#每个时间步有batch_size个样本,每个样本的特征维度为input_size。
input_data = torch.randn(sequence_length, batch_size, input_size)
print("输入数据",input_data)
# 定义RNN模型
# 定义RNN模型时,我们指定了输入特征的维度input_size、隐藏层的维度hidden_size、隐藏层的层数num_layers等参数。
# batch_first=False表示输入数据的维度中批次大小是否在第一个维度,我们在第二个维度上。
rnn = nn.RNN(input_size, hidden_size=20, num_layers=1, batch_first=False)
"""
在前向传播过程中,我们将输入数据传递给RNN模型,并得到输出张量output和最后一个时间步的隐藏状态hidden。
输出张量的大小为(sequence_length, batch_size, hidden_size),表示每个时间步的隐藏层输出。
最后一个时间步的隐藏状态的大小为(num_layers, batch_size, hidden_size)。
"""
# 前向传播,第二个参数h0未传递,默认为0
output, hidden = rnn(input_data)
print("最后一个隐藏层",hidden.shape)
print("输出所有隐藏层",output.shape)# 打印每个隐藏层的权重和偏置项
# weight_ih表示输入到隐藏层的权重,weight_hh表示隐藏层到隐藏层的权重,注意这里使出是转置的结果。
# bias_ih表示输入到隐藏层的偏置,bias_hh表示隐藏层到隐藏层的偏置。
for name, param in rnn.named_parameters():if 'weight' in name or 'bias' in name:print(name, param.data)

单向RNN的参数是共享的,RNN参数共享指的是:在每一个时间步上,所对应的参数是共享的。参数共享的目的有两个:一、用这些参数来捕获序列上的特征;二、共享参数减少模型的复杂度。

对于RNN的参数共享,我们可以理解为对于一个句子或者文本,参数U可以看成是语法结构、参数W是一般规律,而下一个单词的预测必须是上一个单词和一般规律W与语法结构U共同作用的结果。我们知道,语法结构和一般规律在语言当中是共享的。所以,参数自然就是共享的!

我们需要记住的是,深度学习是怎么减少参数的,很大原因就是参数共享,而CNN是在空间上共享参数,RNN是在时间序列上共享参数。

双向RNN

在这里插入图片描述

这种可以结合上下文信息的RNN结构即双向RNN,双向RNN的隐藏层需要保存两个状态值,一个是正向计算,一个是反向计算,基于上述单向计算的过程,双向计算可表示如下: o t = g ( V ∗ s t + V ′ ∗ s t ′ ) o_{t}=g(V*s_{t}+V'*s'_{t}) ot=g(Vst+Vst)
正向计算: s t = f ( U x t + W s t − 1 ) s_{t}=f(Ux_{t}+Ws_{t-1}) st=f(Uxt+Wst1)
反向计算: s t ′ = f ( U ′ x t + W s t + 1 ) s'_{t}=f(U'x_{t}+Ws_{t+1}) st=f(Uxt+Wst+1)
在正向计算和反向计算过程中,权重不共享。其中网络参数的更新是通过前向传播和反向传播过程完成的,其中反向传播的过程采用的是BPTT(BackPropagation Through Time)算法进行的,其实基本原理也是基于常规的BP算法,只是BPTT需要考虑不同时刻的梯度计算结果之和,具体计算可参考:BPTT算法推导 。

# pytorch定义双向RNN
import torch
import torch.nn as nn# 定义输入数据
input_size = 10   # 输入特征的维度
sequence_length = 5   # 时间步个数
batch_size = 3   # 批次大小# 创建随机输入数据
input_data = torch.randn(sequence_length, batch_size, input_size)# 定义双向RNN模型
rnn = nn.RNN(input_size, hidden_size=20, num_layers=1, batch_first=False, bidirectional=True)# 前向传播
output, hidden = rnn(input_data)# 输出结果
print("输出张量大小:", output.size())
print("最后一个时间步的隐藏状态大小:", hidden.size())

Deep RNN

在这里插入图片描述

基本循环神经网络和双向循环神经网络只有单个隐藏层,有时不能很好的学习数据内部关系,可以通过叠加多个隐藏层,形成深度循环神经网络结构。单层的隐藏层RNN的参数是共享的,深层的RNN会有 L L L层的参数,其每一层都可以是一个双向RNN结构。

# pytorch实现双向RNN
import torch
import torch.nn as nn# 定义输入数据和参数
input_size = 5
hidden_size = 10
num_layers = 2
batch_size = 3
sequence_length = 4# 创建输入张量
input_tensor = torch.randn(sequence_length, batch_size, input_size)# 创建多层RNN模型
rnn = nn.RNN(input_size, hidden_size, num_layers)# 前向传播
output, hidden = rnn(input_tensor)# 打印输出张量和隐藏状态的大小
print("Output shape:", output.shape)
print("Hidden state shape:", hidden.shape)

RNN特性总结

  • 单向单隐藏层传播参数共享;

  • 参数更新采用BPTT的算法实现;
    在这里插入图片描述

  • 存在梯度消失和梯度爆炸的问题;

    • 梯度消失:传统的RNN不能捕获长距离词之间的关系。从图中可以看到tanh函数在x趋近于无穷大和无穷小时梯度值都为0,当邻近神经元梯度接近0时,因为前面层的梯度是由后面层的梯度连乘得到的,多个梯度相乘会使梯度值以指数级速度下降,最终在反向传播几步后就完全消失,比较远的时刻的梯度值为0。
    • 梯度爆炸:RNN的学习依赖于我们的激活函数和网络初始参数,如果Jacobian矩阵中的值太大,会产生梯度爆炸而不是梯度消失问题。梯度消失比梯度爆炸受到了更多的关注有两方面的原因。其一,梯度爆炸容易发现,梯度值会变成NaN,导致程序崩溃。其二,用预定义的阈值裁剪梯度可以简单有效的解决梯度爆炸问题。梯度消失问题就不容易发现并且也不好处理,这也是梯度消失比梯度爆炸受到学术界更多关注的原因。
  • RNN的几种架构:

    • 单输入单输出(Single Input Single Output,SISO): 给定一段文本,预测下一个词语;
      在这里插入图片描述
      在这里插入图片描述

    • 单输入多输出(Single Input Multiple Output,SIMO):如上图有两种实现形式。这种1 to N的结构可以处理的问题有很多,比如图像标注,输入的X是图像的特征,而输出的y序列是一段句子。

    • 多输入单输出(Multiple Input Single Output,MISO):输入是一个序列,输出是一个单独的值而不是序列。这种结构通常用来处理序列分类问题。如输入一段文字判别它所属的类别,输入一个句子判断其情感倾向,输入一段文档并判断它的类别等等。

    • 多输入多输出(Multiple Input Multiple Output,MIMO):一种是NtoN,输入和输出序列是等长的。这种可以作为简单的Char RNN可以用来生成文章,诗歌,甚至是代码,非常有意思。另一种是这种结构又叫Encoder-Decoder模型,也称之为Seq2Seq模型。在现实问题中,我们遇到的大部分序列都是不等长的。如机器翻译中,源语言和目标语言的句子往往并没有相同的长度。而Encoder-Decoder结构先将输入数据编码成一个上下文向量c,之后在通过这个上下文向量输出预测序列。

变体RNN

参考链接:【译】理解LSTM(通俗易懂版)

LSTM

RNN的结构的隐藏层只有一个状态,对邻近的输入会非常敏感,如果我们再增加一个门(gate)来控制特征的流通和损失,即c,让它来保存长期的状态,这就是长短时记忆网络(Long Short Term Memory,LSTM)。
在这里插入图片描述
新增加的状态c,称为单元状态。我们把LSTM按照时间维度展开:
其中图像上的标识 σ \sigma σ标识使用sigmod激活到[0-1],tanh激活到[-1,1],⨀ 是一个数学符号,表示逐元素乘积(element-wise product)或哈达玛积(Hadamard product)。当两个相同维度的矩阵、向量或张量进行逐元素相乘时,可以使用 ⨀ 符号来表示。
在这里插入图片描述
LSTM的输入有三个:当前时刻网络的输出值 x t x_{t} xt、上一时刻LSTM的输出值 h t − 1 h_{t-1} ht1 、以及上一时刻的记忆单元向量 c t − 1 c_{t−1} ct1

LSTM的输出有两个:当前时刻LSTM输出值 h t h_{t} ht、当前时刻的隐藏状态向量 h t h_{t} ht、和当前时刻的记忆单元状态向量 c t c_{t} ct

注意:记忆单元c在LSTM 层内部结束工作,不向其他层输出。LSTM的输出仅有隐藏状态向量h。

LSTM 的关键是单元状态,即贯穿图表顶部的水平线,有点像传送带。这一部分一般叫做单元状态(cell state)它自始至终存在于LSTM的整个链式系统中。

在这里插入图片描述

f t f_{t} ft叫做遗忘门,表示 C t − 1 C_{t−1} Ct1 的哪些特征被用于计算 C t C_{t} Ct f t f_{t} ft是一个向量,向量的每个元素均位于(0~1)范围内。通常我们使用 sigmoid 作为激活函数,sigmoid 的输出是一个介于于(0~1)区间内的值,但是当你观察一个训练好的LSTM时,你会发现门的值绝大多数都非常接近0或者1,其余的值少之又少。
在这里插入图片描述

C t C_{t} Ct表示单元状态更新值,由输入数据 x t x_{t} xt和隐节点 h t − 1 h_{t-1} ht1经由一个神经网络层得到,单元状态更新值的激活函数通常使用tanh。 i t i_{t} it叫做输入门,同 f t f_{t} ft一样也是一个元素介于(0~1)区间内的向量,同样由 x t x_{t} xt h t − 1 h_{t-1} ht1经由sigmoid激活函数计算而成。
在这里插入图片描述

在这里插入图片描述

最后,为了计算预测值 y t y^{t} yt和生成下个时间片完整的输入,我们需要计算隐节点的输出 h t h_{t} ht
在这里插入图片描述

GRU

Gated Recurrent Unit – GRU 是 LSTM 的一个变体。他保留了 LSTM 划重点,遗忘不重要信息的特点,在long-term 传播的时候也不会被丢失。

LSTM 的参数太多,计算需要很长时间。因此,最近业界又提出了 GRU(Gated RecurrentUnit,门控循环单元)。GRU 保留了 LSTM使用门的理念,但是减少了参数,缩短了计算时间。

相对于 LSTM 使用隐藏状态和记忆单元两条线,GRU只使用隐藏状态。异同点如下:
在这里插入图片描述
GRU的计算过程如下:
在这里插入图片描述
如图所示,GRU 没有记忆单元,只有一个隐藏状态h在时间方向上传播。这里使用r和z共两个门(LSTM 使用 3 个门),r称为 reset 门,z称为 update 门。r(reset门)决定在多大程度上“忽略”过去的隐藏状态,定义了前面记忆保存到当前时间步的量。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/758613.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Redis6.0多线程的疑惑解答

1.Redis6.0之前的版本真的是单线程吗? Redis在处理客户端的请求是,包括获取(socket读)、解析、执行、内容返回(socket 写)等都有一个 顺序串行的主线程处理,这就是所谓的"单线程"。但如果严格来讲并不是单线程,除了主线…

浏览量这么低,还要不要继续坚持?

哈喽,你好啊,我是雷工! 曾经在一个群里聊天,有群友看到我两位数的浏览量,说到:浏览量这么低还坚持什么? 浏览量低是事实,大多数是十几二十的,上百的都是少数&#xff0c…

python社区垃圾分类管理平台的设计与实现flask-django-php-nodejs

近些年来,随着科技的飞速发展,互联网的普及逐渐延伸到各行各业中,给人们生活带来了十分的便利,社区垃圾分类管理平台利用计算机网络实现信息化管理,使整个社区垃圾分类管理的发展和服务水平有显著提升。 语言&#xf…

Swift 从获取所有 NSObject 对象聊起:ObjC、汇编语言以及底层方法调用链(一)

概览 Swift 语言给我们的印象是:简洁、现代化和可以“心安神泰”的完全信赖。不过,在一些特殊情况下我们唯有进入 Swift 底层的动态世界方能真正地“随遇而安”。 保安局“刘局长”曾语重心长的教导过我们:“非常时期,用非常方法…

有了std::thread,为什么还需要引入std::jthread?

C进阶专栏:http://t.csdnimg.cn/HGkeZ 目录 1.前言 2.std::is_invocable_v 3.std::jthread 3.1.构造函数 3.2.std::jthread无需join/detach使用实例 3.3.std::jthread处理外部请求中断实 3.4.处理中断请求示例代码 4.特性 5.总结 1.前言 C11以来提供了C原…

Redis实现高可用方案

文章目录 前言一、主从模式1.1 复制流程1.2 优缺点 二、哨兵模式2.1 介绍2.2 哨兵的工作模式 三、集群模式3.1 Cluster集群节点的通讯3.2 Hash Slot插槽算法3.3 Redis Cluster集群3.4 故障转移 前言 如果单机部署Redis服务的话,一旦Reids宕机,那么整个服…

英伟达 V100、A100/800、H100/800 GPU 对比

近期,不论是国外的 ChatGPT,还是国内诸多的大模型,让 AIGC 的市场一片爆火。而在 AIGC 的种种智能表现背后,均来自于堪称天文数字的算力支持。以 ChatGPT 为例,据微软高管透露,为 ChatGPT 提供算力支持的 A…

centos 环境部署

一、安装redis 1. 升级 GCC 最直接的解决方式是升级你的 GCC 编译器到支持 C11 标准的版本。CentOS 7 默认的 GCC 版本较旧,可能不支持 _Atomic。你可以通过以下步骤升级 GCC: 启用 CentOS 的 Software Collections (SCL) 仓库,该仓库提供了…

王老吉药业开拓数字经济“新蓝海”,成立数字经济研究所,科技赋能新品压片糖

3月12日,广州王老吉药业股份有限公司(以下简称“王老吉药业”)召开第十一届312感恩活动新闻发布会,宣告王老吉数字经济研究所成立,并发布王老吉压片糖新品。一系列重要重要举措,无一不标志着王老吉药业正以…

Java SE入门及基础(44)

目录 I / O流(上) 1. 什么是I / O流 过程分析 I / O的来源 Java 中的 I / O流 2. 字节流 OutputStream 常用方法 文件输出流 FileOutputStream 构造方法 示例 InputStream 常用方法 文件输入流 FileInputStream 构造方法 示例 综合练习 字节流应用场景 Java SE文…

自动化测试报告生成(Allure)

🍅 视频学习:文末有免费的配套视频可观看 🍅 关注公众号【互联网杂货铺】,回复 1 ,免费获取软件测试全套资料,资料在手,涨薪更快 之前尝试使用过testNG自带的测试报告、优化过reportNG的测试报告…

算法·动态规划Dynamic Programming

很多人听到动态规划或者什么dp数组了,或者是做到一道关于动态规划的题目时,就会有一种他很难且不好解决的恐惧心理,但是如果我们从基础的题目开始深入挖掘动规思想,在后边遇到动态规划的难题时就迎难而解了。  其实不然&#xff…

linux:线程互斥

个人主页 : 个人主页 个人专栏 : 《数据结构》 《C语言》《C》《Linux》 文章目录 前言一、线程互斥问题解释互斥量的接口 二、加锁的原理三、 死锁死锁四个必要条件避免死锁 总结 前言 本文是对于线程互斥的知识总结 一、线程互斥 问题 我们先看下面…

财报解读:出海“窗口期”再现,汇量科技保驾护航的底气源于什么

大数据时代,每个人的喜好都被精准捕捉。购物APP、购物网站们,都仿佛一位贴心的时尚顾问。而这源于个性化广告经过深度学习和智能算法得来的结果。 随着广告市场的竞争愈演愈烈,广告主们需要更为精准、高效的个性化投放。近日,深耕…

基于SSM的宿舍管理系统的设计与实现(JSP,MySQL)

摘 要 随着社会发展、信息技术的普及,人们日常管理工作也发生了巨大的变化。信息化技术之渗透各行业的方方面面。学生宿舍管理作为校园管理工作的重要一环,不仅关系到学生自身的确切利益,同时也是对校园管理工作重大考验。近来年由于在校学生…

leetcode代码记录(移除链表元素

目录 1. 题目:2. 我的代码:小结: 1. 题目: 给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val val 的节点,并返回 新的头节点 。 示例 1: 输入:head […

Flutter开发进阶之瞧瞧Widget

Flutter开发进阶之瞧瞧Widget 在Flutter开发中,WIdget是构建界面的基本单元;Widget是不可变的,意味着一旦创建如果需要改变UI就需要重新创建一个新的Widget;在实际开发中,Widget通常由一个个Widget组合而成,从而形成嵌套的树形结构,复杂的UI就是由这一个个Widget构建而…

【C语言】—— 指针三 : 参透数组传参的本质

【C语言】—— 指针三 : 参透数组传参的本质 一、数组名的理解二、使用指针访问数组2.1、指针访问数组2.2、[ ] 的深入理解2.3、数组与指针的区别 三、一维数组的传参本质四、数组指针变量4.1、数组指针变量是什么4.2、 数组指针的初始化 五、二维数组传参的本质 一…

简单了解多线程

并发和并行 并发: 在同一时刻,多个指令在单一CPU上交替指向 并行:在同一时刻,多个指令在多个CPU上同时执行 2核4线程,4核8线程,8核16线程,16核32线程 基础实现线程的方式 Thread :继承类 &…

多人命题系统|基于SSM框架+ Mysql+Java+ B/S结构的多人命题系统设计与实现(可运行源码+数据库+设计文档)

推荐阅读100套最新项目 最新ssmjava项目文档视频演示可运行源码分享 最新jspjava项目文档视频演示可运行源码分享 最新Spring Boot项目文档视频演示可运行源码分享 2024年56套包含java,ssm,springboot的平台设计与实现项目系统开发资源(可…