循环神经网络(RNN)的原理及实现

2023-05-16

在前馈神经网络中,信息的传递是单向的,这种限制虽然使得网络变得更容易学习,但在一定程度上也减弱了神经网络模型的能力。在生物神经网络中,神经元之间的连接关系要复杂的多。前馈神经网络可以看着是一个复杂的函数,每次输入都是独立的,即网络的输出只依赖于当前的输入。但是在很多现实任务中,网络的输入不仅和当前时刻的输入相关,也和其过去一段时间的输出相关。比如一个有限状态自动机,其下一个时刻的状态(输出)不仅仅和当前输入相关,也和当前状态(上一个时刻的输出)相关。此外,前馈网络难以处理时序数据,比如视频、语音、文本等。时序数据的长度一般是不固定的,而前馈神经网络要求输入和输出的维数都是固定的,不能任意改变。因此,当处理这一类和时序相关的问题时,就需要一种能力更强的模型。

循环神经网络(Recurrent Neural Network,RNN) 是一类具有短期记忆能力的神经网络。在循环神经网络中,神经元不但可以接受其它神经元的信息,也可以接受自身的信息,形成具有环路的网络结构。和前馈神经网络相比,循环神经网络更加符合生物神经网络的结构。循环神经网络已经被广泛应用在语音识别、语言模型以及自然语言生成等任务上。循环神经网络的参数学习可以通过
随时间反向传播算法[Werbos, 1990] 来学习。随时间反向传播算法即按照时间的逆序将错误信息一步步地往前传递。当输入序列比较长时,会存在梯度爆炸
和消失问题[Bengio et al., 1994, Hochreiter and Schmidhuber, 1997, Hochreiter et al., 2001],也称为长期依赖问题。为了解决这个问题,人们对循环神经网络进行了很多的改进,其中最有效的改进方式引入门控机制。

此外,循环神经网络可以很容易地扩展到两种更广义的记忆网络模型:递归神经网络图网络

给网络增加记忆能力

为了处理这些时序数据并利用其历史信息,我们需要让网络具有短期记忆能力。
而前馈网络是一个静态网络,不具备这种记忆能力。
一般来讲,我们可以通过以下三种方法来给网络增加短期记忆能力。

延时神经网络

一种简单的利用历史信息的方法是建立一个额外的延时单元,用来存储网
络的历史信息(可以包括输入、输出、隐状态等)。比较有代表性的模型是延时
神经网络(Time Delay Neural Network,TDNN)
[Lang et al., 1990, Waibelet al., 1989]。

延时神经网络是在前馈网络中的非输出层都添加一个延时器,记录最近几
次神经元的输出。在第 t t t个时刻,第 l + 1 l +1 l+1 层神经元和第 l l l层神经元的最近 p p p 次输出相关,即
h t ( l + 1 ) = f ( h t ( l ) , h t − 1 ( l ) , ⋯   , h t − p + 1 ( l ) ) . \mathbf{h}_t^{(l+1)}=f(\mathbf{h}_t^{(l)},\mathbf{h}_{t-1}^{(l)},\cdots,\mathbf{h}_{t-p+1}^{(l)}). ht(l+1)=f(ht(l),ht1(l),,htp+1(l)).
通过延时器,前馈网络就具有了短期记忆的能力。

有外部输入的非线性自回归模型

自回归模型(Autoregressive Model,AR) 是统计学上常用的一类时间序列模型,用一个变量 y t y_t yt 的历史信息来预测自己。

y t = w 0 + ∑ i = 1 p w p y t − i + ϵ t , \mathbf{y}_t=w_0+\sum\limits_{i=1}^p w_p\mathbf{y}_{t-i}+\epsilon_t, yt=w0+i=1pwpyti+ϵt,

其中 p p p为超参数, w p w_p wp 为参数, ϵ t ∼ N ( 0 , σ 2 ) ϵ_t ∼ N(0, \sigma^{2}) ϵtN(0,σ2) 为第 t t t 个时刻的噪声,方差 σ 2 \sigma^{2} σ2 和时间无关。

有外部输入的非线性自回归模型(Nonlinear Autoregressive with Exogenous Inputs Model,NARX)[Leontaritis and Billings, 1985] 是自回归模型的
扩展,在每个时刻 t t t 都有一个外部输入 x t x_t xt,产生一个输出 y t y_t yt。NARX通过一个延时器记录最近几次的外部输入和输出,第 t t t个时刻的输出 y t y_t yt
y t = f ( x t , x t − 1 , ⋯   , x t − p , y t − 1 , y t − 2 , ⋯   , y t − q ) \mathbf{y}_t=f(\mathbf{x}_t,\mathbf{x}_{t-1},\cdots,\mathbf{x}_{t-p},\mathbf{y}_{t-1},\mathbf{y}_{t-2},\cdots,\mathbf{y}_{t-q}) yt=f(xt,xt1,,xtp,yt1,yt2,,ytq)

其中 f ( ⋅ ) f(·) f() 表示非线性函数,可以是一个前馈网络, p p p q q q 为超参数。

循环神经网络

循环神经网络通过使用带自反馈的神经元,能够处理任意长度的时序数据。

给定一个输入序列

x 1 : T = ( x 1 , x 2 , … , x t , … , x T ) \mathbf{x}_{1:T}=(\mathbf{x}_{1},\mathbf{x}_{2},\ldots,\mathbf{x}_{t},\ldots,\mathbf{x}_{T}) x1:T=(x1,x2,,xt,,xT)

循环神经网络通过下面公式更新带反馈边的隐藏层的活性值 h t h_t ht
h t = f ( h t − 1 , x t ) \mathbf{h}_t=f(\mathbf{h}_{t-1},\mathbf{x}_t) ht=f(ht1,xt)

其中 h 0 = 0 h_0 = 0 h0=0 f ( ⋅ ) f(·) f() 为一个非线性函数,也可以是一个前馈网络。

如图给出了循环神经网路的示例。

循环神经网络

从数学上讲,上述公式可以看成一个动力系统。动力系统(Dynamical Sys-tem) 是一个数学上的概念,指系统状态按照一定的规律随时间变化的系统。

生活中很多现象都可以动力系统来描述,比如钟摆晃动、台球轨迹等。具体地讲,动力系统是使用一个函数来描述一个给定空间(如某个物理系统的状态空间)中所有点随时间的变化情况。因此,隐藏层的活性值 h t h_t ht 在很多文献上也称为状态(state)或隐状态(hidden states)。理论上,循环神经网络可以近似任意的非线性动力系统。

RNN的实现:

class rnn(TFBaseModel):

    def __init__(
        self,
        lstm_size,
        output_mixture_components,
        attention_mixture_components,
        **kwargs
    ):
        self.lstm_size = lstm_size
        self.output_mixture_components = output_mixture_components
        self.output_units = self.output_mixture_components*6 + 1
        self.attention_mixture_components = attention_mixture_components
        super(rnn, self).__init__(**kwargs)

    def parse_parameters(self, z, eps=1e-8, sigma_eps=1e-4):
        pis, sigmas, rhos, mus, es = tf.split(
            z,
            [
                1*self.output_mixture_components,
                2*self.output_mixture_components,
                1*self.output_mixture_components,
                2*self.output_mixture_components,
                1
            ],
            axis=-1
        )
        pis = tf.nn.softmax(pis, axis=-1)
        sigmas = tf.clip_by_value(tf.exp(sigmas), sigma_eps, np.inf)
        rhos = tf.clip_by_value(tf.tanh(rhos), eps - 1.0, 1.0 - eps)
        es = tf.clip_by_value(tf.nn.sigmoid(es), eps, 1.0 - eps)
        return pis, mus, sigmas, rhos, es

    def NLL(self, y, lengths, pis, mus, sigmas, rho, es, eps=1e-8):
        sigma_1, sigma_2 = tf.split(sigmas, 2, axis=2)
        y_1, y_2, y_3 = tf.split(y, 3, axis=2)
        mu_1, mu_2 = tf.split(mus, 2, axis=2)

        norm = 1.0 / (2*np.pi*sigma_1*sigma_2 * tf.sqrt(1 - tf.square(rho)))
        Z = tf.square((y_1 - mu_1) / (sigma_1)) + \
            tf.square((y_2 - mu_2) / (sigma_2)) - \
            2*rho*(y_1 - mu_1)*(y_2 - mu_2) / (sigma_1*sigma_2)

        exp = -1.0*Z / (2*(1 - tf.square(rho)))
        gaussian_likelihoods = tf.exp(exp) * norm
        gmm_likelihood = tf.reduce_sum(pis * gaussian_likelihoods, 2)
        gmm_likelihood = tf.clip_by_value(gmm_likelihood, eps, np.inf)

        bernoulli_likelihood = tf.squeeze(tf.where(tf.equal(tf.ones_like(y_3), y_3), es, 1 - es))

        nll = -(tf.log(gmm_likelihood) + tf.log(bernoulli_likelihood))
        sequence_mask = tf.logical_and(
            tf.sequence_mask(lengths, maxlen=tf.shape(y)[1]),
            tf.logical_not(tf.is_nan(nll)),
        )
        nll = tf.where(sequence_mask, nll, tf.zeros_like(nll))
        num_valid = tf.reduce_sum(tf.cast(sequence_mask, tf.float32), axis=1)

        sequence_loss = tf.reduce_sum(nll, axis=1) / tf.maximum(num_valid, 1.0)
        element_loss = tf.reduce_sum(nll) / tf.maximum(tf.reduce_sum(num_valid), 1.0)
        return sequence_loss, element_loss

    def sample(self, cell):
        initial_state = cell.zero_state(self.num_samples, dtype=tf.float32)
        initial_input = tf.concat([
            tf.zeros([self.num_samples, 2]),
            tf.ones([self.num_samples, 1]),
        ], axis=1)
        return rnn_free_run(
            cell=cell,
            sequence_length=self.sample_tsteps,
            initial_state=initial_state,
            initial_input=initial_input,
            scope='rnn'
        )[1]

    def primed_sample(self, cell):
        initial_state = cell.zero_state(self.num_samples, dtype=tf.float32)
        primed_state = tf.nn.dynamic_rnn(
            inputs=self.x_prime,
            cell=cell,
            sequence_length=self.x_prime_len,
            dtype=tf.float32,
            initial_state=initial_state,
            scope='rnn'
        )[1]
        return rnn_free_run(
            cell=cell,
            sequence_length=self.sample_tsteps,
            initial_state=primed_state,
            scope='rnn'
        )[1]

    def calculate_loss(self):
        self.x = tf.placeholder(tf.float32, [None, None, 3])
        self.y = tf.placeholder(tf.float32, [None, None, 3])
        self.x_len = tf.placeholder(tf.int32, [None])
        self.c = tf.placeholder(tf.int32, [None, None])
        self.c_len = tf.placeholder(tf.int32, [None])

        self.sample_tsteps = tf.placeholder(tf.int32, [])
        self.num_samples = tf.placeholder(tf.int32, [])
        self.prime = tf.placeholder(tf.bool, [])
        self.x_prime = tf.placeholder(tf.float32, [None, None, 3])
        self.x_prime_len = tf.placeholder(tf.int32, [None])
        self.bias = tf.placeholder_with_default(
            tf.zeros([self.num_samples], dtype=tf.float32), [None])

        cell = LSTMAttentionCell(
            lstm_size=self.lstm_size,
            num_attn_mixture_components=self.attention_mixture_components,
            attention_values=tf.one_hot(self.c, len(drawing.alphabet)),
            attention_values_lengths=self.c_len,
            num_output_mixture_components=self.output_mixture_components,
            bias=self.bias
        )
        self.initial_state = cell.zero_state(tf.shape(self.x)[0], dtype=tf.float32)
        outputs, self.final_state = tf.nn.dynamic_rnn(
            inputs=self.x,
            cell=cell,
            sequence_length=self.x_len,
            dtype=tf.float32,
            initial_state=self.initial_state,
            scope='rnn'
        )
        params = time_distributed_dense_layer(outputs, self.output_units, scope='rnn/gmm')
        pis, mus, sigmas, rhos, es = self.parse_parameters(params)
        sequence_loss, self.loss = self.NLL(self.y, self.x_len, pis, mus, sigmas, rhos, es)

        self.sampled_sequence = tf.cond(
            self.prime,
            lambda: self.primed_sample(cell),
            lambda: self.sample(cell)
        )
        return self.loss


if __name__ == '__main__':
    dr = DataReader(data_dir='data/processed/')

    nn = rnn(
        reader=dr,
        log_dir='logs',
        checkpoint_dir='checkpoints',
        prediction_dir='predictions',
        learning_rates=[.0001, .00005, .00002],
        batch_sizes=[32, 64, 64],
        patiences=[1500, 1000, 500],
        beta1_decays=[.9, .9, .9],
        validation_batch_size=32,
        optimizer='rms',
        num_training_steps=100000,
        warm_start_init_step=0,
        regularization_constant=0.0,
        keep_prob=1.0,
        enable_parameter_averaging=False,
        min_steps_to_checkpoint=2000,
        log_interval=20,
        grad_clip=10,
        lstm_size=400,
        output_mixture_components=20,
        attention_mixture_components=10
    )
    nn.fit()
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

循环神经网络(RNN)的原理及实现 的相关文章

  • 【英语】学习记录——5/10

    1 美剧 英雄联盟 xff1a 双城之战 第一季 硅谷 第一季 硅谷 第二季 硅谷 第三季 第五集 2 书籍 书籍阅读工具ReadPaper Thinking Fast and Slow by psychologist Daniel Kah
  • 【Python】画折线图在坐标轴上的点遮挡与去除冗余网格问题

    1 代码 span class token keyword import span numpy span class token keyword as span np span class token keyword import span
  • 【Python】可视化KITTI激光雷达点云&绘制立体框

    更新2023 5 4不如open3d好用 xff0c 依赖太多 xff0c 已转用open3d库 前言 最近在复现PointRCNN论文过程中发现没有可视化代码 xff0c 于是查找资料找到了 xff1a pointRCNN 结果可视化 t
  • 【Python】PointRCNN在线可视化点云与图像

    前言 花了一周多的时间对PointRCNN进行了模型的阅读与复现 xff0c 发现代码没有可视化程序 xff0c 并且开源的可视化程序 xff0c 也是离线的 xff0c 将检测的结果 xff0c 一帧一帧保存并拼接成视频 xff0c 很难
  • MindSpore中张量和Numpy的互相转换

    NumPy 是 Python 语言的一个扩展程序库 支持大量的维度数组与矩阵运算 此外也针对数组运算提供大量的数学函数库 所以下面展示下MindSpore中张量和Numpy类型的互相转换 张量转换为NumPy zeros 61 ops Ze
  • 云安全-Python实现凯撒密码和替换密码的加密解密与暴力破解

    记录顺带保存一次课堂作业 xff0c 部分参考了现有的实现 xff0c 结合需求进行了一波码 xff0c 能用就行 xff0c 人和代码能跑一个就好 xff0c 替换密码暴力破解实在懒得搞了 xff0c 或许以后会更 xff1f span
  • Windows下编程需要看哪些书

    Windows 下编程需要看哪些书 本人是自学计算机的 xff0c 所有计算机方面的知识都看 xff0c 研究过一段时间网络 xff0c 对计算机网络方面有一定的基础 xff0c 对程序设计尤感兴趣 xff0c 个人认为学习 Windows
  • 找工作经验贴----转自cc98 (作者ID:qzz88 ) 仅为收藏,感谢原作者的经验分享

    原帖地址 xff1a http www cc98 org dispbbs asp BoardID 61 248 amp id 61 3813130 amp page 61 amp replyID 61 3813130 amp star 61
  • QGC、PX4和AirSim的安装

    本教程视频地址 xff1a https www bilibili com video BV1dv411K71E 本教程将讲解QGC地面站的安装 PX4控制系统 xff08 包括jMAVSim ROS和Gazebo xff09 的安装 Air
  • Ominibus F4V3 Pro飞控原理图和接线图

    Ominibus F4V3 Pro飞控接线图如下图所示 部分实物接线图如下 注意上图中 xff0c 电流计入口 描述是错误的 xff0c 最形象的是第一个接线图 xff0c 那里表的很清楚 电源这块接线为电池接线到飞控板上的电池 43 和电
  • Mini Crossbow AAT自动跟踪云台设置(配合TeleFlyTiny模块)

    飞行器在空中 xff0c 位置和方位时刻变化 xff0c 而我们使用的图传接收机 xff0c 需要时刻保持跟随飞行器材能捕获较好的图像 xff0c 靠人去调整地面天线角度是不太合适的 xff0c 所以我们可以使用AAT自动跟踪云台来完成调整
  • Mission Planner安卓安装包

    可以在安卓手机上安装并使用的安装包 下载地址 xff1a https download csdn net download xjhappyarrow 22864716 spm 61 1001 2014 3001 5503
  • Docker 相关配置文件路径

    配置文件参数 xff1a 1 优先解析在config file命令行参数 2 在root模式下 Docker Daemon 默认配置文件路径 etc docker daemon json 3 在rootless模式下 默认配置文件路径在 d
  • 1. 【gRPC系列学习】 gRPC起源、优缺点

    gRPC是一项进程间通信技术 xff0c 可以用来连接 调用 操作 调试分布式异构应用程序 xff0c 就像调用本地函数一样 gRPC主要采用同步的请求 响应进行通信 xff0c 但建立连接后 xff0c 它可以完全以异步模式进行操作 1
  • stlink灯一直闪

    灯闪说明stlink工作不正常 原因可能是 xff1a 1 stlink供电不足 试着用外部电源和stlink同时给板子供电 2 电脑的USB口硬件 xff08 USB口烧了 xff0c 但可能性比较少 xff09 或USB相关驱动有问题
  • stlink使用笔记

    1 stlink灯一直闪 2 当用外部电源 xff08 外部 就是不直接使用stlink为板子供电 xff09 为板子供电时 xff0c 如果要用stlink xff08 SWD模式 xff09 xff0c 那么不能只插SWCLK和SWDI
  • 先电OpenStack创建云主机报错500

    现象 xff1a 从报错中可定位到问题出在nova的conductor组件中 日志 xff1a 查看 var log nova nova conductor log 从日志中可以观察到是因为找不到cpu特性 解决方法 xff1a 进入 us
  • MAVROS + APM + pixhawk 填坑日记(一)

    64 TOC MAVROS 43 APM 43 pixhawk 填坑日记 一 树莓派和pixhawk通过usb串口连接 xff0c 想通过mavros读取飞控上关于GPS的位置信息 rostopic list可以看到mavros发布的话题消
  • ubuntu搭建APT源简单方法

    一 为什么需要搭建APT源 原因如下 xff1a 1 在公司内网离线情况下 xff0c ubuntu无法通过apt原生源进行下载 2 有些源国内无法正常访问 xff0c 需要翻墙 基于以上原因 xff0c 需要自建APT源 二 准备条件 需
  • 加速度计参数讲解

    测量范围 FS也称量程 xff0c 单位为g 地球重力 xff0c 是指加速度计能测量到的正反方向最大加速度的额定值范围 常见有 xff08 2g 4g 8g 16g up to 400g 灵敏度 分辨率Sensitivity Resolu

随机推荐

  • vim 编辑器---批量注释和批量取消注释/去除黄色阴影

    添加注释 ctrl 43 v 进入块选泽模式 上下键选中需要注释的行 按大写 I 进入插入模式 xff0c 输入注释符 按两次 ESC 退出 xff0c 即完成添加注释 取消注释 ctrl 43 v 进入块选泽模式 上下键选中需要注释的行
  • 作业—FreeRTOS入门

    FreeRTOS入门 零 需求软件 xff08 自行下载 xff09 一 任务要求二 FreeRTOS的使用1 原理2 多任务程序3 烧录代码4 结果 三 注意事项四 参考资料 零 需求软件 xff08 自行下载 xff09 1 keil5
  • Flask 案例

    创建news xff0c 根目录下创建settings文件 config py文件 xff0c 编写配置项 xff0c 配置项必须大写 class DeFaultConfig SECRET KEY 61 39 39 SQLALCHEMY D
  • 三 Gazebo学习总结之制作一个模型及导入网格

    Models从简单的形状到复杂的机器人都有 它指的是 lt model gt SDF标签 xff0c 从本质上来说是links joints collision objects visuals和plugins的集合 xff0c 生成一个模型
  • STM32F103V跑NuttX之一——下载nuttX及编译烧录

    下载nuttX及编译 1 NuttX官方链接2 NuttX及App工程下载3 编译NuttX中STM32F103V nsh测试例程4 在ubuntu下使用串口来烧录目标文件至STM32F103V4 1 ubuntu下stm32flash工具
  • Win10遍历句柄表+修改权限过Callback保护

    本帖转载于http www m5home com bbs thread 8847 1 1 html 本想发到看雪 xff0c 但自己太菜 xff0c 看雪 牛人 又太多 xff0c 想想还是发到紫水晶吧 感谢 TA 的 WIN64 教程带我
  • Pixhawk飞控源码目录结构及编译流程分析

    xff08 PS xff1a 这是第一次写博客 xff0c 以前也有记录一些经验总结心得什么的 xff0c 不过都是手写笔记或者记在word上 xff0c csdn看了好久 xff0c 总觉的只索取不付出心里有些过意不去 xff0c 以后尽
  • 无刷电机驱动解析

    1 概述 无霍尔的BLDC控制方案与有霍尔BLDC的基本原理相似 都是用所谓 六步换向法 根据转子当前的位置 按照一定的顺序给定子绕组通电使BLDC电机转动 所不同的是无霍尔BLDC不需要霍尔效应传感器 通过检测定子绕组的反电动势过零点来判
  • Ubuntu20.04用D435i运行VINS-Mono

    Ubuntu20 04用D435i运行VINS Mono 一 安装VINS Mono1 首先安装需要的ros包 xff0c 如果安装的是完整ros xff0c 应该是都安装过的2 安装ceres solver xff0c 进VINS Mon
  • 计算机核心期刊新排名(八大学报)

    八大学报 1 计算机学报 2 软件学报 3 计算机科学与技术学报 xff08 JCST xff09 4 计算机研究与发展 5 自动化学报 6 电子学报 7 通信学报 8 中国科学 被SCI检索的国外期刊 xff08 顶级会议 xff09 新
  • 以操作系统的角度述说线程与进程

    什么是线程 什么是线程 xff1f 线程与进程与有什么关系 xff1f 这是一个非常抽象的问题 xff0c 也是一个特别广的话题 xff0c 涉及到非常多的知识 我不能确保能把它讲的话 xff0c 也不能确保讲的内容全部都正确 即使这样 x
  • liunx 服务器升级 nodejs

    liunx 服务器升级 nodejs nodejs下载 linux x64 或 linux x32 的包 最新版本 https nodejs org zh cn 以往版本 https nodejs org zh cn download re
  • 开始LeetCode算法篇,一切不晚

    越来越 感觉自己知识的匮乏 xff0c 代码写得越来越多 xff0c 但感觉会的越来越少 最近项目开始 xff0c 感觉自己什么都做 xff0c 从前端html xff0c css xff0c js xff0c jquery xff0c a
  • keil去掉蓝色标签:ctrl+shift+F2

    keil去掉蓝色标签 xff1a ctrl 43 shift 43 F2
  • 小白首次PX4源码思路梳理,待更新...

    PX4版本 xff1a Firmware 1 10 2 xff08 ubuntu终端下载 xff09 1 我们首先打开Firmware 1 10 2 src modules mc att control文件夹下的mc att control
  • PX4源码分析__uorb通信机制__如何发布自己的数据?如何接收?

    一 创建流程 xff1a 1 在Firmware msg下创建msg文件 xff0c 例 xff1a xxx msg xff0c 内容格式仿照原有msg文件 2 在Firmware msg CMakeLists txt中将对应的msg文件添
  • PX4源码分析__传感器数据“sensor_combined”的来龙去脉

    注 xff1a 本讲解基于V1 10 2源码版本 一 sensor combined 的来源 module cpp src templates module line 166 struct sensor combined s sensor
  • PX4源码分析1:如何分析PX4源代码?

    问 xff1a PX4源代码复杂难懂 xff0c 如何分析才能让思路更清晰呢 xff1f Created with Rapha l 2 2 0 分析PX4系统流程图 理解每个子模块的角色
  • EVE-NG镜像资源

    链接 https pan baidu com s 1R1Ed55Ubj8Sg9IWQHYpwxw 提取码 x3sj
  • 循环神经网络(RNN)的原理及实现

    在前馈神经网络中 xff0c 信息的传递是单向的 xff0c 这种限制虽然使得网络变得更容易学习 xff0c 但在一定程度上也减弱了神经网络模型的能力 在生物神经网络中 xff0c 神经元之间的连接关系要复杂的多 前馈神经网络可以看着是一个