24/10/14 算法笔记 循环神经网络RNN

RNN:

        一种专门用于处理序列数据的神经网络,它能够捕捉时间序列中的动态特征。RNN的核心特点是其循环连接,这允许网络在不同时间步之间传递信息,从而实现对序列数据的记忆和处理能力。

应用的场景:

自然语言处理(NLP)语音识别,时间序列预测(天气预报,股票),机器人控制(预测动作),图像处理

在前向传播过程中,RNN利用前一时间步的隐藏状态和当前时间步的输入来计算当前时间步的隐藏状态和输出,这种循环连接允许RNN在处理序列数据时考虑时间依赖性,从而在多种应用中表现出色。

然而,RNN在训练过程中可能会遇到梯度消失和梯度爆炸的问题,尤其是在处理长序列时。为了解决这些问题,研究者们开发了LSTM(长短期记忆网络)和GRU(门控循环单元)等变体,它们通过引入门控机制来控制信息的流动,从而有效地解决了梯度问题,并提高了RNN在长序列数据上的性能。

隐状态:

它代表了网络在处理序列数据时的内部记忆或信息状态。隐状态是网络在每个时间步的内部表示,它携带了序列中之前信息的累积效应,并用于预测当前时间步的输出。

  1. 信息的累积: 隐状态捕捉了序列中之前所有时间步的信息。在处理序列数据时,如文本、语音或时间序列数据,隐状态帮助网络记住重要的上下文信息。

  2. 序列依赖性: 由于隐状态的存在,RNN能够处理输入数据之间的序列依赖性。这意味着网络的输出不仅依赖于当前的输入,还依赖于之前的输入。

困惑度:困惑度(Perplexity)是一个衡量语言模型性能的指标,尤其在自然语言处理(NLP)领域中。它主要用于评估语言模型对文本序列的预测能力。困惑度越低,表示模型对数据的预测越准确。

困惑度可以被解释为模型在预测下一个词时的平均分支数。例如,如果困惑度为 100,这意味着对于每个词,模型平均需要从 100 个可能的词中选择下一个词。因此,困惑度越低,表示模型的预测越准确。困惑度常用于比较不同的语言模型或评估模型在不同数据集上的性能。它也用于监控模型训练过程中的性能变化,帮助确定何时停止训练以避免过拟合。

循环神经网络的实现

初始化返回隐状态的函数

def __init_rnn_state(batch_size,num_hiddens,device):return(torch.zeros((batch_size,num_hiddens),device = device),)

在一个时间步内计算隐状态和输出

RNN的前向传播

def rnn(inputs,state,params):W_xh,W_hh,b_h,W_hq,b_q = paramsH, = state #这里的逗号 , 是必需的,它告诉 Python 解释器 H 是一个单独的元素,而不是一个元组。如果没有逗号,H = state 将会尝试将整个 state 赋值给变量 Houtputs = []for X in inputs:H = torch.tanh(torch.mm(X,W_xh)+torch.mm(H,W_hh)+b_h)Y = torch.mm(H, W_hq) + b_q   #torch.mm矩阵乘法outputs.append(Y)return torch.cat(outputs, dim=0), (H,)

包装

class RNNModelScratch: #@save"""从零开始实现的循环神经网络模型"""def __init__(self, vocab_size, num_hiddens, device,get_params, init_state, forward_fn):self.vocab_size, self.num_hiddens = vocab_size, num_hiddensself.params = get_params(vocab_size, num_hiddens, device)self.init_state, self.forward_fn = init_state, forward_fndef __call__(self, X, state):X = F.one_hot(X.T, self.vocab_size).type(torch.float32)return self.forward_fn(X, state, self.params)def begin_state(self, batch_size, device):return self.init_state(batch_size, self.num_hiddens, device)

检查输出是否具有正确的形状

num_hiddens = 512
net = RNNModelScratch(len(vocab), num_hiddens, d2l.try_gpu(), get_params,init_rnn_state, rnn)
state = net.begin_state(X.shape[0], d2l.try_gpu())
Y, new_state = net(X.to(d2l.try_gpu()), state)
Y.shape, len(new_state), new_state[0].shape

 预测

其中的prefix是一个用户提供的包含多个字符的字符串。 在循环遍历prefix中的开始字符时, 我们不断地将隐状态传递到下一个时间步,但是不生成任何输出。 这被称为预热(warm-up)期, 因为在此期间模型会自我更新(例如,更新隐状态), 但不会进行预测。 预热期结束后,隐状态的值通常比刚开始的初始值更适合预测, 从而预测字符并输出它们。
def predict_ch8(prefix, num_preds, net, vocab, device):  #@save"""在prefix后面生成新字符"""state = net.begin_state(batch_size=1, device=device)outputs = [vocab[prefix[0]]]get_input = lambda: torch.tensor([outputs[-1]], device=device).reshape((1, 1))for y in prefix[1:]:  # 预热期_, state = net(get_input(), state)outputs.append(vocab[y])for _ in range(num_preds):  # 预测num_preds步y, state = net(get_input(), state)outputs.append(int(y.argmax(dim=1).reshape(1)))return ''.join([vocab.idx_to_token[i] for i in outputs])

梯度裁剪

def grad_clipping(net, theta):  #@save"""裁剪梯度"""if isinstance(net, nn.Module):params = [p for p in net.parameters() if p.requires_grad]else:params = net.paramsnorm = torch.sqrt(sum(torch.sum((p.grad ** 2)) for p in params))if norm > theta:for param in params:param.grad[:] *= theta / norm

训练

def train_epoch_ch8(net, train_iter, loss, updater, device, use_random_iter):"""训练网络一个迭代周期(定义见第8章)"""state, timer = None, d2l.Timer()metric = d2l.Accumulator(2)  # 训练损失之和,词元数量for X, Y in train_iter:if state is None or use_random_iter:# 在第一次迭代或使用随机抽样时初始化statestate = net.begin_state(batch_size=X.shape[0], device=device)else:if isinstance(net, nn.Module) and not isinstance(state, tuple):# state对于nn.GRU是个张量state.detach_()else:# state对于nn.LSTM或对于我们从零开始实现的模型是个张量for s in state:s.detach_()y = Y.T.reshape(-1)X, y = X.to(device), y.to(device)y_hat, state = net(X, state)l = loss(y_hat, y.long()).mean()if isinstance(updater, torch.optim.Optimizer):updater.zero_grad()l.backward()grad_clipping(net, 1)updater.step()else:l.backward()grad_clipping(net, 1)# 因为已经调用了mean函数updater(batch_size=1)metric.add(l * y.numel(), y.numel())return math.exp(metric[0] / metric[1]), metric[1] / timer.stop()

用高级API实现

def train_ch8(net, train_iter, vocab, lr, num_epochs, device,use_random_iter=False):"""训练模型(定义见第8章)"""loss = nn.CrossEntropyLoss()animator = d2l.Animator(xlabel='epoch', ylabel='perplexity',legend=['train'], xlim=[10, num_epochs])# 初始化if isinstance(net, nn.Module):updater = torch.optim.SGD(net.parameters(), lr)else:updater = lambda batch_size: d2l.sgd(net.params, lr, batch_size)predict = lambda prefix: predict_ch8(prefix, 50, net, vocab, device)# 训练和预测for epoch in range(num_epochs):ppl, speed = train_epoch_ch8(net, train_iter, loss, updater, device, use_random_iter)if (epoch + 1) % 10 == 0:print(predict('time traveller'))animator.add(epoch + 1, [ppl])print(f'困惑度 {ppl:.1f}, {speed:.1f} 词元/秒 {str(device)}')print(predict('time traveller'))print(predict('traveller'))
num_epochs, lr = 500, 1
train_ch8(net, train_iter, vocab, lr, num_epochs, d2l.try_gpu())

检查一下使用随机抽样方法的结果

net = RNNModelScratch(len(vocab), num_hiddens, d2l.try_gpu(), get_params,init_rnn_state, rnn)
train_ch8(net, train_iter, vocab, lr, num_epochs, d2l.try_gpu(),use_random_iter=True)

循环神经网络的简洁实现

定义模型

num_hiddens = 256
rnn_layer = nn.RNN(len(vocab), num_hiddens)

使用张量来初始化隐状态

state = torch.zeros((1, batch_size, num_hiddens))

通过一个隐状态和一个输入,我们就可以用更新后的隐状态计算输出。

X = torch.rand(size=(num_steps, batch_size, len(vocab)))
Y, state_new = rnn_layer(X, state)
Y.shape, state_new.shape

为一个完整的循环神经网络模型定义一个RNNModel

class RNNModel(nn.Module):"""循环神经网络模型"""def __init__(self, rnn_layer, vocab_size, **kwargs):super(RNNModel, self).__init__(**kwargs)self.rnn = rnn_layerself.vocab_size = vocab_sizeself.num_hiddens = self.rnn.hidden_size# 如果RNN是双向的(之后将介绍),num_directions应该是2,否则应该是1if not self.rnn.bidirectional:self.num_directions = 1self.linear = nn.Linear(self.num_hiddens, self.vocab_size)else:self.num_directions = 2self.linear = nn.Linear(self.num_hiddens * 2, self.vocab_size)def forward(self, inputs, state):X = F.one_hot(inputs.T.long(), self.vocab_size)X = X.to(torch.float32)Y, state = self.rnn(X, state)# 全连接层首先将Y的形状改为(时间步数*批量大小,隐藏单元数)# 它的输出形状是(时间步数*批量大小,词表大小)。output = self.linear(Y.reshape((-1, Y.shape[-1])))return output, statedef begin_state(self, device, batch_size=1):if not isinstance(self.rnn, nn.LSTM):# nn.GRU以张量作为隐状态return  torch.zeros((self.num_directions * self.rnn.num_layers,batch_size, self.num_hiddens),device=device)else:# nn.LSTM以元组作为隐状态return (torch.zeros((self.num_directions * self.rnn.num_layers,batch_size, self.num_hiddens), device=device),torch.zeros((self.num_directions * self.rnn.num_layers,batch_size, self.num_hiddens), device=device))

训练与预测

device = d2l.try_gpu()
net = RNNModel(rnn_layer, vocab_size=len(vocab))
net = net.to(device)
d2l.predict_ch8('time traveller', 10, net, vocab, device)

由于深度学习框架的高级API对代码进行了更多的优化, 该模型在较短的时间内达到了较低的困惑度。

  • 相比从零开始实现的循环神经网络,使用高级API实现可以加速训练。

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

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

相关文章

[241021] X-CMD 内测版 v0.4.12 新功能: starship ohmyposh ping tping docker ascii

目录 X-CMD 发布内测版 v0.4.12📃Changelog🎨 starship🎨 ohmyposh🎨 theme🌐 ping🌐 tping🐋 docker💻 mac - 集成 MacOS 实用功能🔄 ascii🦖 deno&#x1f…

探索秘境:如何使用智能体插件打造专属的小众旅游助手『小众旅游探险家』

文章目录 摘要引言智能体介绍和亮点展示介绍亮点展示 已发布智能体运行效果智能体创意想法创意想法创意实现路径拆解 如何制作智能体可能会遇到的几个问题快速调优指南总结未来展望 摘要 本文将详细介绍如何使用智能体平台开发一款名为“小众旅游探险家”的旅游智能体。通过这…

怎么设置打别人电话显示自己公司名称?

在日常生活中,想必许多人都曾接到过显示公司名称的来电。相较于常规的电话号码,这类带有企业信息的来电无疑更具可信度,让人更愿意接听。在这个骚扰电话和推销电话泛滥、信任缺失的现代社会,这些能够自证身份的电话号码就像是一张…

职场经验:如何封装自动化测试框架?

封装自动化测试框架,测试人员不用关注框架的底层实现,根据指定的规则进行测试用例的创建、执行即可,这样就降低了自动化测试门槛,能解放出更多的人力去做更深入的测试工作。 本篇文章就来介绍下,如何封装自动化测试框…

filebeat接入nginx和mysql获取日志

下载nginx (1) 直接下载 yum install nginx -y(2)查看状态启动 systemctl start nginx systemctl status nginx(3)配置文件检查 nginx -t(4)端口检查 netstat -tulpn | grep :80&am…

Linux系统:配置Apache支持CGI(Ubuntu)

配置Apache支持CGI 根据以下步骤配置,实现Apache支持CGI 安装Apache: 可参照文章: Ubuntu安装Apache教程。执行以下命令,修改Apache2配置文件000-default.conf: sudo vim /etc/apache2/sites-enabled/000-default.con…

相同的树算法

给你两棵二叉树的根节点 p 和 q ,编写一个函数来检验这两棵树是否相同。 如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。 示例 1: 输入:p [1,2,3], q [1,2,3] 输出:true示例 2&…

屏幕画面卡住不动声音正常怎么办?电脑屏幕卡住不动解决方法

在数字时代,电脑作为我们日常生活与工作中不可或缺的伙伴,偶尔也会遇到一些小状况。其中,“屏幕画面卡住不动,但是声音依然正常”的情况就是一种常见的问题。本文将探讨这一现象的原因,并提供几种可能的解决方案&#…

Pyqt5设计打开电脑摄像头+可选择哪个摄像头(如有多个)

目录 专栏导读库的安装代码介绍完整代码总结 专栏导读 🌸 欢迎来到Python办公自动化专栏—Python处理办公问题,解放您的双手 🏳️‍🌈 博客主页:请点击——> 一晌小贪欢的博客主页求关注 👍 该系列文…

注册安全分析报告:北外网校

前言 由于网站注册入口容易被黑客攻击,存在如下安全问题: 暴力破解密码,造成用户信息泄露短信盗刷的安全问题,影响业务及导致用户投诉带来经济损失,尤其是后付费客户,风险巨大,造成亏损无底洞…

安装Maven配置以及构建Maven项目(2023idea)

一、下载Maven绿色软件 地址:http://maven.apache.org/download.cgi 尽量不要选择最高版本的安装,高版本意味着高风险的不兼容问题,选择低版本后续问题就少。你也可以选择尝试。 压缩后: 打开后: 在该目录下新建mvn-…

手机思维导图怎么制作?5个软件教你在手机上绘制思维导图

手机思维导图怎么制作?5个软件教你在手机上绘制思维导图 在手机上制作思维导图不仅可以帮助你快速理清思路,还可以随时随地进行创作和调整。以下是5款适合手机上绘制思维导图的软件,它们功能强大、操作简单,帮助你轻松上手。 迅…

2024年游戏买量还有空间吗?

本人从事游戏行业多年,一直做游戏分发的工作,但近年来随着我国大经济背景的整体向下,不仅仅影响了实体企业,游戏行业买量也明显受到影响。 2024年,游戏买量市场呈现出以下几个主要特点: 小游戏买量爆发&am…

大模型好书推荐 | 从入门到实践:极简大模型应用开发指南

今天给大家推荐一本大模型应用开发入门书籍《大模型应用开发极简入门》,本书对很多AI概念做了讲解和说明,主要讲解了以下几个方面的大模型技术: GPT-4和ChatGPT的工作原理: 书中详细介绍了这两个先进的语言模型的基本原理&#…

C++ : STL容器之list剖析

STL容器之list剖析 一、几个重要接口(一)push_back 与 emplace_back(二)sort1、系统中的sort2、list中的sort (三)splice(四)unique 和 merge1、unique2、merge 二、list的模拟实现&…

新手小白,如何研究货币相关性

研究货币对之间的相关性可以帮助交易者理解市场动态,从而优化交易策略。以下是一个详细的研究方向,包括每个步骤的代码,以及一些深入探索的建议。 研究方向 选择货币对:确定需要研究的两个货币对。 数据收集:获取选…

如何保证Redis和数据库的数据一致性

文章目录 0. 前言1. 补充知识:CP和AP2. 什么情况下会出现Redis与数据库数据不一致3. 更新缓存还是删除缓存4. 先操作缓存还是先操作数据库4.1 先操作缓存4.1.1 数据不一致的问题是如何产生的4.1.2 解决方法(延迟双删)4.1.3 最终一致性和强一致…

【Postman】如何导出导入数据文件?Postman链接分享?

方式一:postman分享链接 1.1 导出 1.2 导入 1.3 导入完成后删除分享的链接 方式二:postman导出导入json 2.1 导出 2.2 post导入json数据

基于asp.NET的图书借阅系统

文章目录 前言项目介绍技术介绍功能介绍核心代码数据库参考 系统效果图 前言 文章底部名片,获取项目的完整演示视频,免费解答技术疑问 项目介绍 随着科学技术水平的逐年发展,构建一个高效、便捷的图书借阅系统。解决传统图书馆借阅过程中存…

全面了解CAN总线协议

提及总线,总是让人联想到那些交错在一起的计算机电线。那么这些电线如何发挥功效呢?这还得配合总线协议的管理来使用。那么今天我们介绍的就是CAN总线协议。看看这个协议的含义和应用吧。 CAN总线协议基本概念 1. 报文 总线上的信息以不同格式的报文发…