深度学习之基础模型——循环神经网络RNN

相关资料

(1)What are Recurrent Neural Networks? | IBM
(2)浅析循环神经网络(RNN)的反向求导过程 - 知乎 (zhihu.com) 总共有四篇
(3)循环神经网络(RNN)浅析 - 简书 (jianshu.com)

引入

简单燃烧下卡路里

在深度学习中最基础也是最经典的三种分别是前馈神经网络(FNN)、卷积神经网络(CNN)、循环神经网络(RNN)。前馈神经网络最为简单易懂,通过参数传递和矩阵运算将数据从一个维度映射到另外一个维度。而卷积神经网络可以综合某个元素周围的元素进行映射。但是两者都不能够很好地去处理时间序列的问题,而循环神经网络 RNN (Recurrent neural networks) 则可以很好地处理这样的数据。这是因为,相比于前两者来说,RNN 假定输入的数据序列在时间维度上并不是等价的,而是有区分的。
比如现在我们想用神经网络处理行人的运动轨迹,如果我们用卷积神经网络,那么对于不同时间的轨迹数据,卷积权重都是一样的。这样可能会带来一定的问题,比如随着时间推移,一个人会变得越来越疲惫,那么其行动轨迹肯定与一开始的行动轨迹有很大区别。比如我们举下面一个例子:现在有个人在家 (home)和公园 (park)之间跑步进行锻炼,他往公园跑的时候体力比较充沛,所以跑的速度比较快。虽然他在公园休息了一会,跑回家的时候他还是逐渐体力不支速度逐渐变慢下来。
请添加图片描述

如果我们用 FNN 前馈神经网络去处理,那么我们需要让每个权重自己去学习参数,很容易忽略权重之间的关联性;如果我们用 CNN 卷积神经网络去处理,那么对于这个人精力充沛时候的运动数据和逐渐疲倦时候的运动数据处理的卷积权重参数都是一样的,过于将不同数据关联化(或者说是强行将所有数据等价化)。所以我们需要一种新的神经网络传递方式去处理这类数据。通过观察不难发现,这一系列运动数据之间是有关联的。比如当跑到公园之后才会休息;跑到公园消耗了很多体力之后,回来的跑步速度才会越来越慢 · · · · · · 这说明随着时间的发展,轨迹数据之间是有关联的。而反过来思考之前主要用于处理图像的 CNN,像素之间虽然确实可能存在潜在的关联,但是宏观角度我们并不清楚他们之间的联系,或者换句话说,图片像素之间的联系是空间维度,而并不是时间维度。

时间维度与空间维度

这个问题对于 RNN 来说其实比较重要,我只从辅助理解 RNN 的角度探讨这一问题,并不会全面而详细的论述其本质根源。为了方便理解,此处我们需要一个假定,我们假定下面说的空间指的是三维及以内的空间,而时间单独作为一个维度。
通常我们很容易区分这两个概念,空间维度就是我们存在的三维空间中,有鲜花有泪水也有那个相伴你一生的人;而时间维度就是看着你慢慢变老。但是当我们拓展一下,讨论广义的时间与空间,两者似乎并没有那么的清晰。比如,现在有一个句子:“你这么年轻怎么睡得着的?”,那么这个句子是更偏向于是存在时间维度
还是空间维度?如果我们从存在角度,这个句子如果写在纸上,那么其确实存在于空间维度,但是从理解角度,我们是从“你”字开始,依次往后看“这么”“年轻”“睡得着”,我们需要之前的汉字,才能辅助理解后面的汉字,乃至整个句子。如果语序发生改变句意很可能就完全不同:“这么年轻怎么睡得着你的?”,嗯,这句话就不太对劲了。
可以发现,无论是时间正向流淌的客观事实(别抬杠超过光速时间逆向),还是人为约定的看句子从左往右从上往下看,都具有时间维度的“特性”。个人认为,这种特性与空间维度区别比较大的一点在于,在时间维度每个时间点上,都有一个较为完整的“空间”。比如你在奔跑,每个时间点上都有一个完整的地球空间,而你正处于某个跑步姿势;比如你在阅读文字,每个字都是完整的一个个体,由它许多笔画组成。而三维空间并不存在时间的概念。此外,在时间维度这条线上,不同时间点的三维空间是相互联系的,尤其是正向关联。跑步变慢是因为之前跑太多消耗了太多精力;一个个单独的字组成了完整的有蕴含的一句话。

基本原理

先从最简单的入手

前面提到过,时间序列的正向关联十分重要,也就是上一个时间点对下一个时间点有较大的影响。我们还是以之前的跑步的例子为例。对于 FNN 来说,输入数据是经过一个权重 u 1 u_{1} u1 到隐藏的神经 (灰色)元,再从隐藏的神经元经过另外一个权重 v 1 v_{1} v1 得到输出结果,如下图 (a)。写成公式如下:
o u t p u t = v 1 ⋅ ( u 1 ⋅ t 1 ) output = v_{1}·(u_{1}·t_{1}) output=v1(u1t1)
其中 t 1 t_{1} t1 代表的是该时刻输入的数据。
请添加图片描述

如果我们希望 t 2 t_2 t2 时刻的输入受到 t 1 t_{1} t1 时刻输入的影响,我们可以将 t 1 t_1 t1 输入的隐藏变量乘以 w 1 w_{1} w1 再输入进 t 2 t_{2} t2 得到的隐藏变量,这样输入就拥有两个时刻输入数据的贡献,如上图 (b)。写成公式如下:
o u t p u t = v 1 ⋅ ( u 2 ⋅ t 2 + w 1 ⋅ ( u 1 ⋅ t 1 ) ) output=v_{1}·(u_{2}·t_{2}+w_{1}·(u_{1}·t_{1})) output=v1(u2t2+w1(u1t1))

有人可能会疑惑,为什么要将两个时刻的隐藏神经元数值相加,而不是直接将输入数据相加?
其实这里的隐藏神经元更像是经过了一种映射或者变换,原数据可能会有一些数量级不匹配等问题,而变成隐藏神经元之后会更加适合相加。

以此类推,我们会得到如图 ©图 (d)的参数传递方式。这样我们就将十个时刻人的跑步数据全部综合起来得到了这个输出结果,这个输出结果包含了完整的跑步位置信息。这就是 RNN 最简单的一种实现方式,其思想就是上文提到时间维度上的正向影响

高维信息的拓展

上面的例子中,输入数据时各个时刻人跑步的一维位置信息。很明显,这里做了极大地简化。真实的数据可能包括经纬度、速度加速度等等特征,这使得我们输入的数据变成了高维张量。我们对此处理的方式与 FNN 相类似,即将一个单一的元素(如下图 (a))转换成一个张量(如下图 (b))。
请添加图片描述

进一步拓展,中间的隐藏元素和输出维度都有可能会改变,这样就转化成了图 ©的形式。不难发现,这与 FNN (MLP)简直一模一样;然后就可以将这个替换原 RNN 中的图 (a)了,如下图:
请添加图片描述

学到这应该思考一下

请添加图片描述

还记得上文这个图嘛,此时我们已经对 RNN 有了一定的基础的了解,可以进一步思考为什么 RNN 更加适合处理时间序列。上文提到,FNN 不容易学习输入数据之间的关联性,而 RNN 通过隐藏神经元 (层)的传递将各个时间序列的数据都传递在了一起;CNN 会导致所有数据经过处理的参数都共享,失去了不同数据的独立性(过于关联、等价),而 RNN 虽然也共享参数,但是每个输入数据按照时间远近有不同的深度,比如 t 1 t_{1} t1 时刻要经过 9 个 W W W ,而 t 5 t_{5} t5 时刻只需要经过 5 个,通过深度对不同的时间点进行差异化。所以可以说,RNN 在某种意义上是 FNN 和 CNN 的中和。

这里个人觉得有必要补充一下为什么这些参数能够共享:
仍然以跑步为例。在现实情况中,之前的跑步距离等信息是会一直影响到最后的。刚开始如果跑步速度过快,很容易就过早疲惫,10 分钟可能就慢慢走回家,然后因为特别累直接倒在床上睡着了,然后导致白天睡多了晚上睡不着,晚上睡不着于是刷手机,然后刷手机刷 emo 了。可以发现,刚开始跑步速度过快其实是对 emo 有间接影响的,而刷手机是直接影响。无论是间接影响还是直接影响,都是在同一事件链下,必然有相似之处,所以可以共享参数,符合实际逻辑的同时,又可以减小参数量

不同的输入输出与中间层

上文介绍的 RNN 输入是 10 个时间点的数据,输出是 1 组。但是事实上,输入输出的维度是可以改变的。比如这 10 个时间点的跑步数据发生了缺失情况,则可以如下改变:
请添加图片描述

然后我们将中间多余的隐藏元删去,就可以得到不同输入的 RNN 了:
请添加图片描述

我们也可以进一步改变输出维度:
请添加图片描述

也可以如下改变:
请添加图片描述

有各种各样的排列组合方式。
类比于 FNN (MLP)和 CNN,RNN 也可以拥有更多的隐藏层。
请添加图片描述

反向传播 BPTT

这里有必要介绍一下 RNN 的反向传播 Backpropagation Through Time (BPTT),其与传统的 FNN 反向传播略有不同,并且了解 BPTT 的简单原理和结果对了解 RNN 的弱点以及 LSTM 提出的初衷有比较大的帮助。
请添加图片描述

这里不过多阐述其是如何推导的,因为过于理论,篇幅较长,先说结论,求完偏导后的公式结果如下 (以 4 层 RNN 为例):
∂ L ∂ V = ∂ L ∂ y ∂ y ∂ V ∂ L ∂ U = ∂ L ∂ y ∂ y ∂ T 4 ∂ T 4 ∂ U + ∂ L ∂ y ∂ y ∂ T 4 ∂ T 4 ∂ T 3 ∂ T 3 ∂ U + ∂ L ∂ y ∂ y ∂ T 4 ∂ T 4 ∂ T 3 ∂ T 3 ∂ T 2 ∂ T 2 ∂ U + ∂ L ∂ y ∂ y ∂ T 4 ∂ T 4 ∂ T 3 ∂ T 3 ∂ T 2 ∂ T 2 ∂ T 1 ∂ T 1 ∂ U ∂ L ∂ W = ∂ L ∂ y ∂ y ∂ T 4 ∂ T 4 ∂ W + ∂ L ∂ y ∂ y ∂ T 4 ∂ T 4 ∂ T 3 ∂ T 3 ∂ W + ∂ L ∂ y ∂ y ∂ T 4 ∂ T 4 ∂ T 3 ∂ T 3 ∂ T 2 ∂ T 2 ∂ W + ∂ L ∂ y ∂ y ∂ T 4 ∂ T 4 ∂ T 3 ∂ T 3 ∂ T 2 ∂ T 2 ∂ T 1 ∂ T 1 ∂ W \begin{aligned} \frac{\partial L}{\partial V}&=\frac{\partial L}{\partial y}\frac{\partial y}{\partial V} \\ \frac{\partial L}{\partial U}&=\frac{\partial L}{\partial y}\frac{\partial y}{\partial T_{4}}\frac{\partial T_{4}}{\partial U}+\frac{\partial L}{\partial y}\frac{\partial y}{\partial T_{4}}\frac{\partial T_{4}}{\partial T_{3}}\frac{\partial T_{3}}{\partial U}+\frac{\partial L}{\partial y}\frac{\partial y}{\partial T_{4}}\frac{\partial T_{4}}{\partial T_{3}}\frac{\partial T_{3}}{\partial T_{2}}\frac{\partial T_{2}}{\partial U}+\frac{\partial L}{\partial y}\frac{\partial y}{\partial T_{4}}\frac{\partial T_{4}}{\partial T_{3}}\frac{\partial T_{3}}{\partial T_{2}}\frac{\partial T_{2}}{\partial T_{1}}\frac{\partial T_{1}}{\partial U} \\ \frac{\partial L}{\partial W}&=\frac{\partial L}{\partial y}\frac{\partial y}{\partial T_{4}}\frac{\partial T_{4}}{\partial W}+\frac{\partial L}{\partial y}\frac{\partial y}{\partial T_{4}}\frac{\partial T_{4}}{\partial T_{3}}\frac{\partial T_{3}}{\partial W}+\frac{\partial L}{\partial y}\frac{\partial y}{\partial T_{4}}\frac{\partial T_{4}}{\partial T_{3}}\frac{\partial T_{3}}{\partial T_{2}}\frac{\partial T_{2}}{\partial W}+\frac{\partial L}{\partial y}\frac{\partial y}{\partial T_{4}}\frac{\partial T_{4}}{\partial T_{3}}\frac{\partial T_{3}}{\partial T_{2}}\frac{\partial T_{2}}{\partial T_{1}}\frac{\partial T_{1}}{\partial W} \end{aligned} VLULWL=yLVy=yLT4yUT4+yLT4yT3T4UT3+yLT4yT3T4T2T3UT2+yLT4yT3T4T2T3T1T2UT1=yLT4yWT4+yLT4yT3T4WT3+yLT4yT3T4T2T3WT2+yLT4yT3T4T2T3T1T2WT1
其实不难从中找到规律, U , W U,W U,W 其实就是多次使用链式法则累乘再相加。这样可能会带来一些问题,也是所有链式法则可能带来的问题,就是梯度消失以及梯度爆炸。

  • 梯度消失: 就是梯度过小导致梯度接近于 0 使得参数不再更新。在 RNN 中,数据经过每个神经元后会通过 tanh 激活函数,使得绝大部分数据的值小于 1。而随着 RNN 网络加深,许多小于 1 的值累乘会得到一个十分接近于 0 的数,这就是梯度消失的原因。
  • 梯度爆炸: 就是梯度过大导致梯度过高变成 NaN。这个同理梯度消失,当许多大于 1 的梯度相乘时,会导致梯度过大而没法正常进行反向传播。
    请添加图片描述
    从直观表现上,梯度消失和梯度爆炸都是由于输入的时序过于长,根据链式法则会使得梯度急剧增大或者减小。而这也是 RNN 比较大的缺点之一,由此提出了 LSTM 、GRU 进行改进。关于这两者的介绍,将放到后续博客中进行讲解

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

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

相关文章

【React】Day6

项目搭建 基于CRA创建项目 CRA是一个底层基于webpack快速创建React项目的脚手架工具 # 使用npx创建项目 npx create-react-app react-jike# 进入到项 cd react-jike# 启动项目 npm start调整项目目录结构 -src-apis 项目接口函数-assets 项目资源文件&…

springboot3 集成knife4j

knife4j介绍 Knife4j是一个集Swagger2 和 OpenAPI3为一体的增强解决方案。 springdoc地址:OpenAPI 3 Library for spring-boot Knife4j官网地址:Knife4j 集Swagger2及OpenAPI3为一体的增强解决方案. | Knife4j 环境介绍 java:17 Spring…

java 溯本求源之基础(十八)之Monitoring--jmc

1.JMC概述 JMC全称Java Mission Control,集成了多个功能强大的组件,其中最核心的两部分是管理控制台和Java Flight Recorder。管理控制台允许开发者实时监控应用的运行状态,捕捉各种性能指标;而Java Flight Recorder则提供了一种高…

ELK日志系统的搭建

文章目录 简介软件准备安装JDK下载Elasticsearch软件修改配置信息创建ElasticSearch运行用户、启动服务添加防火墙策略ElasticSearch-Head插件安装 安装Kibana下载软件包修改配置启动服务 安装Logstash安装包下载安装服务配置修改配置pipeline流水线服务配置文件 启动服务 全流…

腾讯云轻量应用服务器和CVM S5服务器有什么区别?

腾讯云轻量应用服务器和CVM云服务器S5有什么不同?性能哪个更好一些?CVM S5云服务器CPU采用2.5GHz主频的Intel Xeon Cascade Lake或者Intel Xeon Cooper Lake处理器,轻量不支持指定CPU,从功能、内网连通性、集群及公网带宽等方面对…

邂逅JavaScript逆向爬虫-------基础语法篇之面向对象

目录 一、概念二、对象的创建和操作2.1 JavaScript创建对象的方式2.2 对象属性操作的控制2.3 理解JavaScript创建对象2.3.1 工厂模式2.3.2 构造函数2.3.3 原型构造函数 三、继承3.1 通过原型链实现继承3.2 借用构造函数实现继承3.3 寄生组合式继承3.3.1 对象的原型式继承3.3.2 …

并发编程之线程通信及Condition的原理分析

1. synchronized中的线程通信 调用wait方法会使线程处于等待状态&#xff0c;直到另一个线程调用notify线程才会唤醒等待中的某个线程&#xff0c;生产者和消费者模型可以很好的使用到该例子。 生产者代码: public class Producer implements Runnable {private Queue<Str…

虚拟现实(VR)的应用场景

虚拟现实&#xff08;VR&#xff09;技术创建和体验三维虚拟世界的计算机仿真技术。用户通过佩戴VR头显等设备&#xff0c;可以完全沉浸在虚拟世界中&#xff0c;并与虚拟世界中的物体进行交互。VR技术具有广泛的应用前景&#xff0c;可以应用于各行各业。以下是一些VR的应用场…

STM32标准库编程与51单片机直接写寄存器的区别和联系

简介&#xff1a; 在学完51单片机之后&#xff0c;我们去学习32的时候&#xff0c;会发现编程的方法有很大的区别&#xff0c;让人非常的不适应&#xff0c;但是通过不断的调用相应外设的库函数之后&#xff0c;你也可以去编程STM32&#xff0c;来实现功能&#xff0c;但是你真…

SQL的基础语句

1、select语句 select colums from table_name 2、条件语句 #查询出查询出用户id为1和3的用户记录 IN 操作符允许我们在 WHERE 子句中规定多个值。 select * from student where id in (1,3) #查询出所有姓王的同学 模糊查询 like 通配符(% 任意多个字符 _单个字符) #下例…

如何使用渐变块创建自定义聊天机器人

如何使用渐变块创建自定义聊天机器人 文章目录 如何使用渐变块创建自定义聊天机器人一、介绍二、参考示例1、一个简单的聊天机器人演示2、将流式传输添加到您的聊天机器人3、喜欢/不喜欢聊天消息4、添加 Markdown、图像、音频或视频 一、介绍 **重要提示&#xff1a;**如果您刚…

软考高级架构师:AI 通俗讲解负载测试、压力测试、强度测试、容量测试和可靠性测试

在软件工程领域&#xff0c;测试是一个确保软件质量和性能的关键步骤。负载测试、压力测试、强度测试、容量测试和可靠性测试都是性能测试的不同类型&#xff0c;它们的目的和方法有所不同。 下面我将通过简单的比喻和解释&#xff0c;帮助您理解这些测试之间的区别。 负载测试…

跳跃游戏 II (贪心, 动态规划)

题目描述(力扣45题) : 给定一个长度为 n 的 0 索引整数数组 nums。初始位置为 nums[0]。 每个元素 nums[i] 表示从索引 i 向前跳转的最大长度。换句话说&#xff0c;如果你在 nums[i] 处&#xff0c;你可以跳转到任意 nums[i j] 处: 0 < j < nums[i] i j < n 返回到…

使用Unity扫描场景内的二维码,使用插件ZXing

使用Unity扫描场景内的二维码&#xff0c;使用插件ZXing 使用Unity扫描场景内的二维码&#xff0c;ZXing可能没有提供场景内扫描的方法&#xff0c;只有调用真实摄像机扫描二维码的方法。 实现的原理是&#xff1a;在摄像机上添加脚本&#xff0c;发射射线&#xff0c;当射线打…

【面试八股总结】Linux系统下的I/O多路复用

参考资料 &#xff1a;小林Coding、阿秀、代码随想录 I/O多路复用是⼀种在单个线程或进程中处理多个输入和输出操作的机制。它允许单个进程同时监视多个文件描述符(通常是套接字)&#xff0c;一旦某个描述符就绪&#xff08;一般是读就绪或者写就绪&#xff09;&#xff0c;能够…

分享三个转换速度快、准确率高的视频转文字工具

想要直接将视频转换成文字&#xff0c;转换工具很重要&#xff01;给大家分享三个转换速度快、准确率高的视频转文字工具&#xff0c;轻松完成转换。 1.网易见外 https://sight.youdao.com/ 网易家的智能转写翻译服务工作站&#xff0c;网页端就可以直接使用&#xff0c;支持视…

Spring Bean依赖注入-Spring入门(二)

1、SpringBean概述 在Spring中&#xff0c;一切Java对象都被视为Bean&#xff0c;用于实现某个具体功能。 Bean的依赖关系注入的过程&#xff0c;也称为Bean的装配过程。 Bean的装配方式有3种&#xff1a; XML配置文件注解Java类 Spring中常用的两种装配方式分别是基于XML的…

Codeforces Round 821 (Div. 2) D2. Zero-One

题目 #include <bits/stdc.h> using namespace std; #define int long long #define pb push_back #define fi first #define se second #define lson p << 1 #define rson p << 1 | 1 const int maxn 1e5 5, inf 1e18, maxm 4e4 5; const int N 1e6;c…

【MySQL】InnoDB与MyISAM存储引擎的区别与选择

存储引擎就是存储数据、建立索引、更新/查询数据等技术的实现方式 。 存储引擎是基于表的&#xff0c;而不是基于库的&#xff0c;所以存储引擎也可被称为表类型。我们可以在创建表的时候&#xff0c;来指定选择的存储引擎&#xff0c;如果没有指定将自动选择默认的存储引擎。…

【工具-PyCharm】

工具-PyCharm ■ PyCharm-简介■ PyCharm-安装■ PyCharm-使用■ 修改主题■ 设置字体■ 代码模板■ 解释器配置■ 文件默认编码■ 快捷键■ 折叠■ 移动■ 注释■ 编辑■ 删除■ 查看■ 缩进■ 替换 ■ PyCharm-简介 官方下载地址 Professional&#xff1a;专业版&#xff0…