NLP学习笔记(一) RNN基本介绍

news2025/1/19 22:04:50

大家好,我是半虹,这篇文章来讲循环神经网络 (Recurrent Neural Network, RNN)

文章行文思路如下:

  1. 首先通过前馈神经网络引出为啥需要循环神经网络
  2. 然后介绍循环神经网络的核心思想与运作方式
  3. 最后拓展两个循环神经网络常见且常用的变体

在讲循环神经网络前,先来回顾下前馈神经网络,这是深度学习中最基础的网络结构之一

前馈神经网络也称为多层感知机,由多个隐藏层叠加得到,每个隐藏层可看作是一个线性模型加激活函数

为简单起见,这里先以单层感知机为例进行介绍

前馈神经网络结构

上图是单层感知机的结构示意图,其中, X X X 是输入, H H H 是输出

对应的公式表达如下所示:
H = α ( X W x h + b h ) H = \alpha(X W_{xh} + b_{h}) H=α(XWxh+bh)
其中, W x h W_{xh} Wxh b h b_{h} bh 都是隐藏层的参数,表示可学习的权重矩阵, α \alpha α 是激活函数


研究表明,前馈神经网络具有很强的学习能力,只要有足够多训练数据,理论上能拟合任意函数

既然如此,那为什么还需要有循环神经网络呢

这是因为前馈神经网络只能单独处理每个输入,对于网络而言,前一个输入和后一个输入是没有任何关系的

这在处理时序数据时前馈神经网络就会显得力不从心,一个典型的场景就是文本处理


举个例子,假设现在我们需要完成一个词性标注任务,给定的句子是:我在看画

如果用前馈神经网络完成上述任务时,就会出现下面的情况:

前馈神经网络例子

这是因为前馈神经网络对于句子中的每个词都是独立处理的

对于画这个词,在不给定上下文的情况下,它既可以是动词,也可以是名词,这时候网络无法判断它的词性

而人是怎么判断词性的呢?当我们发现看是动词时,自然就能推断画是名词,因为动词后接的是名词

这就引出一个重要的结论,在处理文本时,网络需要根据之前的词语来理解当前的词语

循环神经网络例子

这就是循环神经网络的核心,在处理序列当前的数据时,同时考虑序列之前的数据

循环神经网络是怎么做到这一点的呢?答案就是:使用一个隐状态保存之前的信息,具体网络结构请看下图:

要注意这里的隐状态跟隐藏层不是一回事噢

循环神经网络结构

上图左半部分是循环神经网络的结构示意图,右半部分是其按时间展开的示意图

可以看到,循环神经网络当前隐藏层的输出不仅取决于当前的输入,而且取决于先前隐藏层的输出

对应的公式表达如下所示:
H t = α ( X t W x h + H t − 1 W h h + b h ) H_{t} = \alpha(X_{t} W_{xh} + H_{t-1} W_{hh} + b_{h}) Ht=α(XtWxh+Ht1Whh+bh)
其中, H t H_{t} Ht 是当前隐藏层, X t X_{t} Xt 是当前输入, H t − 1 H_{t-1} Ht1 是先前隐藏层, W x h W_{xh} Wxh W h h W_{hh} Whh b h b_h bh 都是可学习的参数


对比循环神经网络和前馈神经网络的结构表示和公式表达,可以很清楚地发现两者的区别

在结构表示上,循环神经网络增加了一个隐状态,能保存上一个隐藏层的信息

在公式表达上,循环神经网络计算当前隐藏层时,不仅取决于当前输入,还会考虑先前的隐藏层

能理解这两点,就能理解循环神经网络的核心思想


为了帮助大家进一步理解循环神经网络的工作方式,下面我们举一个例子来说,并给出关键代码

假设我们用循环神经网络对下面这个句子进行编码:我在画画

import torch
import torch.nn as nn

# 定义输入数据
# 对于输入句子我在画画,首先用独热编码得到其向量表示

x1 = torch.tensor([1, 0, 0]).float() # 我
x2 = torch.tensor([0, 1, 0]).float() # 在
x3 = torch.tensor([0, 0, 1]).float() # 画
x4 = torch.tensor([0, 0, 1]).float() # 画

h0 = torch.zeros(5) # 初始化隐状态

# 定义模型参数
# 模型的输入是三维向量,这里定义模型的输出是五维向量

W_xh = nn.Parameter(torch.randn(3, 5), requires_grad = True)
W_hh = nn.Parameter(torch.randn(5, 5), requires_grad = True)
b_h  = nn.Parameter(torch.randn(5)   , requires_grad = True)

# 前向传播

h1 = torch.tanh(torch.matmul(x1, W_xh) + torch.matmul(h0, W_hh) + b_h)
h2 = torch.tanh(torch.matmul(x2, W_xh) + torch.matmul(h1, W_hh) + b_h)
h3 = torch.tanh(torch.matmul(x3, W_xh) + torch.matmul(h2, W_hh) + b_h)
h4 = torch.tanh(torch.matmul(x4, W_xh) + torch.matmul(h3, W_hh) + b_h)

# 结果验证
# 可以发现,即使是对于同一个词语,得到的表示也是不一样的
# 这是因为在计算当前词语时,会考虑先前的词语

print(h3) # tensor([0.9787, 0.9974, 0.9995, 0.9999, 0.9970])
print(h4) # tensor([0.6867, 0.6352, 0.9994, 0.2269, 0.9801])

至此,我们已经介绍了循环神经网络的基本原理

下面再补充循环神经网络的两个变体,深度循环神经网络以及双向循环神经网络


不知道大家是否还记得,文章开头我们是通过单层感知机来引出循环神经网络的

对比单层感知机拓展成多层感知机时,普通的循环神经网络同理可以拓展成深度循环神经网络

其按时间展开的示意图如下所示:

深度循环神经网络

可以看到,上图有 L L L 个隐藏层、 T T T 个时间步,其中 X X X 是输入, H H H 是隐藏层的输出

从横向看,上一步隐藏层输出作为下一步隐藏层输入,这和普通的循环神经网络是一样的

从纵向看,上一层隐藏层输出作为下一层隐藏层输入,这是普通的循环神经网络上进行的堆叠

不难发现,当 L = 1 L = 1 L=1 时,就是普通的循环神经网络

在实际应用中,通常会取最后一层隐藏层的输出 H t ( L ) H^{(L)}_{t} Ht(L) 作为每个时间步输入 X t X_{t} Xt 的表示


而另一个循环神经网络的变种是双向循环神经网络

上面我们所讲的循环神经网络都是从左往右递推的,这让我们可以根据前文的语义理解当前的词语

但有的时候,后文的语义对于当前词语的理解也同样重要

因此我们不妨在从左往右递推的基础上,补一个从右往左的递推,这就是双向循环神经网络

其按时间展开的示意图如下所示:

双向循环神经网络

如图所示,其中 X X X 是输入, H → \overrightarrow{H} H 是从左往右的隐藏层输出, H ← \overleftarrow{H} H 是从右往左的隐藏层输出

在实际应用中,通常会取两个隐藏层输出的拼接 [ H → t   ;   H ← t ] [\overrightarrow{H}_{t}\ ;\ \overleftarrow{H}_{t}] [H t ; H t] 作为每个时间步输入 X t X_{t} Xt 的表示


至此本文结束,要点总结如下:

  1. 循环神经网络可以有效地处理时序数据,弥补前馈神经网络的缺陷

  2. 循环神经网络的核心在于当前输出不仅由当前输入决定,还由先前的输出决定

    这是通过增加隐状态在上一时间步保存、在下一时间步读取而实现的

  3. 深度循环神经网络和双向循环神经网络是循环神经网络的两个变体

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

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

相关文章

Windows 7恢复分区丢失了怎么恢复?

问题:Windows 7恢复分区丢失 戴尔、惠普和华硕等电脑制造商现会在他们的计算机上创建一个恢复分区。恢复分区允许用户在系统出现问题时将计算机恢复到出厂默认设置。但是,由于丢失了恢复分区,因此某些用户无法将电脑恢复到出厂设置。这是一个…

析构函数可以为纯虚函数吗?纯虚函数可以有函数体吗?纯虚函数需要函数体吗?

先回答标题中中的几个问题: 析构函数可以为纯虚函数吗? yes。纯虚函数可以有函数体吗? yes。纯虚函数需要函数体吗? 一般来讲,如果析构函数是纯虚函数,那么析构函数必须要有函数体,如果是其它函…

Web前端大作业:基于bootstrap响应式页面,家具装修公司网站

🎉精彩专栏推荐 💭文末获取联系 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 💂 作者主页: 【主页——🚀获取更多优质源码】 🎓 web前端期末大作业: 【📚毕设项目精品实战案例 (10…

最新版本APT漏洞利用工具箱

点击"仙网攻城狮”关注我们哦~不当想研发的渗透人不是好运维让我们每天进步一点点简介1.最近发现一个好用的渗透工具箱,基本包含最新热门漏洞exp,分享一下项目地址:https://github.com/White-hua/Apt_t00ls环境:jdk1.8如果双…

【深度学习】PyTorch深度学习实践 - Lecture_11_Advanced_CNN

文章目录一、GoogLe Net1.1 网络结构1.2 Inception Model1.3 11 Convolution1.4 PyTorch-GPU 实现 GoogLe Net二、Residual Net2.1 梯度消失和梯度爆炸2.2 残差模块2.3 PyTorch-GPU 实现 Simple Residual Net2.3.1 整体结构2.3.2 残差块对象2.3.3 残差网络对象2.3.4 完整代码三…

微服务框架 SpringCloud微服务架构 分布式事务 38 动手实践 38.7 案例实现TCC 模式【分析】

微服务框架 【SpringCloudRabbitMQDockerRedis搜索分布式,系统详解springcloud微服务技术栈课程|黑马程序员Java微服务】 分布式事务 文章目录微服务框架分布式事务38 动手实践38.7 案例实现TCC 模式【分析】38.7.1 实现TCC 模式38.7.2 TCC 的空回滚 和业务悬挂38…

Redis框架(八):大众点评项目 逻辑过期时间处理缓存击穿

大众点评项目 逻辑过期时间处理缓存击穿需求:逻辑过期时间处理缓存击穿业务实现总结SpringCloud章节复习已经过去,新的章节Redis开始了,这个章节中将会回顾Redis实战项目 大众点评 主要依照以下几个原则 基础实战的Demo和Coding上传到我的代…

七分钟教会你如何编写一个合格的测试用例

目录 1、测试用例的基本要素 2、根据测试用例去测试带来的好处 3、测试用例的设计方法 3.1、等价类 3.2、边界值 3.3、错误猜测法 3.4、场景法 3.5、因果图法 3.6、正交排列 4、怎样判断一个测试用例是好的测试用例 1、测试用例的基本要素 测试用例是为了实施测试而向…

基于LEACH和HEED的WSN路由协议研究与改进(Matlab代码实现)

👨‍🎓个人主页:研学社的博客 💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜…

Google谷歌浏览器Post请求预见strict-origin-when-cross-origin跨域问题的 解决办法

问题概述 关于这个问题,后端接口开发完成,前端功能界面和函数方法体编写完成后,博主在前后端联调的时候遇到的,接口是调用成功了,但是没有返回任何结果, 错误信息:“ Referrer Policy: strict-…

C++中二叉树的非递归遍历方法2-1

1 二叉树简介 树是一种数学上的抽象,在算法的设计与分析中起到一个中心作用。树是有n个节点的有限集合。二叉树是树的一种特殊形式,这种树的每个节点最多有2个子节点。 2 二叉树的遍历方法 二叉树的遍历分为前序遍历、中序遍历、后序遍历和层序遍历四…

【华为上机真题 2022】寻找身高相近的小朋友

🎈 作者:Linux猿 🎈 简介:CSDN博客专家🏆,华为云享专家🏆,Linux、C/C、云计算、物联网、面试、刷题、算法尽管咨询我,关注我,有问题私聊! &…

力扣(LeetCode)147. 对链表进行插入排序(C++)

排序 ①遍历链表,当前遍历的结点记作 ppp 。 ②从前往后遍历链表,找到最后一个值小于 ppp 的结点 curcurcur 。 ③(关键操作) 插入,如图,将 ppp 插入 curcurcur 的后面。 p->next cur->next; cur->next p; p next;…

关于Mac启动人人开源前端项目遇到node-sass下载不了的问题!

今天在网上看到了一个前后端分离用户管理系统,于是心血来潮下载下来看一看,结果发现前端项目中用Mac开发的话坑比较多 1.关于node版本问题 node版本最好不要太高,我对于该项目使用的node版本是v10.16.3 node版本最好使用nvm来管理&#xff0c…

[附源码]Python计算机毕业设计Django的图书互换系统

项目运行 环境配置: Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术: django python Vue 等等组成,B/S模式 pychram管理等等。 环境需要 1.运行环境:最好是python3.7.7,…

java基于springboot的在线电影评论投票系统

项目介绍 随着信息技术和网络技术的飞速发展,人类已进入全新信息化时代,传统管理技术已无法高效,便捷地管理信息。为了迎合时代需求,优化管理效率,各种各样的管理系统应运而生,各行各业相继进入信息管理时代…

可以提高开发效率的vscode插件

1,koroFileHeader 我们在新建一个文件后,常常需要在文件头部加入默认注释,vscode中提供了一个 的插件,可以帮助我们实现。 1.1,安装插件 在vscode extensions中搜索并按照koroFileHeader 插件 installl完成后&…

大数据-HDFS的Shell操作

一、了解HDFS常用Shell命令 1、三种Shell命令方式 命令适用场合hadoop fs适用于任何不同的文件系统,比如本地文件系统和HDFS文件系统hadoop dfs只能适用于HDFS文件系统hdfs dfshdfs dfs跟hadoop dfs的命令作用一样,也只能适用于HDFS文件系统 2、常用HD…

基于C+++Mysql实现(WinForm)图书管理系统【100010034】

图书管理系统 实验内容、步骤以及结果 做出数据流图和数据字典。 在数据流图和字典的基础上做出 E-R 图(概念结构设计)。 学生: 图书: 管理员: 汇总: 在 E-R 图基础上进行关系模式设计(至少满足 3NF)&am…

b站黑马的Vue快速入门案例代码——计数器

目录 目标效果: 重点原理: 1.创建Vue实例的时候: 2.v-on——为元素绑定事件 3.v-text——【解析文本用】设置标签的文本值 v-text【简写】为{{}} 实现步骤: 代码部分: 1.计数器模板.html(全是重点&#xf…