Python-Tensorflow-循环神经网络

简介: Python-Tensorflow-循环神经网络

循环神经网络(Recurrent Neural Network,RNN)很多实时情况都能通过时间序列模型来描述。

例如,如果你想写一个文档,单词的顺序很重要,当前的单词肯定取决于以前的单词。如果把注意力放在文字写作上...一个单词中的下一个字符取决于之前的字符(例如,The quick brown f...,下一个字母是 o 的概率很高),如下图所示。关键思想是在给定上下文的情况下产生下一个字符的分布,然后从分布中取样产生下一个候选字符:

image.png

图 1 关于“The quick brown fox”句子的预测示例

一个简单的变体是存储多个预测值,并创建一个预测扩展树,如下图所示:

image.png

图 2 关于“The quick brown fox”句子的预测树示例

基于序列的模型可以用在很多领域中。在音乐中,一首曲子的下一个音符肯定取决于前面的音符,而在视频领域,电影中的下一帧肯定与先前的帧有关。此外,在某些情况下,视频的当前帧、单词、字符或音符不仅仅取决于过去的信号,而且还取决于未来的信号。

基于时间序列的模型可以用RNN来描述,其中,时刻 i 输入为 Xi,输出为 Yi,时刻 [0,i-1] 区间的状态信息被反馈至网络。这种反馈过去状态的思想被循环描述出来,如下图所示:

image.png

图 3 反馈的描述

展开(unfolding)网络可以更清晰地表达循环关系,如下图所示:

image.png

图 4 循环单元的展开

最简单的 RNN 单元由简单的 tanh 函数组成,即双曲正切函数,如下图所示:

image.png

图 5 简单的 tanh 单元

梯度消失与梯度爆炸


由于存在两个稳定性问题,训练 RNN 是很困难的。由于反馈环路的缘故,梯度可以很快地发散到无穷大,或者迅速变为 0。如下图所示:

image.png

图 6 梯度示例

在这两种情况下,网络将停止学习任何有用的东西。梯度爆炸的问题可以通过一个简单的策略来解决,就是梯度裁剪。梯度消失的问题则难以解决,它涉及更复杂的 RNN 基本单元(例如长短时记忆(LSTM)网络或门控循环单元(GRU))的定义。先来讨论梯度爆炸和梯度裁剪:

梯度裁剪包括对梯度限定最大值,以使其不能无界增长。如下图所示,该方法提供了一个解决梯度爆炸问题的简单方案:

image.png

图 7 梯度裁剪示例

解决梯度消失需要一个更复杂的记忆模型,它可以有选择地忘记以前的状态,只记住真正重要的状态。如下图所示,将输入以概率 p∈[0,1] 写入记忆块 M,并乘以输入的权重。

以类似的方式,以概率 p∈[0,1] 读取输出,并乘以输出的权重。再用一个概率来决定要记住或忘记什么:

image.png

图 8 记忆单元示例

长短时记忆网络(LSTM)


长短时记忆网络可以控制何时让输入进入神经元,何时记住之前时序中学到的东西,以及何时让输出传递到下一个时间戳。所有这些决策仅仅基于输入就能自我调整。

乍一看,LSTM 看起来很难理解,但事实并非如此。我们用下图来解释它是如何工作的:

image.png

图 9 一个 LSTM 单元的示例

首先,需要一个逻辑函数 σ 计算出介于 0 和 1 之间的值,并且控制哪个信息片段流经 LSTM 门。请记住,logisitic 函数是可微的,所以它允许反向传播。

然后需要一个运算符 ⊗ 对两个相同维数的矩阵进行点乘产生一个新矩阵,其中新矩阵的第 ij 个元素是两个原始矩阵第 ij 个元素的乘积。同样,需要一个运算符 ⊕ 将两个相同维数的矩阵相加,其中新矩阵的第 ij 个元素是两个原始矩阵第 ij 个元素的和。在这些基本模块中,将 i 时刻的输入 xi 与前一步的输出 yi放在一起。

方程 fi=σ(Wf·[yi-1,xi]+bf) 是逻辑回归函数,通过控制激活门 ⊗ 决定前一个单元状态 Ci-1 中有多少信息应该传输给下一个单元状态 Ci(Wf 是权重矩阵,bf是偏置)。逻辑输出 1 意味着完全保留先前单元状态 Ct-1,输出 0 代表完全忘记 Ci-1 ,输出(0,1)中的数值则代表要传递的信息量。

接着,方程根据当前输入产生新信息,方程 si=σ(Wc·[Yi-1,Xi]+bc) 则能控制有多少新信息通过运算符 ⊕ 被加入到单元状态 Ci 中。利用运算符 ⊗ 和 ⊕,给出公式对单元状态进行更新。

最后,需要确定当前单元状态的哪些信息输出到 Yi。很简单,再次采用逻辑回归方程,通过 ⊗ 运算符控制候选值的哪一部分应该输出。在这里有一点需要注意,单元状态是通过 tanh 函数压缩到 [-1,1]。这部分对应的方程是 Yi=ti*tanh(Ci)。

这看起来像很多数学理论,但有两个好消息。首先,如果你明白想要达到的目标,那么数学部分就不是那么难;其次,你可以使用 LSTM 单元作为标准 RNN 元的黑盒替换,并立即解决梯度消失问题。因此你真的不需要知道所有的数学理论,你只需从库中取出 TensorFlow LSTM 并使用它。

门控循环单元和窥孔LSTM


近年来已经提出了许多 LSTM 的变种模型,其中有两个很受欢迎:窥孔(peephole)LSTM 允许门层查看单元状态,如下图中虚线所示;而门控循环单元(GRU)将隐藏状态和单元状态合并为一个信息通道。

同样,GRU 和窥孔 LSTM 都可以用作标准 RNN 单元的黑盒插件,而不需要知道底层数学理论。这两种单元都可以用来解决梯度消失的问题,并用来构建深度神经网络。

image.png

图 10 标准LTSM、窥孔LTSM、GRU示例

处理向量序列


真正使 RNN 强大的是它能够处理向量序列,其中 RNN 的输入和输出可以是序列,下图很好地说明了这一点,最左边的例子是一个传统(非递归)网络,后面跟着一个序列输出的 RNN,接着跟着一个序列输入的 RNN,其次跟着序列输入和序列输出不同步的 RNN,最后是序列输入和序列输出同步的 RNN。

image.png

图 11 RNN序列示例

机器翻译是输入序列和输出序列中不同步的一个例子:网络将输入文本作为一个序列读取,读完全文后输出目标语言。

视频分类是输入序列和输出序列同步的一个例子:视频输入是一系列帧,对于每一帧,在输出中提供分类标签。

长短期记忆网络(LSTM)


LSTM的网络机构图如下所示:

image.png

LSTM的网络结构


与传统的循环神经网络相比,LSTM仍然是基于xt和ht−1来计算ht,只不过对内部的结构进行了更加精心的设计,加入了输入门it 、遗忘门ft以及输出门ot三个门和一个内部记忆单元ct。输入门控制当前计算的新状态以多大程度更新到记忆单元中;遗忘门控制前一步记忆单元中的信息有多大程度被遗忘掉;输出门控制当前的输出有多大程度上取决于当前的记忆单元。

在经典的LSTM模型中,第t层的更新计算公式为

image.png

每层输出的信息的计算公式

其中it是通过输入xt和上一步的隐含层输出ht−1进行线性变换,再经过激活函数σ得到的。输入门it的结果是向量,其中每个元素是0到1之间的实数,用于控制各维度流过阀门的信息量;Wi 、Ui两个矩阵和向量bi为输入门的参数,是在训练过程中需要学习得到的。遗忘门ft和输出门ot的计算方式与输入门类似,它们有各自的参数W、U和b。与传统的循环神经网络不同的是,从上一个记忆单元的状态ct−1到当前的状态ct的转移不一定完全取决于激活函数计算得到的状态,还由输入门和遗忘门来共同控制。

在一个训练好的网络中,当输入的序列中没有重要信息时,LSTM的遗忘门的值接近于1,输入门的值接近于0,此时过去的记忆会被保存,从而实现了长期记忆功能;当输入的序列中出现了重要的信息时,LSTM应当把其存入记忆中,此时其输入门的值会接近于1;当输入的序列中出现了重要信息,且该信息意味着之前的记忆不再重要时,输入门的值接近1,而遗忘门的值接近于0,这样旧的记忆被遗忘,新的重要信息被记忆。经过这样的设计,整个网络更容易学习到序列之间的长期依赖。

下面跑一下简单的循环神经网络的代码,同样以手写识别为例:

import os
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
#读取mnist数据集 如果没有则会下载
mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)
#输入图片是28*28
n_inputs = 28 #输入一行,一行有28个数据
max_time = 28 #一共28行
lstm_size = 100 #隐藏单元
n_classes = 10 #10个分类
batch_size = 50 #每批次50个样本
n_batch = mnist.train.num_examples//batch_size #计算一共多少批次
#这里表示第一个维度可以是任意的长度
x = tf.placeholder(tf.float32,[None,784])
#正确的标签
y = tf.placeholder(tf.float32,[None,10])
#初始化权值
weights = tf.Variable(tf.truncated_normal([lstm_size,n_classes],stddev=0.1))
#初始化偏置值
biases = tf.Variable(tf.constant(0.,shape=[n_classes]))
#定义RNN网络
def RNN(X, weights, biases):
    # inputs=[batch_size, max_time, n_inputs]
    inputs = tf.reshape(X, [-1, max_time, n_inputs])
    # 定义LSTM基本CELL
    lstm_cell = tf.contrib.rnn.BasicLSTMCell(lstm_size)
    # final_state[0]是cell state
    # final_state[1]是hidden_state
    outputs, final_state = tf.nn.dynamic_rnn(lstm_cell, inputs, dtype=tf.float32)
    results = tf.nn.softmax(tf.matmul(final_state[1], weights) + biases)
    return results
#计算RNN的返回结果
prediction = RNN(x,weights,biases)
#损失函数
cross_entropy = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=prediction,labels=y))
#使用AdamOptimizer进行优化
train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)
#结果存放在一个布尔型的列表中
correct_prediction = tf.equal(tf.argmax(y,1),tf.argmax(prediction,1))#argmax返回一维张量中最大值所在位置
#求准确率
accuracy = tf.reduce_mean(tf.cast(correct_prediction,tf.float32))
#初始化
init = tf.global_variables_initializer()
# 进行训练
with tf.Session() as sess:
    sess.run(init)
    for epoch in range(6):  # 周期
        for batch in range(n_batch):  # 批次
            batch_xs, batch_ys = mnist.train.next_batch(batch_size)
            sess.run(train_step, feed_dict={x: batch_xs, y: batch_ys})
        acc = sess.run(accuracy, feed_dict={x: mnist.test.images, y: mnist.test.labels})
        print("周期 :" + str(epoch) + "准确率:" + str(acc))
目录
相关文章
|
4月前
|
运维 监控 数据可视化
Python 网络请求架构——统一 SOCKS5 接入与配置管理
通过统一接入端点与标准化认证,集中管理配置、连接策略及监控,实现跨技术栈的一致性网络出口,提升系统稳定性、可维护性与可观测性。
|
7月前
|
机器学习/深度学习 算法 量子技术
GQNN框架:让Python开发者轻松构建量子神经网络
为降低量子神经网络的研发门槛并提升其实用性,本文介绍一个名为GQNN(Generalized Quantum Neural Network)的Python开发框架。
163 4
GQNN框架:让Python开发者轻松构建量子神经网络
|
4月前
|
机器学习/深度学习 大数据 关系型数据库
基于python大数据的青少年网络使用情况分析及预测系统
本研究基于Python大数据技术,构建青少年网络行为分析系统,旨在破解现有防沉迷模式下用户画像模糊、预警滞后等难题。通过整合多平台亿级数据,运用机器学习实现精准行为预测与实时干预,推动数字治理向“数据驱动”转型,为家庭、学校及政府提供科学决策支持,助力青少年健康上网。
|
5月前
|
JavaScript Java 大数据
基于python的网络课程在线学习交流系统
本研究聚焦网络课程在线学习交流系统,从社会、技术、教育三方面探讨其发展背景与意义。系统借助Java、Spring Boot、MySQL、Vue等技术实现,融合云计算、大数据与人工智能,推动教育公平与教学模式创新,具有重要理论价值与实践意义。
|
6月前
|
运维 Linux 开发者
Linux系统中使用Python的ping3库进行网络连通性测试
以上步骤展示了如何利用 Python 的 `ping3` 库来检测网络连通性,并且提供了基本错误处理方法以确保程序能够优雅地处理各种意外情形。通过简洁明快、易读易懂、实操性强等特点使得该方法非常适合开发者或系统管理员快速集成至自动化工具链之内进行日常运维任务之需求满足。
385 18
|
7月前
|
JSON 网络安全 数据格式
Python网络请求库requests使用详述
总结来说,`requests`库非常适用于需要快速、简易、可靠进行HTTP请求的应用场景,它的简洁性让开发者避免繁琐的网络代码而专注于交互逻辑本身。通过上述方式,你可以利用 `requests`处理大部分常见的HTTP请求需求。
619 51
|
6月前
|
数据采集 存储 数据可视化
Python网络爬虫在环境保护中的应用:污染源监测数据抓取与分析
在环保领域,数据是决策基础,但分散在多个平台,获取困难。Python网络爬虫技术灵活高效,可自动化抓取空气质量、水质、污染源等数据,实现多平台整合、实时更新、结构化存储与异常预警。本文详解爬虫实战应用,涵盖技术选型、代码实现、反爬策略与数据分析,助力环保数据高效利用。
366 0
|
7月前
|
存储 监控 算法
基于 Python 跳表算法的局域网网络监控软件动态数据索引优化策略研究
局域网网络监控软件需高效处理终端行为数据,跳表作为一种基于概率平衡的动态数据结构,具备高效的插入、删除与查询性能(平均时间复杂度为O(log n)),适用于高频数据写入和随机查询场景。本文深入解析跳表原理,探讨其在局域网监控中的适配性,并提供基于Python的完整实现方案,优化终端会话管理,提升系统响应性能。
204 4
|
9月前
|
调度 Python
探索Python高级并发与网络编程技术。
可以看出,Python的高级并发和网络编程极具挑战,却也饱含乐趣。探索这些技术,你将会发现:它们好比是Python世界的海洋,有穿越风暴的波涛,也有寂静深海的奇妙。开始旅途,探索无尽可能吧!
230 15
|
9月前
|
机器学习/深度学习 算法 测试技术
图神经网络在信息检索重排序中的应用:原理、架构与Python代码解析
本文探讨了基于图的重排序方法在信息检索领域的应用与前景。传统两阶段检索架构中,初始检索速度快但结果可能含噪声,重排序阶段通过强大语言模型提升精度,但仍面临复杂需求挑战
300 0
图神经网络在信息检索重排序中的应用:原理、架构与Python代码解析

推荐镜像

更多