【深度学习入门篇 ⑨】循环神经网络实战

【🍊易编橙:一个帮助编程小伙伴少走弯路的终身成长社群🍊】

大家好,我是小森( ﹡ˆoˆ﹡ ) ! 易编橙·终身成长社群创始团队嘉宾,橙似锦计划领衔成员、阿里云专家博主、腾讯云内容共创官、CSDN人工智能领域优质创作者 。


今天我们看一下用循环神经网络RNN的原理并且动手应用到案例。

3e012755cfd647aebdf70ff24536d38b.png

循环神经网络

在普通的神经网络中,信息的传递是单向的,这种限制虽然使得网络变得更容易学习,但在一定程度上也减弱了神经网络模型的能力。特别是在很多现实任务中,网络的输出不仅和当前时刻的输入相关,也和其过去一段时间的输出相关。此外,普通网络难以处理时序数据,比如视频、语音、文本等,时序数据的长度一般是不固定的,而前馈神经网络要求输入和输出的维数都是固定的,不能任意改变。因此,当处理这一类和时序相关的问题时,就需要一种能力更强的模型。

循环神经网络 (RNN)是一类具有短期记忆能力的神经网络。在循环神经网络中,神经元不但可以接受其它神经元的信息,也可以接受自身的信息,形成具有环路的网络结构。  

ab119b30479c4d74bb10bf02ef0d9f34.png

RNN比传统的神经网络多了一个循环圈,这个循环表示的就是在下一个时间步上会返回作为输入的一部分,我们把RNN在时间点上展开 :

6e2096802ad346c1836d1ede9370a9fe.png

💥在不同的时间步,RNN的输入都将与之前的时间状态有关 ,具体来说,每个时间步的RNN单元都会接收两个输入:当前时间步的外部输入和前一时间步(隐藏层)的输出状态。通过这种方式,RNN能够学习并理解数据中的长期依赖关系,使得它在处理文本生成、语音识别、时间序列预测等序列数据时表现尤为出色。

💥此外,RNN的隐藏状态(或称为内部状态)在每次迭代时都会更新,这种更新过程包含了当前输入和前一时间步状态的非线性组合,使得网络能够动态地调整其对序列中接下来内容的预测或理解。

d1ad2acff14b48458791021e8ce8eaa5.png

LSTM和GRU

传统的RNN在处理长序列数据时常常面临梯度消失或梯度爆炸的问题,这限制了其在处理长期依赖关系上的能力。为了克服这一局限性,LSTM(Long Short-Term Memory,长短期记忆网络)作为RNN的一种变体被引入。

LSTM是一种RNN特殊的类型,可以学习长期依赖信息。在很多问题上,LSTM都取得相当巨大的成功,并得到了广泛的应用。

48465d18371741739f23324e0f1f3e05.png

LSTM是通过一个叫做的结构实现,门可以选择让信息通过或者不通过。 这个门主要是通过sigmoid和点乘实现的 ;sigmoid 的取值范围是在(0,1)之间,如果接近0表示不让任何信息通过,如果接近1表示所有的信息都会通过。

  • 遗忘门通过sigmoid函数来决定哪些信息会被遗忘
  • 输入门决定哪些新的信息会被保留。

例如:

我昨天吃了拉面,今天我想吃炒饭,在这个句子中,通过遗忘门可以遗忘拉面,同时更新新的主语为炒饭。

输出门

我们需要决定什么信息会被输出,也是一样这个输出经过变换之后会通过sigmoid函数的结果来决定那些细胞状态会被输出。

  1. 前一次的输出和当前时间步的输入的组合结果通过sigmoid函数进行处理得到O_t

  2. 更新后的细胞状态C_t会经过tanh层的处理,把数据转化到(-1,1)的区间

  3. tanh处理后的结果和O_t进行相乘,把结果输出同时传到下一个LSTM的单元

8ca0b205bcfa44e18c3af5b4f7271880.png

GRU

GRU是一种LSTM的变形版本, 它将遗忘和输入门组合成一个“更新门”。它还合并了单元状态和隐藏状态,并进行了一些其他更改,由于他的模型比标准LSTM模型简单,所以越来越受欢迎。

664e50357e604f918c707643ca15bc9c.png

  • GRU的优势:

    • GRU和LSTM作用相同, 在捕捉长序列语义关联时, 能有效抑制梯度消失或爆炸, 效果都优于传统RNN且计算复杂度相比LSTM要小
  • GRU的缺点:

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

b429639b6a994ec099f87d8adf609263.png

双向LSTM

单向的 RNN,是根据前面的信息推出后面的,但有时候只看前面的词是不够的, 可能需要预测的词语和后面的内容也相关,那么此时需要一种机制,能够让模型不仅能够从前往后的具有记忆,还需要从后往前需要记忆。此时双向LSTM就可以帮助我们解决这个问题

f990226c2e3a4c9da262cc74ff2201e4.png

由于是双向LSTM,所以每个方向的LSTM都会有一个输出,最终的输出会有2部分,所以往往需要concat的操作。

96f81f98d8e74dadaa1f4925a3406007.pngRNN实现文本情感分类 

torch.nn.LSTM(input_size,hidden_size,num_layers,batch_first,dropout,bidirectional)
  1. input_size:输入数据的形状,即embedding_dim

  2. hidden_size:隐藏层神经元的数量,即每一层有多少个LSTM单元

  3. num_layer :即RNN的中LSTM单元的层数

  4. batch_first:默认值为False,输入的数据需要[seq_len,batch,feature],如果为True,则为[batch,seq_len,feature]

  5. dropout:dropout的比例,默认值为0。dropout是一种训练过程中让部分参数随机失活的一种方式,能够提高训练速度,同时能够解决过拟合的问题。

  6. bidirectional:是否使用双向LSTM,默认是False

实例化LSTM对象之后,不仅需要传入数据,还需要前一次的h_0(前一次的隐藏状态)和c_0

LSTM的默认输出为output, (h_n, c_n)  

  1. output(seq_len, batch, num_directions * hidden_size)--->batch_first=False

  2. h_n:(num_layers * num_directions, batch, hidden_size)

  3. c_n: (num_layers * num_directions, batch, hidden_size)

 4b9843ea2e35484f86a90641afd0fff6.png

LSTM和GRU的使用注意点

  1. 第一次调用之前,需要初始化隐藏状态,如果不初始化,默认创建全为0的隐藏状态

  2. 往往会使用LSTM or GRU 的输出的最后一维的结果,来代表LSTM、GRU对文本处理的结果,其形状为[batch, num_directions*hidden_size]

使用LSTM完成文本情感分类

class IMDBLstmmodel(nn.Module):def __init__(self):super(IMDBLstmmodel,self).__init__()self.hidden_size = 64self.embedding_dim = 200self.num_layer = 2self.bidriectional = Trueself.bi_num = 2 if self.bidriectional else 1self.dropout = 0.5self.embedding = nn.Embedding(len(ws),self.embedding_dim,padding_idx=ws.PAD) #[N,300]self.lstm = nn.LSTM(self.embedding_dim,self.hidden_size,self.num_layer,bidirectional=True,dropout=self.dropout)self.fc = nn.Linear(self.hidden_size*self.bi_num,20)self.fc2 = nn.Linear(20,2)def forward(self, x):x = self.embedding(x)x = x.permute(1,0,2) h_0,c_0 = self.init_hidden_state(x.size(1))_,(h_n,c_n) = self.lstm(x,(h_0,c_0))out = torch.cat([h_n[-2, :, :], h_n[-1, :, :]], dim=-1)out = self.fc(out)out = F.relu(out)out = self.fc2(out)return F.log_softmax(out,dim=-1)def init_hidden_state(self,batch_size):h_0 = torch.rand(self.num_layer * self.bi_num, batch_size, self.hidden_size).to(device)c_0 = torch.rand(self.num_layer * self.bi_num, batch_size, self.hidden_size).to(device)return h_0,c_0

为了提高程序的运行速度,可以考虑把模型放在GPU上运行:

  1. device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

  2. model.to(device)

train_batch_size = 64
test_batch_size = 5000
imdb_model = IMDBLstmmodel().to(device) 
optimizer = optim.Adam(imdb_model.parameters())
criterion = nn.CrossEntropyLoss()def train(epoch):mode = Trueimdb_model.train(mode)train_dataloader =get_dataloader(mode,train_batch_size)for idx,(target,input,input_lenght) in enumerate(train_dataloader):target = target.to(device)input = input.to(device)optimizer.zero_grad()output = imdb_model(input)loss = F.nll_loss(output,target) loss.backward()optimizer.step()if idx %10 == 0:pred = torch.max(output, dim=-1, keepdim=False)[-1]acc = pred.eq(target.data).cpu().numpy().mean()*100.print('Train Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.6f}\t ACC: {:.6f}'.format(epoch, idx * len(input), len(train_dataloader.dataset),100. * idx / len(train_dataloader), loss.item(),acc))torch.save(imdb_model.state_dict(), "model/mnist_net.pkl")torch.save(optimizer.state_dict(), 'model/mnist_optimizer.pkl')def test():mode = Falseimdb_model.eval()test_dataloader = get_dataloader(mode, test_batch_size)with torch.no_grad():for idx,(target, input, input_lenght) in enumerate(test_dataloader):target = target.to(device)input = input.to(device)output = imdb_model(input)test_loss  = F.nll_loss(output, target,reduction="mean")pred = torch.max(output,dim=-1,keepdim=False)[-1]correct = pred.eq(target.data).sum()acc = 100. * pred.eq(target.data).cpu().numpy().mean()print('idx: {} Test set: Avg. loss: {:.4f}, Accuracy: {}/{} ({:.2f}%)\n'.format(idx,test_loss, correct, target.size(0),acc))if __name__ == "__main__":test()for i in range(10):train(i)test()

💯然后由大家写代码得到模型训练的最终输出,大家可以改变模型来观察不同的结果。

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

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

相关文章

【一刷《剑指Offer》】面试题 48:不能被继承的类

《剑指Offer》对应内容: 可参考: 【C】继承 -- 详解_c,两个派生类继承一个基类,声明对象的时候用基类的对象。-CSDN博客

每日OJ_牛客_WY33 计算糖果

目录 牛客_WY33 计算糖果 解析代码 牛客_WY33 计算糖果 计算糖果_牛客题霸_牛客网 解析代码 A - B aB - C bA B cB C d 这道题目的实质是:判断三元一次方程组是否有解及求解, 13可以得到A(ac)/2;4-2可以得到C(d-b)/2; 24可以得到B2…

WebGSI地图切片|栅格地图切片原理|地图矢量切片原理

介绍 图栅格切片是WebGIS中使用的一种新技术,通过地图栅格切片可以有效缩短服务器的地图生成时间和地图传输时间,提高系统的响应速度。 地图切片是在多个比例尺下配置地图,预先将每个比例尺下的地图绘制成小图片,保存到服务器上一…

Python 爬虫实战----3(实力展现)

实战:获取豆瓣电影top250的电影名字 1.获取url:打开网站按发f12,点击网络,刷新找到第一个截取url和User-Agent。 2.请求爬取数据 mport requests import fake_useragent from lxml import etree import re #UA head {"User…

Android AutoSize屏幕适配:适配不同屏幕大小的尺寸,让我们无需去建立多个尺寸资源文件

目录 AutoSize是什么 AutoSize如何使用 一、AndroidautoSize是什么 在开发产品的时候,我们会遇到各种各样尺寸的屏幕,如果只使用一种尺寸去定义控件、文字的大小,那么到时候改起来就头皮发麻。以前使用dime的各种类库,文件太多…

PHP 7 新特性

PHP 7 新特性 PHP 7,作为PHP语言的一个重要版本,引入了许多新特性和性能改进,对开发效率和代码执行效率都有显著提升。本文将详细介绍PHP 7的一些主要新特性。 1. 性能提升 PHP 7最大的亮点之一是其性能的大幅提升。根据官方数据&#xff…

Spark调优特殊case- Task倾斜

首先我们观察下上面的stage5, Task MaxTime2.4Min, 但是stage5的整体耗时竟然可以达到55Min, 其实分区1000, 300个executor, 按照最大的TaskTime2.4Min来估算所有Task运行完成时间, 那么时间应该是- 2.4Min * 3 2.4Min 9.6Min 也就是最慢也就跑10分钟就…

对JVM及Java并发编程的简单了解

目录 引言 一、JVM内存结构 1. 程序计数器(Program Counter Register) 2. Java虚拟机栈(Java Virtual Machine Stack) 3. 本地方法栈(Native Method Stack) 4. 堆内存(Heap Memory&#x…

域名SSL证书安装记录(Nginx)

Tomcat和Nginx使用证书的方法不一样 1.在腾讯云控制台申请证书 需要按照流程,加上一条CNAME记录 2.将证书拷贝到Nginx所在的服务器上 例如: /usr/local/webserver/nginx/sslcertificate/followmentor.com_nginx3.配置nginx.conf 找域名对应443端口…

C++ | Leetcode C++题解之第274题H指数

题目&#xff1a; 题解&#xff1a; class Solution { public:int hIndex(vector<int>& citations) {int left0,rightcitations.size();int mid0,cnt0;while(left<right){// 1 防止死循环mid(leftright1)>>1;cnt0;for(int i0;i<citations.size();i){if(…

Kubernetes集群安装步骤

前言&#xff1a;本博客仅作记录学习使用&#xff0c;部分图片出自网络&#xff0c;如有侵犯您的权益&#xff0c;请联系删除 一、安装要求 在开始之前&#xff0c;部署Kubernetes集群集群需要满足以下几个条件&#xff1a; 一台多多台机器&#xff0c;操作系统CentOS.x-86_x…

数据结构——栈(顺序结构)

一、栈的定义 栈是一种数据结构&#xff0c;它是一种只能在一端进行插入和删除操作的特殊线性表。这一端被称为栈顶&#xff0c;另一端被称为栈底。栈按照后进先出&#xff08;LIFO&#xff09;的原则进行操作&#xff08;类似与手枪装弹后射出子弹的顺序&#xff09;。在计算…

【51项目】基于51单片机protues交通灯的设计(完整资料源码)

基于51单片机protues交通灯的设计 一、 项目背景 1.1背景 随着科技的不断发展,LED技术在交通领域的应用越来越广泛。LED模拟交通灯作为一种新型的交通信号控制设备,以其高效、节能、环保等优点,逐渐取代了传统的交通信号灯。近年来,我国城市化进程不断加快,城市人口和车辆…

iOS应用冷启动优化,可以做哪些事情

main()函数之后 首屏渲染不需要的&#xff0c;在首屏渲染完成后&#xff0c;异步执行&#xff1b;首屏渲染必要的&#xff0c;梳理依赖关系&#xff0c;生成启动树&#xff08;startTree&#xff09;&#xff0c;调用 root 节点的 start 方法&#xff0c;依次执行各个节点&…

服务攻防-应用协议cve

Cve-2015-3306 背景&#xff1a; ProFTPD 1.3.5中的mod_copy模块允许远程攻击者通过站点cpfr和site cpto命令读取和写入任意文件。 任何未经身份验证的客户端都可以利用这些命令将文件从文件系统的任何部分复制到选定的目标。 复制命令使用ProFTPD服务的权限执行&#xff0c;…

qt-C++笔记之json文件内容操作完整例程

qt-C笔记之json文件内容操作完整例程 code review! 文章目录 qt-C笔记之json文件内容操作完整例程1.运行输出2.运行后的test.json文件内容3.main.cpp 1.运行输出 读取到的 JSON 对象: {"Array": ["Item1","Item2"],"Name": "Ex…

掌握Xcode后台处理的艺术:iOS应用的隐形力量

掌握Xcode后台处理的艺术&#xff1a;iOS应用的隐形力量 在iOS应用开发中&#xff0c;后台处理能力是提升用户体验的关键因素之一。无论是在后台下载数据、播放音乐&#xff0c;还是在后台完成长时间运行的任务&#xff0c;Xcode都提供了强大的工具和API来支持这些操作。本文将…

jvm-证明cpu指令是乱序执行的案例

package jvm;/*** 证明cpu指令是乱序执行的** author 1* version 1.0* description: TODO* date 2024-07-19 9:31*/ public class T04_Disorder {private static int x 0, y 0;private static int a 0, b 0;public static void main(String[] args) throws InterruptedExcep…

B树:高效的数据存储结构

在计算机科学中&#xff0c;B树&#xff08;B-Tree&#xff09;是一种平衡多路查找树&#xff0c;它广泛应用于数据库和文件系统等需要高效数据存储和检索的场景。B树的设计旨在优化磁盘I/O操作&#xff0c;通过减少磁盘访问次数来提高数据检索的效率。本文将介绍B树的基本概念…

配置web服务器

当访问网站www.haha.com时显示&#xff1a;haha&#xff1b;当访问网站www.xixi.com/secret/显示&#xff1a;this is secret 第一步&#xff0c;配置一个新的IP 确认后 esc返回 第二步&#xff1a;重启ens160 第三步&#xff1a;创建目录&#xff0c;并且在文件内写入内容 第…