深度学习处理时间序列(5)

Keras中的循环层

上面的NumPy简单实现对应一个实际的Keras层—SimpleRNN层。不过,二者有一点小区别:SimpleRNN层能够像其他Keras层一样处理序列批量,而不是像NumPy示例中的那样只能处理单个序列。也就是说,它接收形状为(batch_size,timesteps, input_features)的输入,而不是(timesteps, input_features)。指定初始Input()的shape参数时,你可以将timesteps设为None,这样神经网络就能够处理任意长度的序列,如代码清单10-16所示。

代码清单10-16 能够处理任意长度序列的RNN层

num_features = 14
inputs = keras.Input(shape=(None, num_features))
outputs = layers.SimpleRNN(16)(inputs)

果你想让模型处理可变长度的序列,那么这就特别有用。但是,如果所有序列的长度相同,那么我建议指定完整的输入形状,因为这样model.summary()能够显示输出长度信息,这总是很好的,而且还可以解锁一些性能优化功能。Keras中的所有循环层(SimpleRNN层、LSTM层和GRU层)都可以在两种模式下运行:一种是返回每个时间步连续输出的完整序列,即形状为(batch_size, timesteps,output_features)的3阶张量;另一种是只返回每个输入序列的最终输出,即形状为(batch_size, output_features)的2阶张量。这两种模式由return_sequences参数控制。我们来看一个SimpleRNN示例,它只返回最后一个时间步的输出,如代码清单10-17所示。

代码清单10-17 只返回最后一个时间步输出的RNN层

>>> num_features = 14
>>> steps = 120
>>> inputs = keras.Input(shape=(steps, num_features))
>>> outputs = layers.SimpleRNN(16, return_sequences=False)(inputs)----请注意,默认情况下使用return_sequences=False
>>> print(outputs.shape)
(None, 16)

代码清单10-18给出的示例返回了完整的状态序列。

代码清单10-18 返回完整输出序列的RNN层

>>> num_features = 14
>>> steps = 120
>>> inputs = keras.Input(shape=(steps, num_features))
>>> outputs = layers.SimpleRNN(16, return_sequences=True)(inputs)
>>> print(outputs.shape)
(None, 120, 16)

为了提高神经网络的表示能力,有时将多个循环层逐个堆叠也是很有用的。在这种情况下,你需要让所有中间层都返回完整的输出序列,如代码清单10-19所示。

代码清单10-19 RNN层堆叠

inputs = keras.Input(shape=(steps, num_features))
x = layers.SimpleRNN(16, return_sequences=True)(inputs)
x = layers.SimpleRNN(16, return_sequences=True)(x)
outputs = layers.SimpleRNN(16)(x)

我们在实践中很少会用到SimpleRNN层。它通常过于简单,没有实际用途。特别是SimpleRNN层有一个主要问题:在t时刻,虽然理论上来说它应该能够记住许多时间步之前见过的信息,但事实证明,它在实践中无法学到这种长期依赖。原因在于梯度消失问题,这一效应类似于在层数较多的非循环网络(前馈网络)中观察到的效应:随着层数的增加,神经网络最终变得无法训练。Yoshua Bengio等人在20世纪90年代初研究了这一效应的理论原因。

值得庆幸的是,SimpleRNN层并不是Keras中唯一可用的循环层,还有另外两个:LSTM层和GRU层,二者都是为解决这个问题而设计的。我们来看LSTM层,其底层的长短期记忆(LSTM)算法由Sepp Hochreiter和Jürgen Schmidhuber在1997年开发4,是二人研究梯度消失问题的重要成果。

LSTM层是SimpleRNN层的变体,它增加了一种携带信息跨越多个时间步的方式。假设有一条传送带,其运行方向平行于你所处理的序列。序列中的信息可以在任意位置跳上传送带,然后被传送到更晚的时间步,并在需要时原封不动地跳回来。这其实就是LSTM的原理:保存信息以便后续使用,从而防止较早的信号在处理过程中逐渐消失。这应该会让你想到残差连接,二者的思路几乎相同。为了详细解释LSTM,我们先从SimpleRNN单元开始讲起,如图10-8所示。因为有许多个权重矩阵,所以对单元中的W和U两个矩阵添加下标字母o(Wo和Uo)​,表示输出(output)​。

在这里插入图片描述

我们向图10-8中添加新的数据流,其中携带跨越时间步的信息。这条数据流在不同时间步的值称为c_t,其中c表示携带(carry)​。这些信息会对单元产生以下影响:它将与输入连接和循环连接进行计算(通过密集变换,即与权重矩阵做点积,然后加上偏置,再应用激活函数)​,从而影响传递到下一个时间步的状态(通过激活函数和乘法运算)​。从概念上来看,携带数据流可以调节下一个输出和下一个状态,如图10-9所示。到目前为止,内容都很简单。

在这里插入图片描述

下面来看一下这种方法的精妙之处,即携带数据流下一个值的计算方法。它包含3个变换,这3个变换的形式都与SimpleRNN单元相同,如下所示。

y = activation(dot(state_t, U) + dot(input_t, W) + b)

但这3个变换都有各自的权重矩阵,我们分别用字母i、f、k作为下标。目前的模型如代码清单10-20所示(这可能看起来有些随意,但请你耐心一点)​。

代码清单10-20 LSTM架构的详细伪代码(1/2)

output_t = activation(dot(state_t, Uo) + dot(input_t, Wo) + dot(c_t, Vo) + bo)
i_t = activation(dot(state_t, Ui) + dot(input_t, Wi) + bi)
f_t = activation(dot(state_t, Uf) + dot(input_t, Wf) + bf)
k_t = activation(dot(state_t, Uk) + dot(input_t, Wk) + bk)

通过对i_t、f_t和k_t进行计算,我们得到了新的携带状态(下一个c_t)​,如代码清单10-21所示。代码清单10-21 LSTM架构的详细伪代码(2/2)

c_t+1 = i_t * k_t + c_t * f_t

添加上述内容之后的模型如图10-10所示。这就是LSTM层,不算很复杂,只是稍微有些复杂而已。

在这里插入图片描述

你甚至可以解释每个运算的作用。比如你可以说,将c_t和f_t相乘,是为了故意遗忘携带数据流中不相关的信息。同时,i_t和k_t都包含关于当前时间步的信息,可以用新信息来更新携带数据流。但归根结底,这些解释并没有多大意义,因为这些运算的实际效果是由权重参数决定的,而权重以端到端的方式进行学习,每次训练都要从头开始,因此不可能为某个运算赋予特定的意义。RNN单元的类型(如前所述)决定了假设空间,即在训练过程中搜索良好模型配置的空间,但它不能决定RNN单元的作用,那是由单元权重来决定的。相同的单元具有不同的权重,可以起到完全不同的作用。因此,RNN单元的运算组合最好被解释为对搜索的一组约束,而不是工程意义上的设计。这种约束的选择(如何实现RNN单元)最好留给优化算法来完成(比如遗传算法或强化学习过程)​,而不是让人类工程师来完成。那将是未来我们构建模型的方式。总之,你不需要理解LSTM单元的具体架构。作为人类,你不需要理解它,而只需记住LSTM单元的作用:允许过去的信息稍后重新进入,从而解决梯度消失问题。

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

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

相关文章

操作系统相关知识点

操作系统在进行线程切换时需要进行哪些动作? 保存当前线程的上下文 保存寄存器状态、保存栈信息。 调度器选择下一个线程 调度算法决策:根据策略(如轮转、优先级、公平共享)从就绪队列选择目标线程。 处理优先级:实时…

从0到1:Rust 如何用 FFmpeg 和 OpenGL 打造硬核视频特效

引言:视频特效开发的痛点,你中了几个? 视频特效如今无处不在:短视频平台的滤镜美化、直播间的实时美颜、影视后期的电影级调色,甚至 AI 生成内容的动态效果。无论是个人开发者还是团队,视频特效都成了吸引…

【并发编程 | 第一篇】线程相关基础知识

1.并发和并行有什么区别 并发是指多核CPU上的多任务处理,多个任务在同一时刻真正同时执行。 并行是指单核CPU上的多任务处理,多个任务在同一时间段内交替执行,通过时间片轮转实现交替执行,用于解决IO密集型瓶颈。 如何理解线程安…

Kafka 偏移量

在 Apache Kafka 中,偏移量(Offset)是一个非常重要的概念。它不仅用于标识消息的位置,还在多种场景中发挥关键作用。本文将详细介绍 Kafka 偏移量的核心概念及其使用场景。 一、偏移量的核心概念 1. 定义 偏移量是一个非负整数…

18.redis基本操作

Redis(Remote Dictionary Server)是一个开源的、高性能的键值对(Key-Value)存储数据库,广泛应用于缓存、消息队列、实时分析等场景。它以其极高的读写速度、丰富的数据结构和灵活的应用方式而受到开发者的青睐。 Redis 的主要特点 ​高性能: ​内存存储:Redis 将所有数…

历年跨链合约恶意交易详解(一)——THORChain退款逻辑漏洞

漏洞合约函数 function returnVaultAssets(address router, address payable asgard, Coin[] memory coins, string memory memo) public payable {if (router address(this)){for(uint i 0; i < coins.length; i){_adjustAllowances(asgard, coins[i].asset, coins[i].a…

通俗易懂的讲解SpringBean生命周期

&#x1f4d5;我是廖志伟&#xff0c;一名Java开发工程师、《Java项目实战——深入理解大型互联网企业通用技术》&#xff08;基础篇&#xff09;、&#xff08;进阶篇&#xff09;、&#xff08;架构篇&#xff09;清华大学出版社签约作家、Java领域优质创作者、CSDN博客专家、…

深入理解 `git pull --rebase` 与 `--allow-unrelated-histories`:区别、原理与实战指南

&#x1f680; git pull --rebase vs --allow-unrelated-histories 全面解析 在日常使用 Git 时&#xff0c;我们经常遇到两种拉取远程代码的方式&#xff1a;git pull --rebase 和 git pull --allow-unrelated-histories。它们的区别是什么&#xff1f;各自适用哪些场景&…

Matlab_Simulink中导入CSV数据与仿真实现方法

前言 在Simulink仿真中&#xff0c;常需将外部数据&#xff08;如CSV文件或MATLAB工作空间变量&#xff09;作为输入信号驱动模型。本文介绍如何高效导入CSV数据至MATLAB工作空间&#xff0c;并通过From Workspace模块实现数据到Simulink的精确传输&#xff0c;适用于运动控制…

Spring Boot 中 JdbcTemplate 处理枚举类型转换 和 减少数据库连接的方法 的详细说明,包含代码示例和关键要点

以下是 Spring Boot 中 JdbcTemplate 处理枚举类型转换 和 减少数据库连接的方法 的详细说明&#xff0c;包含代码示例和关键要点&#xff1a; 一、JdbcTemplate 处理枚举类型转换 1. 场景说明 假设数据库存储的是枚举的 String 或 int 值&#xff0c;但 Java 实体类使用 enu…

API 安全之认证鉴权

作者&#xff1a;半天 前言 API 作为企业的重要数字资源&#xff0c;在给企业带来巨大便利的同时也带来了新的安全问题&#xff0c;一旦被攻击可能导致数据泄漏重大安全问题&#xff0c;从而给企业的业务发展带来极大的安全风险。正是在这样的背景下&#xff0c;OpenAPI 规范…

MATLAB绘图配色包说明

本栏目将分享MATLAB数据分析图表&#xff0c;该贴讲述配色包的使用 将配色包colormap_nclCM文件夹添加到路径close all&#xff08;尽量不要删&#xff09;&#xff0c;使用map colormap(nclCM(309))时会多出来一张空白图片。配色资源来自slandarer&#xff1b;找不到合适颜色…

Oracle 数据库系统全面详解

Oracle 数据库是全球领先的关系型数据库管理系统(RDBMS)&#xff0c;由 Oracle 公司开发。它为企业级应用提供了高性能、高可用性、安全性和可扩展性的数据管理解决方案。 目录 一、Oracle 数据库体系结构 1. 物理存储结构 主要组件&#xff1a; 存储层次&#xff1a; 2. …

Flink介绍——发展历史

引入 我们整个大数据处理里面的计算模式主要可以分为以下四种&#xff1a; 批量计算&#xff08;batch computing&#xff09; MapReduce Hive Spark Flink pig流式计算&#xff08;stream computing&#xff09; Storm SparkStreaming/StructuredStreaming Flink Samza交互计…

在MFC中使用Qt(四):使用属性表(Property Sheet)实现自动化Qt编译流程

前言 首先回顾下前面文章介绍的&#xff1a; 在MFC中使用Qt&#xff08;一&#xff09;&#xff1a;玩腻了MFC&#xff0c;试试在MFC中使用Qt&#xff01;&#xff08;手动配置编译Qt&#xff09; 在MFC中使用Qt&#xff08;二&#xff09;&#xff1a;实现Qt文件的自动编译流…

Go红队开发— 收官工具

文章目录 免责声明个人武器开发美观输出Whois查询反查ip目录扫描子域名爆破被动扫描主动扫描(字典爆破)CDN检测 免责声明 &#x1f4a1; 本博客绝不涉及任何非法用途。 &#x1f4a1; 使用者风险自担&#xff0c;违规后果自负。 &#x1f4a1; 守法为先&#xff0c;技术向善。 …

论文阅读《P​roximal Curriculum for Reinforcement Learning Agents》——提升智能体学习速度的

老规矩&#xff0c;今天是使用Gemini2.5pro来生成的模板 这篇论文研究了如何为处理多个相关任务的强化学习智能体自动设计学习课程&#xff08;即任务顺序&#xff09;&#xff0c;以加速训练过程&#xff0c;并解决现有方法需要大量调参或缺乏理论依据的问题。为此&#xff0…

【面试题】在 CSS 中,实现一个 div 中的子 div 水平垂直居中

1. 使用 Flexbox 特点&#xff1a;简单、直观&#xff0c;现代浏览器支持良好。 代码&#xff1a; css .parent {display: flex;justify-content: center; /* 水平居中 */align-items: center; /* 垂直居中 */height: 200px; /* 父容器需有高度 */ } .child {…

基于SpringBoot的失物招领平台(源码+数据库)

476基于SpringBoot的失物招领平台&#xff0c;有用户和管理员两个角色&#xff0c;主要功能如下 失物招领系统功能介绍如下&#xff1a; 1. 用户功能&#xff1a; - 发布失物公告&#xff1a;用户可以发布自己的失物信息 - 失物分类&#xff1a;用户可以根据失物的类型进行分类…

PyQt6实例_批量下载pdf工具_批量pdf网址获取

目录 前置&#xff1a; 步骤&#xff1a; step one 安装包 step two 获取股票代码 step three 敲代码&#xff0c;实现 step four 网址转pdf网址 视频 前置&#xff1a; 1 本系列将以 “PyQt6实例_批量下载pdf工具”开头&#xff0c;放在 【PyQt6实例】 专栏 2 本节讲…