【NLP】循环神经网络RNN

news2025/2/22 17:31:52

目录

一、认识RNN

二、RNN模型分类

三、传统RNN模型

3.1 结构分析

3.2 Pytorch构建RNN模型

3.3 优缺点


一、认识RNN

RNN(Recurrent Neural Network),中文称作循环神经网络,一般以序列数据为输入,通过网络内部的结构设计有效捕捉序列之间的关系特征,一般也是以序列形式进行输出

一般单层神经网络结构:

RNN单层网络结构:

以时间步对RNN进行展开后的单层网络结构:

RNN的循环机制使模型隐层上一时间步产生的结果,能够作为当下时间步输入的一部分(当下时间步的输入除了正常的输入外还包括上一步的隐层输出)对当下时间步的输出产生影响

因为RNN结构能够很好利用序列之间的关系,因此针对自然界具有连续性的输入序列,如人类的语言、语音等进行很好的处理,广泛应用于NLP领域的各项任务,如文本分类、情感分析、意图识别、机器翻译等

第一步:用户输入了"What time is it ?",首先需要进行分词,因为RNN是按照顺序工作的,每次只接收一个单词进行处理

第二步:先将单词"What"输送给RNN,将产生一个输出O1

第三步:继续将单词"time"输送给RNN,但此时RNN不仅仅利用"time"来产生输出O2,还会使用来自上一层隐层输出O1作为输入信息

第四步:重复上述步骤,直到处理完所有单词,将隐层输出O5进行处理来解析用户意图

二、RNN模型分类

按照输入和输出的结构进行分类:

  • N vs N - RNN
  • N vs 1 - RNN
  • 1 vs N - RNN
  • N vs M - RNN

按照RNN的内部构造进行分类:

  • 传统RNN
  • LSTM
  • Bi-LSTM
  • GRU
  • Bi-GRU

N vs N - RNN

RNN最基础的结构形式,最大的特点就是:输入和输出序列是等长的。由于这个限制的存在,使其适用范围比较小,可用于生成等长度的合辙诗句

N vs 1 - RNN

有时候要处理的问题输入是一个序列,而要求输出是一个单独的值而不是序列,应该怎样建模呢?只要在最后一个隐层输出h上进行线性变换就可以了,大部分情况下,为了更好的明确结果,还要使用 sigmoid 或者 softmax 进行处理。这种结构经常被应用在文本分类问题上

1 vs N - RNN

若输入不是序列而输出为序列的情况怎么处理呢?最常采用的一种方式就是使该输入作用于每次的输出之上。这种结构可用于将图片生成文字任务等

N vs M - RNN

这是一种不限输入输出长度的RNN结构,由编码器和解码器两部分组成,两者的内部结构都是某类RNN,也被称为 seq2seq 架构。输入数据首先通过编码器,最终输出一个隐含变量c,之后最常用的做法是使用这个隐含变量c作用在解码器进行解码的每一步上,以保证输入信息被有效利用

seq2seq 架构最早被提出应用于机器翻译,因为其输入输出不受限制,如今也是应用最广的RNN模型结构。在机器翻译、阅读理解、文本摘要等众多领域都进行了非常多的应用实践

三、传统RNN模型

3.1 结构分析

中间的方块部分,其输入有两部分,分别是 h(t-1) 以及 x(t),代表上一时间步的隐层输出,以及此时间步的输入,进入 RNN 结构体后,会"融合"到一起(将二者进行拼接, 形成新的张量 [x(t),h(t-1)]),之后这个新的张量将通过一个全连接层(线性层),该层使用 tanh 作为激活函数,最终得到该时间步的输出 h(t),将作为下一个时间步的输入和 x(t+1) 一起进入结构体。以此类推

内部计算公式:

h_{t} = tanh(W_{t}[X_{t},h_{t-1}] + b_{t})

激活函数tanh的作用:用于帮助调节流经网络的值,将值压缩在-1和1之间

在默写地方可以看到下面这个公式,本质上是等价的 

  1. W_{ih} 表示输入数据的权重
  2. b_{ih} 表示输入数据的偏置
  3. W_{hh} 表示输入隐藏状态的权重
  4. b_{hh} 表示输入隐藏状态的偏置

最后对输出的结果使用 tanh 激活函数进行计算,得到该神经元的输出

 循环网络层可以有多个神经元

依次将 "你爱我" 三个字分别送入到每个神经元进行计算,假设词嵌入时 "你爱我" 的维度为 128,经过循环网络 "你爱我" 三个字的词向量维度就会变成 4。循环神经网络的的神经元个数会影响到输出的数据维度

3.2 Pytorch构建RNN模型

nn.RNN类初始化主要参数解释:

  • input_size:输入张量x中特征维度的大小
  • hidden_size:隐层张量h中特征维度的大小
  • num_layers:隐含层的数量
  • nonlinearity:激活函数的选择,默认是tanh

nn.RNN类实例化对象主要参数解释:

  • input:输入张量x
  • h0:初始化的隐层张量h

RNN 层输入的数据为三个维度:(seq_len,batch_size,input_size)

import torch
import torch.nn as nn

# 输入单个数据
def test01():
    # seq_len, batch_size, input_size
    inputs = torch.randn(1, 1, 128)
    # 隐藏层 num_layers, batch_size, hidden_size
    hn = torch.zeros(1, 1, 256)
    # input_size 输入词向量的维度
    # hidden_size 隐藏层的大小, 隐藏层的神经元个数, 影响最终输出结果的维度
    rnn = nn.RNN(input_size=128, hidden_size=256)
    outputs, hn = rnn(inputs, hn)
    print("outputs shape", outputs.shape)
    # outputs shape torch.Size([1, 1, 256])
    print("hidden shape", hn.shape)
    # hidden shape torch.Size([1, 1, 256])

# 输入句子
def test02():
    # seq_len, batch_size, input_size
    inputs = torch.randn(8, 1, 128)
    hn = torch.zeros(1, 1, 256)

    rnn = nn.RNN(input_size=128, hidden_size=256)
    outputs, hn = rnn(inputs, hn)
    print("outputs shape", outputs.shape)
    # outputs shape torch.Size([8, 1, 256])
    print("hidden shape", hn.shape)
    # hidden shape torch.Size([1, 1, 256])

# 输入批量数据
def test03():
    # seq_len, batch_size, input_size
    inputs = torch.randn(8, 32, 128)
    hn = torch.zeros(1, 32, 256)

    rnn = nn.RNN(input_size=128, hidden_size=256)
    outputs, hn = rnn(inputs, hn)
    print("outputs shape", outputs.shape)
    # outputs shape torch.Size([8, 32, 256])
    print("hidden shape", hn.shape)
    # hidden shape torch.Size([1, 32, 256])

if __name__ == "__main__":
    # test01()
    # test02()
    test03()
import torch
import torch.nn as nn

def main():
    # seq_len, batch_size, input_size
    inputs = torch.randn(1, 3, 5)
    # num_layers, batch_size, hidden_size
    hn = torch.zeros(1, 3, 6)

    rnn = nn.RNN(input_size=5, hidden_size=6, num_layers=1)
    outputs, hn = rnn(inputs, hn)
    print(outputs.shape)
    print(outputs)
    print(hn.shape)
    print(hn)


if __name__ == "__main__":
    main()

# torch.Size([1, 3, 6])
# tensor([[[-0.0967, -0.5609,  0.5251,  0.8019, -0.4680, -0.3090],
#          [-0.5468, -0.9248,  0.7486, -0.1423, -0.8194, -0.5981],
#          [ 0.7297, -0.3720,  0.2796,  0.6966, -0.0226, -0.1303]]],
#        grad_fn=<StackBackward0>)
# torch.Size([1, 3, 6])
# tensor([[[-0.0967, -0.5609,  0.5251,  0.8019, -0.4680, -0.3090],
#          [-0.5468, -0.9248,  0.7486, -0.1423, -0.8194, -0.5981],
#          [ 0.7297, -0.3720,  0.2796,  0.6966, -0.0226, -0.1303]]],
#        grad_fn=<StackBackward0>)

3.3 优缺点

传统RNN的优势

由于内部结构简单,对计算资源要求低,相比RNN变体:LSTM和GRU模型参数总量少了很多,在短序列任务上性能和效果都表现优异

传统RNN的缺点

传统RNN在解决长序列之间的关联时, 通过实践,证明经典RNN表现很差,原因是在进行反向传播的时候,过长的序列导致梯度的计算异常,发生梯度消失或爆炸

seq_len是多少就需要进行多少次链式求导,更新权重时使用的是所有时间步梯度的总和

梯度消失或爆炸

根据反向传播算法和链式法则,梯度的计算可以简化为以下公式

其中 sigmoid 的导数值域是固定的,在 [0,0.25] 之间,而一旦公式中的 w 也小于1,那么通过这样的公式连乘后,最终的梯度就会变得非常非常小,这种现象称作梯度消失。反之,若人为的增大w的值,使其大于1,那么连乘够就可能造成梯度过大,称作梯度爆炸

梯度消失或爆炸的危害:

若在训练过程中发生了梯度消失,权重无法被更新,最终导致训练失败。梯度爆炸所带来的梯度过大,大幅度更新网络参数,在极端情况下,结果会溢出(NaN值)

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

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

相关文章

pnpm, eslint, vue-router4, element-plus, pinia

利用 pnpm 创建 vue3 项目 pnpm 包管理器 - 创建项目 Eslint 配置代码风格(Eslint用于规范纠错&#xff0c;prettier用于美观&#xff09; 在 设置 中配置保存时自动修复 提交前做代码检查 husky是一个 git hooks工具&#xff08;git的钩子工具&#xff0c;可以在特定实际执行特…

Vue的简单入门 一

声明&#xff1a;本版块根据B站学习&#xff0c;创建的是vue3项目&#xff0c;用的是vue2语法风格&#xff0c;仅供初学者学习。 目录 一、Vue项目的创建 1.已安装15.0或更高版本的Node.js 2.创建项目 二、 简单认识目录结构 三、模块语法中的指令 1.v-html 1.文本插值…

VMware Workstate 的 Ubuntu18 安装 vmware tools(不安装没法共享)

在共享主机路径后&#xff0c;可以在&#xff1a; /mnt/hgfs/下方找到共享的文件。但没有安装vmware tool时是没法共享的。 如何安装vmware tool&#xff0c;网上版本很多。这里记录一下&#xff1a; VMware Workstation 17 Pro&#xff0c;版本&#xff1a;17.6.0 虚拟机系统…

GC 基础入门

什么是GC&#xff08;Garbage Collection&#xff09;&#xff1f; 内存管理方式通常分为两种&#xff1a; 手动内存管理&#xff08;Manual Memory Management&#xff09;自动内存管理&#xff08;Garbage Collection, GC&#xff09; 手动内存管理 手动内存管理是指开发…

UE求职Demo开发日志#32 优化#1 交互逻辑实现接口、提取Bag和Warehouse的父类

1 定义并实现交互接口 接口定义&#xff1a; // Fill out your copyright notice in the Description page of Project Settings.#pragma once#include "CoreMinimal.h" #include "UObject/Interface.h" #include "MyInterActInterface.generated.h…

如何在 Mac 上解决 Qt Creator 安装后应用程序无法找到的问题

在安装Qt时&#xff0c;遇到了一些问题&#xff0c;尤其是在Mac上安装Qt后&#xff0c;发现Qt Creator没有出现在应用程序中。通过一些搜索和操作&#xff0c;最终解决了问题。以下是详细的记录和解决方法。 1. 安装Qt后未显示Qt Creator 安装完成Qt后&#xff0c;启动应用程…

多线程基础面试题剖析

一、线程的创建方式有几种 创建线程的方式有两种&#xff0c;一种是继承Thread&#xff0c;一种是实现Runable 在这里推荐使用实现Runable接口&#xff0c;因为java是单继承的&#xff0c;一个类继承了Thread将无法继承其他的类&#xff0c;而java可以实现多个接口&#xff0…

Android设备 网络安全检测

八、网络与安全机制 6.1 网络框架对比 volley&#xff1a; 功能 基于HttpUrlConnection;封装了UIL图片加载框架&#xff0c;支持图片加载;网络请求的排序、优先级处理缓存;多级别取消请求;Activity和生命周期的联动&#xff08;Activity结束生命周期同时取消所有网络请求 …

神经网络的学习 求梯度

import sys, ossys.path.append(os.pardir) import numpy as npfrom common.functions import softmax, cross_entropy_error from common.gradient import numerical_gradient# simpleNet类 class simpleNet:def __init__(self):self.W np.random.rand(2, 3) # 随机形状为2*…

AI向量数据库之LanceDB快速介绍

LanceDB LanceDB 是一个开源的向量搜索数据库&#xff0c;具备持久化存储功能&#xff0c;极大地简化了嵌入向量的检索、过滤和管理。 LanceDB的主要特点 LanceDB 的主要特点包括&#xff1a; 生产级向量搜索&#xff1a;无需管理服务器。 存储、查询和过滤向量、元数据以…

CentOS7 安装配置FTP服务

CentOS7 安装配置FTP服务 CentOS7 安装配置FTP服务1. FTP简介2. 先行准备2.1 关闭防火墙2.2 关闭 SELinux 3.安装FTP软件包4. 创建 FTP 用户及目录4.1 创建 FTP 目录并设置权限4.2 防止 FTP 用户登录 Linux 终端4.3 创建 FTP 用户组及用户4.4 创建 FTP 可写目录 5. 配置ftp服务…

【设计模式】03-理解常见设计模式-行为型模式(专栏完结)

前言 前面我们介绍完创建型模式和创建型模式&#xff0c;这篇介绍最后的行为型模式&#xff0c;也是【设计模式】专栏的最后一篇。 一、概述 行为型模式主要用于处理对象之间的交互和职责分配&#xff0c;以实现更灵活的行为和更好的协作。 二、常见的行为型模式 1、观察者模…

编程题-最大子数组和(中等-重点【贪心、动态规划、分治思想的应用】)

题目&#xff1a; 给你一个整数数组 nums &#xff0c;请你找出一个具有最大和的连续子数组&#xff08;子数组最少包含一个元素&#xff09;&#xff0c;返回其最大和。 子数组是数组中的一个连续部分。 解法一&#xff08;枚举法-时间复杂度超限&#xff09;&#xff1a; …

本地通过隧道连接服务器的mysql

前言 服务器上部署了 mysql&#xff0c;本地希望能访问该 mysql&#xff0c;但是又不希望 mysql 直接暴露在公网上 那么可以通过隧道连接 ssh 端口的方式进行连接 从外网看&#xff0c;服务器只开放了一个 ssh 端口&#xff0c;并没有开放 3306 监听端口 设置本地免密登录 …

2. grafana插件安装并接入zabbix

一、在线安装 如果不指定安装位置&#xff0c;则默认安装位置为/var/lib/grafana/plugins 插件安装完成之后需要重启grafana 命令在上一篇讲到过 //查看相关帮助 [rootlocalhost ~]# grafana-cli plugins --help //从列举中的插件过滤zabbix插件 [rootlocalhost ~]# grafana…

Linux第107步_Linux之PCF8563实验

使用PCF8563代替内核的RTC&#xff0c;可以降低功耗&#xff0c;提高时间的精度。同时有助于进一步熟悉I2C驱动的编写。 1、了解rtc_time64_to_tm()和rtc_tm_to_time64() 打开“drivers/rtc/lib.c” /* * rtc_time64_to_tm - Converts time64_t to rtc_time. * Convert seco…

功能说明并准备静态结构

功能说明并准备静态结构 <template><div class"card-container"><!-- 搜索区域 --><div class"search-container"><span class"search-label">车牌号码&#xff1a;</span><el-input clearable placeho…

[免费]SpringBoot公益众筹爱心捐赠系统【论文+源码+SQL脚本】

大家好&#xff0c;我是老师&#xff0c;看到一个不错的SpringBoot公益众筹爱心捐赠系统&#xff0c;分享下哈。 项目介绍 公益捐助平台的发展背景可以追溯到几十年前&#xff0c;当时人们已经开始通过各种渠道进行公益捐助。随着互联网的普及&#xff0c;本文旨在探讨公益事业…

ML.Net二元分类

ML.Net二元分类 文章目录 ML.Net二元分类前言项目的创建机器学习模型的创建添加模型选择方案训练环境的选择训练数据的添加训练数据的选择训练数据的格式要预测列的选择模型评估模型的使用总结前言 ‌ML.NET‌是由Microsoft为.NET开发者平台创建的免费、开源、跨平台的机器学习…

visutal studio 2022使用qcustomplot基础教程

编译 下载&#xff0c;2.1.1版支持到Qt6.4 。 拷贝qcustomplot.h和qcustomplot.cpp到项目源目录&#xff08;Qt project&#xff09;。 在msvc中将它俩加入项目中。 使用Qt6.8&#xff0c;需要修改两处代码&#xff1a; L6779 # if QT_VERSION > QT_VERSION_CHECK(5, 2, …