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))
目录
相关文章
|
15天前
|
机器学习/深度学习 人工智能 算法
基于Python深度学习的眼疾识别系统实现~人工智能+卷积网络算法
眼疾识别系统,本系统使用Python作为主要开发语言,基于TensorFlow搭建卷积神经网络算法,并收集了4种常见的眼疾图像数据集(白内障、糖尿病性视网膜病变、青光眼和正常眼睛) 再使用通过搭建的算法模型对数据集进行训练得到一个识别精度较高的模型,然后保存为为本地h5格式文件。最后使用Django框架搭建了一个Web网页平台可视化操作界面,实现用户上传一张眼疾图片识别其名称。
74 4
基于Python深度学习的眼疾识别系统实现~人工智能+卷积网络算法
|
1月前
|
机器学习/深度学习 人工智能 算法
猫狗宠物识别系统Python+TensorFlow+人工智能+深度学习+卷积网络算法
宠物识别系统使用Python和TensorFlow搭建卷积神经网络,基于37种常见猫狗数据集训练高精度模型,并保存为h5格式。通过Django框架搭建Web平台,用户上传宠物图片即可识别其名称,提供便捷的宠物识别服务。
288 55
|
2月前
|
Python
Python中的异步编程:使用asyncio和aiohttp实现高效网络请求
【10月更文挑战第34天】在Python的世界里,异步编程是提高效率的利器。本文将带你了解如何使用asyncio和aiohttp库来编写高效的网络请求代码。我们将通过一个简单的示例来展示如何利用这些工具来并发地处理多个网络请求,从而提高程序的整体性能。准备好让你的Python代码飞起来吧!
116 2
|
1月前
|
机器学习/深度学习 人工智能 算法
【宠物识别系统】Python+卷积神经网络算法+深度学习+人工智能+TensorFlow+图像识别
宠物识别系统,本系统使用Python作为主要开发语言,基于TensorFlow搭建卷积神经网络算法,并收集了37种常见的猫狗宠物种类数据集【'阿比西尼亚猫(Abyssinian)', '孟加拉猫(Bengal)', '暹罗猫(Birman)', '孟买猫(Bombay)', '英国短毛猫(British Shorthair)', '埃及猫(Egyptian Mau)', '缅因猫(Maine Coon)', '波斯猫(Persian)', '布偶猫(Ragdoll)', '俄罗斯蓝猫(Russian Blue)', '暹罗猫(Siamese)', '斯芬克斯猫(Sphynx)', '美国斗牛犬
193 29
【宠物识别系统】Python+卷积神经网络算法+深度学习+人工智能+TensorFlow+图像识别
|
22天前
|
算法 网络协议 Python
探秘Win11共享文件夹之Python网络通信算法实现
本文探讨了Win11共享文件夹背后的网络通信算法,重点介绍基于TCP的文件传输机制,并提供Python代码示例。Win11共享文件夹利用SMB协议实现局域网内的文件共享,通过TCP协议确保文件传输的完整性和可靠性。服务器端监听客户端连接请求,接收文件请求并分块发送文件内容;客户端则连接服务器、接收数据并保存为本地文件。文中通过Python代码详细展示了这一过程,帮助读者理解并优化文件共享系统。
|
1月前
|
机器学习/深度学习 人工智能 算法
深度学习入门:用Python构建你的第一个神经网络
在人工智能的海洋中,深度学习是那艘能够带你远航的船。本文将作为你的航标,引导你搭建第一个神经网络模型,让你领略深度学习的魅力。通过简单直观的语言和实例,我们将一起探索隐藏在数据背后的模式,体验从零开始创造智能系统的快感。准备好了吗?让我们启航吧!
90 3
|
2月前
|
网络安全 Python
Python网络编程小示例:生成CIDR表示的IP地址范围
本文介绍了如何使用Python生成CIDR表示的IP地址范围,通过解析CIDR字符串,将其转换为二进制形式,应用子网掩码,最终生成该CIDR块内所有可用的IP地址列表。示例代码利用了Python的`ipaddress`模块,展示了从指定CIDR表达式中提取所有IP地址的过程。
68 6
|
2月前
|
机器学习/深度学习 自然语言处理 语音技术
Python在深度学习领域的应用,重点讲解了神经网络的基础概念、基本结构、训练过程及优化技巧
本文介绍了Python在深度学习领域的应用,重点讲解了神经网络的基础概念、基本结构、训练过程及优化技巧,并通过TensorFlow和PyTorch等库展示了实现神经网络的具体示例,涵盖图像识别、语音识别等多个应用场景。
91 8
|
2月前
|
数据采集 XML 存储
构建高效的Python网络爬虫:从入门到实践
本文旨在通过深入浅出的方式,引导读者从零开始构建一个高效的Python网络爬虫。我们将探索爬虫的基本原理、核心组件以及如何利用Python的强大库进行数据抓取和处理。文章不仅提供理论指导,还结合实战案例,让读者能够快速掌握爬虫技术,并应用于实际项目中。无论你是编程新手还是有一定基础的开发者,都能在这篇文章中找到有价值的内容。
|
2月前
|
机器学习/深度学习 人工智能 算法
基于Python深度学习的【垃圾识别系统】实现~TensorFlow+人工智能+算法网络
垃圾识别分类系统。本系统采用Python作为主要编程语言,通过收集了5种常见的垃圾数据集('塑料', '玻璃', '纸张', '纸板', '金属'),然后基于TensorFlow搭建卷积神经网络算法模型,通过对图像数据集进行多轮迭代训练,最后得到一个识别精度较高的模型文件。然后使用Django搭建Web网页端可视化操作界面,实现用户在网页端上传一张垃圾图片识别其名称。
111 0
基于Python深度学习的【垃圾识别系统】实现~TensorFlow+人工智能+算法网络

热门文章

最新文章